Building Input Functions with tf.estimator(使用tf.estimator建立输入函数)

Building Input Functions with tf.estimator

本教程将向您介绍如何在tf.estimator中创建输入函数。您将了解如何构建一个input_fn预处理模型并将数据输入到模型中。然后,您将实施一项input_fn将训练,评估和预测数据输入到神经网络回归器以预测房屋中值的中值。

使用input_fn自定义输入管道

input_fn用于特征和目标数据传递给trainevaluateEstimatorpredict方法。用户可以在input_fn其中进行特征工程或预处理。以下是来自 tf.estimator 快速入门教程的示例:

import numpy as np training_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename=IRIS_TRAINING, target_dtype=np.int, features_dtype=np.float32) train_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": np.array(training_set.data)}, y=np.array(training_set.target), num_epochs=None, shuffle=True) classifier.train(input_fn=train_input_fn, steps=2000)

解剖一个input_fn

以下代码演示了输入函数的基本框架:

def my_input_fn(): # Preprocess your data here... # ...then return 1) a mapping of feature columns to Tensors with # the corresponding feature data, and 2) a Tensor containing labels return feature_cols, labels

输入函数的主体包含用于预处理输入数据的特定逻辑,例如清理不好的示例或特征缩放

输入函数必须返回以下两个值,其中包含要输入到模型中的最终特征和标签数据(如上面的代码框架所示):

feature_cols 一个包含键/值对的字典,可将要素列名映射到包含相应的要素数据的Tensors(或SparseTensors)。labelsA Tensor包含您的标签(目标)值:您的模型旨在预测的值。

将特征数据转换为张量

如果您的特征/标签数据是一个python数组或者存储在pandas数据框或numpy数组中,则可以使用以下方法构造input_fn

import numpy as np # numpy input_fn. my_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": np.array(x_data)}, y=np.array(y_data), ...)

import pandas as pd # pandas input_fn. my_input_fn = tf.estimator.inputs.pandas_input_fn( x=pd.DataFrame{"x": x_data}), y=pd.Series(y_data), ...)

对于稀疏的分类数据(大多数值为0的数据),您将改为填充一个使用三个参数实例化的SparseTensor数据:

dense_shape张量的形状。获取一个列表,指出每个维度中元素的数量。例如,dense_shape=[3,6]指定二维3x6张量,dense_shape=[2,3,4]指定三维2x3x4张量,并dense_shape=[9]指定具有9个元素的一维张量。indices张量中包含非零值的元素的索引。获取术语列表,其中每个术语本身都是包含非零元素索引的列表。(元素是零索引的 - 即,0,0是二维张量中第一行第一列元素的索引值)。例如,indices=[[1,3], [2,4]]指定索引为1,3和2的元素,4有非零值。values价值的一维张量。Term iin values对应于term i中的indices并指定其值。例如,给定indices=[[1,3], [2,4]]的参数values=[18, 3.6]指定张量的元素1,3的值为18,张量的元素2,4的值为3.6。

以下代码定义了SparseTensor3行5列的二维。索引为0,1的元素的值为6,索引为2,4的元素的值为0.5(所有其他值均为0):

sparse_tensor = tf.SparseTensor(indices=[[0,1], [2,4]], values=[6, 0.5], dense_shape=[3, 5])

这对应于以下稠密张量:

[[0, 6, 0, 0, 0] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0.5]]

For more on SparseTensor, see tf.SparseTensor.

将input_fn数据传递给您的模型

要将数据提供给您的模型进行培训,只需将您创建的输入函数train作为input_fn参数的值传递给您的操作,例如:

classifier.train(input_fn=my_input_fn, steps=2000)

请注意,该input_fn参数必须接收函数对象(即,input_fn=my_input_fn),而不是函数调用(input_fn=my_input_fn())的返回值。这意味着如果您尝试将参数传递给input_fn您的train调用中,如下面的代码所示,它将导致一个TypeError

classifier.train(input_fn=my_input_fn(training_set), steps=2000)

但是,如果您希望能够对输入函数进行参数化,还有其他方法可以这样做。你可以使用一个不带任何参数的包装函数,input_fn并用它来调用具有所需参数的输入函数。例如:

def my_input_fn(data_set): ... def my_input_fn_training_set(): return my_input_fn(training_set) classifier.train(input_fn=my_input_fn_training_set, steps=2000)

或者,您可以使用Python的functools.partial函数构建一个新的函数对象,并修复所有参数值:

classifier.train( input_fn=functools.partial(my_input_fn, data_set=training_set), steps=2000)

第三种选择是将您的input_fn调用包装在a lambda 中并将其传递给input_fn参数:

classifier.train(input_fn=lambda: my_input_fn(training_set), steps=2000)

如上所示设计输入管道的一大优势 - 接受数据集的参数 - 就是您可以通过更改数据集参数来传递相同input_fn内容到evaluatepredict的操作,例如:

classifier.evaluate(input_fn=lambda: my_input_fn(test_set), steps=2000)

这种方法提高了代码的可维护性:无需定义多个input_fn(例如input_fn_traininput_fn_testinput_fn_predict)对于每个类型的操作。

最后,您可以使用这些方法从numpy或pandas数据集tf.estimator.inputs创建input_fn。额外的好处是你可以使用更多的参数,比如num_epochsshuffle控制input_fn迭代数据的方式:

import pandas as pd def get_input_fn_from_pandas(data_set, num_epochs=None, shuffle=True): return tf.estimator.inputs.pandas_input_fn( x=pdDataFrame(...), y=pd.Series(...), num_epochs=num_epochs, shuffle=shuffle)

import numpy as np def get_input_fn_from_numpy(data_set, num_epochs=None, shuffle=True): return tf.estimator.inputs.numpy_input_fn( x={...}, y=np.array(...), num_epochs=num_epochs, shuffle=shuffle)

波士顿房屋价值的神经网络模型

在本教程的其余部分中,您将编写一个输入函数,用于预处理从 UCI房屋数据集 提取的波士顿房屋数据子集,并用它将数据提供给神经网络回归器以预测房屋中值。

您将用于训练您的神经网络的波士顿CSV数据集包含波士顿郊区的以下特征数据

FeatureDescription
CRIMCrime rate per capita
ZNFraction of residential land zoned to permit 25,000+ sq ft lots
INDUSFraction of land that is non-retail business
NOXConcentration of nitric oxides in parts per 10 million
RMAverage Rooms per dwelling
AGEFraction of owner-occupied residences built before 1940
DISDistance to Boston-area employment centers
TAXProperty tax rate per $10,000
PTRATIOStudent-teacher ratio

你的模型预测的标签是MEDV,即自住住宅的中值,以千美元计。

建立

下载以下数据集:boston_train.csvboston_test.csvboston_predict.csv

以下部分将逐步介绍如何创建输入函数,将这些数据集提供给神经网络回归器,训练和评估模型,并进行房屋价值预测。完整的最终代码可以在这里找到

导入住房数据

要开始之前,请设置导入(包括pandastensorflow)并将日志记录详细设置为INFO为了更详细的日志输出:

from __future__ import absolute_import from __future__ import division from __future__ import print_function import itertools import pandas as pd import tensorflow as tf tf.logging.set_verbosity(tf.logging.INFO)

为数据集定义列名称COLUMNS。为了区分标签的特征,还要定义FEATURESLABEL。然后将这三个CSV(tf.train,,tf.test并预测)读入熊猫 DataFrame s:

COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio", "medv"] FEATURES = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio"] LABEL = "medv" training_set = pd.read_csv("boston_train.csv", skipinitialspace=True, skiprows=1, names=COLUMNS) test_set = pd.read_csv("boston_test.csv", skipinitialspace=True, skiprows=1, names=COLUMNS) prediction_set = pd.read_csv("boston_predict.csv", skipinitialspace=True, skiprows=1, names=COLUMNS)

定义FeatureColumns并创建回归器

接下来,为输入数据创建一个FeatureColumns 列表,正式指定用于训练的一组要素。由于住房数据集中的所有功能都包含连续值,因此您可以FeatureColumn使用以下tf.contrib.layers.real_valued_column()函数创建它们:

feature_cols = [tf.feature_column.numeric_column(k) for k in FEATURES]

注意:有关功能列的更深入概述,请参阅此介绍,有关说明如何定义FeatureColumns分类数据的示例,请参阅线性模型教程。

现在,为神经网络回归模型实例化一个DNNRegressor。您需要在这里提供两个参数:hidden_units一个超参数,指定每个隐藏层中的节点数(这里是两个隐藏层,每个隐藏层各有10个节点),以及feature_columns包含您刚刚定义的FeatureColumns列表:

regressor = tf.estimator.DNNRegressor(feature_columns=feature_cols, hidden_units=[10, 10], model_dir="/tmp/boston_model")

构建input_fn

为了将输入数据传入regressor,写一个接受pandasDataframe 的工厂方法并返回input_fn

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)

需要注意的是输入数据传入input_fndata_set参数,它表示该功能可以处理任何的你已经导入DataFramesS:training_settest_setprediction_set

提供了两个附加参数: num_epochs__:控制迭代数据的历元数量。对于培训,将其设置为 None__,所以

input_fn 保持返回数据,直到达到所需的训练步数。为了评估和预测,将其设置为1,以便 input_fn将迭代数据一次,然后提高OutOfRangeError__。该错误将表示Estimator停止评估或预测。shuffle:是否洗牌数据。为了评估和预测,将其设置为False,以便input_fn按顺序迭代数据。对于训练,请将此设置为True。

训练(神经网络) 回归

训练神经网络回归,运行traintraining_set传递到input_fn如下:

regressor.train(input_fn=get_input_fn(training_set), steps=5000)

您应该看到类似于以下内容的日志输出,该输出每100步报告一次训练损失:

INFO:tensorflow:Step 1: loss = 483.179 INFO:tensorflow:Step 101: loss = 81.2072 INFO:tensorflow:Step 201: loss = 72.4354 ... INFO:tensorflow:Step 1801: loss = 33.4454 INFO:tensorflow:Step 1901: loss = 32.3397 INFO:tensorflow:Step 2001: loss = 32.0053 INFO:tensorflow:Step 4801: loss = 27.2791 INFO:tensorflow:Step 4901: loss = 27.2251 INFO:tensorflow:Saving checkpoints for 5000 into /tmp/boston_model/model.ckpt. INFO:tensorflow:Loss for final step: 27.1674.

评估模型

接下来,看看训练的模型如何针对测试数据集执行。运行evaluate了,这个时候传递test_setinput_fn

ev = regressor.evaluate( input_fn=get_input_fn(test_set, num_epochs=1, shuffle=False))

ev结果中检索损失并将其打印输出:

loss_score = ev["loss"] print("Loss: {0:f}".format(loss_score))

您应该看到类似于以下的结果:

INFO:tensorflow:Eval steps [0,1) for training step 5000. INFO:tensorflow:Saving evaluation summary for 5000 step: loss = 11.9221 Loss: 11.922098

进行预测

最后,您可以使用该模型来预测该房屋的prediction_set房屋中值,其中包含以下没有标签的六个示例的特征数据:

y = regressor.predict( input_fn=get_input_fn(prediction_set, num_epochs=1, shuffle=False)) # .predict() returns an iterator of dicts; convert to a list and print # predictions predictions = list(p["predictions"] for p in itertools.islice(y, 6)) print("Predictions: {}".format(str(predictions)))

你的结果应该包含六千美元的房屋价值预测,例如:

Predictions: [ 33.30348587 17.04452896 22.56370163 34.74345398 14.55953979 19.58005714]

其他资源

本教程专注于创建input_fn一个神经网络回归器。要详细了解如何将input_fns用于其他类型的模型,请查看以下资源:

  • 带有TensorFlow的大型线性模型:TensorFlow中的线性模型介绍提供了用于转换输入数据的特征列和技术的高级概述。

  • TensorFlow线性模型教程:本教程涵盖了根据人口普查数据预测收入范围的线性分类模型的创建FeatureColumninput_fn预测。

  • TensorFlow广泛和深度学习教程:基于线性模型教程,本教程涵盖FeatureColumn和input_fn创建了一个“广泛而深入”的模型,它结合了线性模型和使用DNNLinearCombinedClassifier的神经网络。