李里:TensorFlow除了比较复杂的Low Level API外还提供了可以极大简化机器学习编程的高阶API,称之为Estimator。Estimator提供了诸如训练,评估,预测,导出保存等操作,用户可以使用预创建的Estimator,也可以编写自定义Estimator。所有的Estimator无论是预创建还是自定义都是基于tf.estimator.Estimator这个基类派生出来的。
Estimator 具有下列优势:
- 可以在本地主机上或分布式多服务器环境中运行基于 Estimator 的模型,而无需更改模型。此外,还可以在 CPU、GPU 或 TPU 上运行基于 Estimator 的模型,而无需重新编码模型。
- Estimator 实现了模型在多开发者之间实现共享。
- 采用 Estimator 创建模型通常比采用Low Level TensorFlow API 更简单,更易懂。
- Estimator 本身在 tf.layers 之上构建而成,可以简化自定义过程。
- Estimator 不必构建计算图。
- Estimator 提供安全的分布式训练循环,可以控制如何以及何时:
- 构建计算图
- 初始化变量
- 开始排队
- 处理异常
- 创建检查点文件并从故障中恢复
- 保存 TensorBoard 的摘要
李里:先回顾一下Low Level API开发的步骤:数据准备,数据输入,训练,评估,存储。这里也从数据准备开始,看看如何使用Estimator API将训练数据准备好并填充到模型开始训练的。
Estimator模型通用训练框架示例:
#使用Estimator完成数据填充到模型
import tensorflow as tf #定义一个基础Estimator的输入模板 def my_input_fn(): #feature_cols为输入数据,以dict方式呈现 #格式为{name:data} #labels为结果数据 return feature_cols,labels
#使用Numpy进行填充 import numpy as np my_input_fn = tf.estimator.inputs.numpy_input_fn( x = {"x":np.array(x_data)}, y = np.array(y_data), )
#使用pandas进行填充 import pandas as pd my_input_fn = tf.estimator.inputs.pandas_input_fn( x = pd.DataFrame({"x" : x_data}), y = pd.Series(y_data), )
#将数据填充到模型,特别注意不是my_input_fn(),否则报错 classifier.train(input_fn=my_input_fn,steps=2000) |
李里:到这里会有个疑问,既然不能用参数初始化my_input_fn,有没有办法非要加入参数传递呢?请参考如下写法:
#将数据填充如模型,特别注意不是my_input_fn(),否则报错 classifier.train(input_fn=my_input_fn,steps=2000)
def my_param_input_fn(data_set): pass def my_input_fn_data_set(): return my_param_input_fn(data_set)
classifier.train(input_fn=my_input_fn_data_set,steps=2000) #或者采用lambda classifier.train(input_fn=lambda: my_param_input_fn(data_set),steps=2000) |
李里:下面用一个完整的预测波士顿房价的例子来的演示一下构建的训练集,验证集,预测集的如何填充到预测模型中,该程序也可以作为通用框架在今后的工作中直接套用
表3.5.4.1 为Boston数据集概要:
Boston_train.csv房价训练集
备注:这里需要注意Header的头两个字段是400和9,这里400指的是共400个组数据,9指指的是从CRIM到PTRATIO的共9个feature,最后一个栏位MEDV是Label也就是实际的房价。 |
Boston_test.csv房价验证集
|
Boston_predict.csv房价测试集
备注:房价测试集可以看到没有最后一栏MEDV了,也就是没有结果列了,需要自己去验证自己的模型是否准确。
|
表3.5.4.1 为Boston数据集概要
李里:下面开始建立深度网络模型,这里加入之前学到的Log输出以此查看模型训练的状态。
基于深度网络模型的训练,验证,预测代码框架:
#预测Boston 房价的模型 import pandas as pd import TensorFlow as tf tf.logging.set_verbosity(tf.logging.INFO) """ COLUMNS:所有栏位 FEATURES:影响房价的元素 LABEL:房价值 """ COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio", "medv"] FEATURES = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio"] LABEL = "medv"
train_set = pd.read_csv("./data/boston/boston_train.csv", skipinitialspace=True,skiprows=1,names=COLUMNS) test_set = pd.read_csv("./data/boston/boston_test.csv", skipinitialspace=True,skiprows=1, names=COLUMNS) prediction_set = pd.read_csv("./data/boston/boston_predict.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)
""" 构建feature_columns,这里应用各个栏位的名称作为索引, 若希望读取该feature_column的值可以采用 tf.contrib.layers.real_valued_column() """ feature_cols = [tf.feature_column.numeric_column(k) for k in FEATURES] """ 建立深度神经网络回归模型 参数: hidden_units:隐藏层的节点单元数,[10,10]代表2两层网络,每层10个节点 model_dir:生成模型存储路径 """ regressor=tf.estimator.DNNRegressor( feature_columns = feature_cols, hidden_units=[10,10], model_dir="./model/boston" )
""" 使用pandas Dataframe构造数据集 num_epochs:数据迭代次数,若设为None,在训练过程中会一直将数据 填充到训练集中直到结束,若是评估和预测则设为1,表示填充一次数据即可 """ def get_input_fn(data_set,num_epochs=None,shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame({k:data_set[k].values for k in FEATURES}), y=pd.Series(data_set[LABEL].values), num_epochs=num_epochs, shuffle=shuffle ) #训练 regressor.train(input_fn=get_input_fn(train_set),steps=5000) #评估 ev=regressor.evaluate(input_fn=get_input_fn(test_set,num_epochs=1, shuffle=False)) #打印Loss值 loss_score=ev["loss"] print("Loss:{0:f}".format(loss_score))
import itertools y = regressor.predict(input_fn=get_input_fn(prediction_set, num_epochs=1,shuffle=False)) predictions = list(p["predictions"] for p in itertools.islice(y, 6)) print("Predictions: {}".format(str(predictions)))
|
|
高维:这样倒是简单很多了,以后开发套用这个框架就可以了。
安逸:这个Estimator和您说的Keras都是Hi-LevelAPI,但它们之间有什么区别么?
李里:Keras可以直接转换为estimator,反之不行。并且estimator不仅包含了训练,预测等基本功能,还包含了发布服务、分布式、数据处理等整套服务,是一套比较完善的API。