tf.estimator.BoostedTreesClassifier

大纲

  1. 代码实践
  2. 待解决的问题

1. 代码实践

本文尝试了tensorflow自带的BoostedTreesClassifier API。

import os
import sys
import pandas as pd
import numpy as np
import time
import json 

# pylint: disable=wrong-import-order
from absl import app as absl_app
from absl import flags
from six.moves import urllib
import tensorflow as tf

搭建特征

class DataPreprocesser(object):
    def __init__(self, train_file):
        self.train_file = train_file
        self.categorical_columns = cols 
        self._categorical_column_vocab()
    
    def _categorical_column_vocab(self):
        self.train_data, labels = data_preprocess(self.train_file, train=True)
        self.categorical_vocabs = {}
        for feature in self.categorical_columns:
            vocab = list(self.train_data[feature].dropna().unique())
            print (feature, vocab[:10])
            self.categorical_vocabs[feature] = vocab

    def build_model_columns(self):
        feature_columns = []
        for feature in real_data_columns:
            if feature in self.categorical_columns:
                _column = tf.feature_column.categorical_column_with_vocabulary_list(feature, self.categorical_vocabs[feature])
                feature_columns.append(tf.feature_column.indicator_column(_column))
            else:
                _column = tf.feature_column.numeric_column(feature)
                if feature == "house_month_ctr":
                    _bucket_ranges = [i/100.0 for i in range(2500)]
                else:
                    continue
                feature_columns.append(tf.feature_column.bucketized_column(_column, _bucket_ranges))
         return feature_columns

搭建模型

这里用了tf.estimator.LinearClassifier做baseline

def build_estimator(model_dir, model_type, model_column_fn, inter_op, intra_op):
  """Build an estimator appropriate for the given model type."""
  feature_columns = model_column_fn()
  if os.path.isdir(model_dir):
      shutil.rmtree(model_dir)
  os.makedirs(model_dir)

  # Create a tf.estimator.RunConfig to ensure the model is run on CPU, which
  # trains faster than GPU for this model.
  run_config = tf.estimator.RunConfig().replace(
      session_config=tf.ConfigProto(device_count={'GPU': 0},
                                    inter_op_parallelism_threads=inter_op,
                                    intra_op_parallelism_threads=intra_op))
  print ("model_type: %s" % model_type)
  if model_type == 'lr':
    return tf.estimator.LinearClassifier(
        model_dir=model_dir,
        feature_columns=feature_columns,
        #optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.01),
        #optimizer=tf.train.FtrlOptimizer(learning_rate=0.01),
        optimizer=tf.train.AdamOptimizer(learning_rate=0.001),
        config=run_config)
  else:
    return tf.estimator.BoostedTreesClassifier(
        feature_columns=feature_columns,
        n_batches_per_layer=50, #0.5 * NUM_EXAMPLES / BATCH_SIZE
        model_dir=model_dir,
        n_classes=2,
        n_trees=100,
        max_depth=6,
        learning_rate=0.1,
        l1_regularization=0.,
        l2_regularization=0.,
        config=run_config)

准备数据

def data_preprocess(data_file, train=False):
    data = pd.read_csv(data_file, names=all_feature_columns, low_memory=False)
    data.sort_values("query_id", inplace=True)
    data.replace(-1, pd.NaT, inplace=True)
    data.replace("-1", pd.NaT, inplace=True)
    if train:
        data.dropna(thresh=25, inplace=True)
    data = data[real_data_columns]
    labels = data["label"].astype(int)
    del data['label'] #删除之后就是训练集
    del data["query_id"]
    for col in cols:
        if data[col].dtype != np.str:
            data[col] = data[col].astype("str")
    print ("data shape:", data.shape)
    return data, labels

def input_fn(data_file, num_epochs, shuffle, batch_size, train=False):
    data, labels = data_preprocess(data_file, train)
    data_columns = data.columns.values.tolist()
    return tf.estimator.inputs.pandas_input_fn(
            x=data,
            y=labels,
            batch_size=batch_size,
            num_epochs=num_epochs,
            shuffle=shuffle,
            num_threads=5)

训练模型

def run_loop(train_input_fn, eval_input_fn, model_column_fn,
        build_estimator_fn, flags_obj):
  model = build_estimator_fn(
      model_dir=flags_obj.model_dir, model_type=flags_obj.model_type,
      model_column_fn=model_column_fn,
      inter_op=0,
      intra_op=0)

  # Train and evaluate the model every `flags.epochs_between_evals` epochs.
  for n in range(flags_obj.train_epochs // flags_obj.epochs_between_evals):
    print ("============================")
    model.train(input_fn=train_input_fn)
    print ("============================")

    results = model.evaluate(input_fn=eval_input_fn)

    for key in sorted(results):
      print("%s: %s" % (key, results[key]))

程序入口

def main(_):
  train_file = "./data_dir/20190316_data.csv"
  test_file = "./data_dir/20190317_data_eval.csv"
  flags_obj = FLAGS

  dp = data_preprocesser.DataPreprocesser(train_file)
  run_loop(train_input_fn=data_preprocesser.input_fn(train_file, num_epochs=2, shuffle=True, batch_size=32),
          eval_input_fn=data_preprocesser.input_fn(test_file, 1, False, batch_size=32),
          model_column_fn=dp.build_model_columns,
          build_estimator_fn=build_estimator,
          flags_obj=flags_obj) 


if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.register("type", "bool", lambda v: v.lower() == "true")
  parser.add_argument(
      "--model_dir",
      type=str,
      default="./model_dir",
      help="Base directory for output models."
  )
  parser.add_argument(
      "--model_type",
      type=str,
      default="lr",
      help="Valid model types: {'lr', 'boosted_tree'}."
  )
  parser.add_argument(
      "--train_epochs",
      type=int,
      default=2,
      help="Number of training epochs."
  )
  parser.add_argument(
      "--epochs_between_evals",
      type=int,
      default=2,
      help="Number of eval epochs."
  )
  parser.add_argument(
      "--batch_size",
      type=int,
      default=256,
      help="batch_size."
  )
  parser.add_argument(
      "--train_data",
      type=str,
      default="",
      help="Path to the training data."
  )
  parser.add_argument(
      "--test_data",
      type=str,
      default="",
      help="Path to the test data."
  )
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

2. 待解决的问题

feature_column

目前用的是tensorflow1.12.0版本,tf.estimator.BoostedTreesClassifier只能支持tf.feature_column.indicator_column和tf.feature_column.bucketized_column,因此处理特征不灵活,模型效果下降。

训练速度

当数据量增大后,性能特别慢。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容