本教程介绍了tf.contrib.learn
中的输入函数,我们将首先学习如何建立一个input_fn
来预处理数据并且把它们送入模型中训练、评估或测试。接着我们将运用input_fn
构造一个神经网络回归器用来预测房价。
教程地址:https://www.tensorflow.org/get_started/input_fn
使用input_fn的输入方法
当我们用tf.contrib.learn
来训练一个神经网络时,我们可以直接把特征数据和标签数据送入fit
、evaluate
或predict
操作中。如下例子是我们上篇教程中用到的方法:
|
|
当我们对源数据操作较小时,这种方法很好。但如果我们需要大量的特征工程,我们可以使用输入函数input_fn
来进行数据预处理的操作。
input_fn结构
如下代码显示了一个输入函数的基本框架:
|
|
函数主体包含了对输入数据的预处理操作,例如清除异常点等。输入函数必须返回如下两个值:
feature_cols
:一个包含了键值对的字典,把特征名映射到对应的Tensor
上,该Tensor
包含了特征数据。labels
:一个包含了标签数据的Tensor
把特征数据转化为Tensors
如果在input_fn
函数中,我们的特征数据或标签数据保存在pandas dataframes
或者numpy arrays
里面,我们需要把它们转化为Tensor
返回。
对于连续数据,我们可以用tf.constant
创建一个Tensor
:
|
|
对于稀疏矩阵数据(大部分值为0),我们可以使用SparseTensor
,一般来说我们用三个参数来实例化一个SparseTensor
:
dense_shape
:tensor
的形状,用一个列表来表示每个维度的元素的个数,例如dense_shape=[3,5]
表示一个二维的tensor
,有3行5列;而dense_shape=[9]
表示一个一维的tensor
,有9个元素。indices
:表示tensor
中非0值的位置。用一个嵌套列表来表示,每个嵌套列表代表一个非0值所在的位置。例如indices=[[0,1], [2,4]]
表示在tensor
中第0行第1个元素和第2行第4个元素为非零值。values
:一维tensor
,values
中的第i个值位于在indices
中第i个值表示的位置上。例如下面的例子,表示在第0行第1个元素为6,第2行第4个元素为0.5。
|
|
对应的tensor
为:
|
|
把input_fn送入模型中
为了把数据送入模型进行训练,我们只需要把创建的输入函数赋值给fit
的input_fn
参数即可:
|
|
注意input_fn
会把特征数据和标签数据一起送入模型中,它代替了fit
中的x
和y
参数,如果我们同时保留了input_fn
和x
或者y
,程序会报错。
同时需要注意的是input_fn
参数必须接受一个函数名(input_fn=my_input_fn
)而不是接受一个函数调用(input_fn=my_input_fn()
)。这意味着如果我们尝试在fit
函数的参数中使用一个函数调用,如下代码,将会报错。
|
|
不过如果我们想让我们的输入函数具有输入参数,第一个方法是用另一个无参数函数包含它,然后用该函数名作为input_fn
的值,这样我们就可以在内层函数送入我们需要的参数。例如:
|
|
第二个方法是使用python内置的偏函数functools.partial
来实现上述功能,它会建立一个新的函数同时把所有的参数固定住:
|
|
第三个方法我们可以使用lambda
操作:
|
|
上述三个方法最大的优点是我们可以把同一个input_fn
送到evaluate
和predict
操作上,而只需要修改内层函数的输入参数即可:
|
|
这些方法增强了代码的可操作性,我们不需要对每个操作都分别获取x
和y
的值并用两个变量表示出来,如 x_train
, x_test
, y_train
, y_test
。
补充
关于functools.partial()
:
如果某一个函数的其中一个输入参数始终固定,而我们每次调用该函数都要输入一次就显得很没有必要,于是我们就可以对该函数进行封装,使得输入参数减少。用到的函数就是functools.partial()
。举个例子:
|
|
如果我们的key1
在使用过程中始终是固定的,而只有key2
是变化的,如:
|
|
这时候我们就可以固定key1
的值,对input1()
进行封装:
|
|
这样我们就可以很方便的使用该函数:
|
|
输出a,b,c
的值得到:
|
|
波士顿房价神经网络模型
接下来我们将携一个输入函数来预处理波士顿房价数据,然后我们把处理后的数据送入神经网络回归器中进行训练,进而预测房价中位数。
我们要用到的数据集的CSV文件包含以下特征:
Feature | Description |
---|---|
CRIM | Crime rate per capita |
ZN | Fraction of residential land zoned to permit 25,000+ sq ft lots |
INDUS | Fraction of land that is non-retail business |
NOX | Concentration of nitric oxides in parts per 10 million |
RM | Average Rooms per dwelling |
AGE | Fraction of owner-occupied residences built before 1940 |
DIS | Distance to Boston-area employment centers |
TAX | Property tax rate per $10,000 |
PTRATIO | Student-teacher ratio |
模型预测的标签是MEDV,表示房价的中位数,以千美元为计数单位。
通过以下链接下载数据集:
- 训练数据:boston_train.csv
- 测试数据:boston_test.csv
- 预测数据:boston_predict.csv
接下来我们将依次介绍如何创建一个输入函数,把它们送入神经网络回归器中,训练并评估模型,进行房价预测。
引入房价数据
首先我们需要引入必要的库,包括pandas
和tensorflow
,同时我们利用set_verbosity
来获得更多的输出信息。
|
|
关于logging
我们将在下个笔记中介绍,简单来说我们在代码开始(import
之后)加上这行代码,训练过程将打印出详细的loss
信息和step
信息,可以更好的监控整个训练过程。
因为我们是使用pandas
来倒入CSV数据,所以在此之前先定义好column
的名字,以及特征名和标签名。
|
|
因为第一行是关于数据的介绍,所以我们在这里跳过第一行,用skiprows=1
。
定义FeatureColumns并创建回归器
接下来我们创建一系列FeatureColumn
来组成特征数据。每个FeatureColumn
表示一个特征,根据数据类型的不同用相应的函数创建,更详细内容可以看以下两个参考链接:
- 所有函数类型:Layers (contrib) | TensorFlow,
- 特征是分类数据(categorical data)的例子:TensorFlow Linear Model Tutorial | TensorFlow。
因为本数据集所有的特征都是连续值,所以我们可以用tf.contrib.layers.real_valued_column()
函数来创建,函数输入是特征的名字,这和下面的input_fn()
函数相对应。
|
|
接下来,我们将实例化一个DNNRegressor
,我们需要提供两个参数,一个hidden_units
,它是用来定义隐藏层神经元个数的超参数,这里我们用两层各10个神经元;另一个是feature_columns
,即我们刚刚定义的FeatureColumns
的列表。
|
|
建立input_fn
为了把输入数据送入regressor
中,我们要创建一个输入函数,它接受一个pandas
的Datafram
同时返回包含特征信息和标签信息的两个Tensor
:
|
|
注意data_set[k].values
将返回一个numpy array
,feature_cols
是一个字典。input_fn()
函数将对data_set
进行处理,这意味着我们可以把任何我们需要的DataFrame
送入该函数中,包括training_set
、test_set
和 prediction_set
。
训练回归器
训练神经网络回归器,我们只需要执行fit
方法,然后把training_set
送入input_fn
中:
|
|
我们将会看到打印出的训练信息,每100步迭代打印一次训练损失:
|
|
评估模型
借下来我们在测试集上评估训练好的模型,执行evaluate
指令,这次把test_set
送入input_fn
函数:
|
|
打印出损失的确切值:
|
|
可以看到以下输出:
|
|
进行预测
最后,我们可以用训练好的模型来进行房价的预测,这里我们使用的数据集是prediction_set
,共有6个样本,包含了特征数据但是没有包含标签数据。
|
|
结果输出如下:
|
|
结果给出了六个样本的预测房价。
参考
- Building Input Functions with tf.contrib.learn | TensorFlow
- 飘逸的python - 偏函数functools.partial - mattkang - CSDN博客
- Logging and Monitoring Basics with tf.contrib.learn | TensorFlow