我是一个很懒的人,我想试试
希望我能坚持到最后,把tensorflow的官方教程全部翻译出来
提高自己,也帮助他人
Building Input Functions with tf.estimator
本教程将向你介绍如何使用 tf.estimator 创建输入函数。你将了解如何构建一个 input_fn
来预处理并将数据传入你的模型中。然后你将使用 input_fn
将训练,评估和预测的数据传入到神经网络回归以便预测房屋的中位数价值。
Custom Input Pipelines with input_fn
input_fn
用于将特征和目标数据传递给 Estimator
的 train
, evaluate
和 predict
方法。用户可以在input_fn
进行特征工程或者预处理。以下是从 tf.estimator Quickstart tutorial 得到的一个例子:
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)
Anatomy of an 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
键/值对的字典,映射包含了相对应的特征数据的特征 columns 名字到
Tensor
(或SparseTensor
) 中。 -
labels
Tensor
包含了你的标签(目标)值:这个值是你的模型需要预测的。
Converting Feature Data to Tensors
如果你的特征/标签数据是一个 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),
...)
对于 sparse, categorical data (其中大部分数据值都是0),你将使用SparseTensor
,它使用三个参数实例化:
-
dense_shape
张量形状。获取一个列表指明每个维度的元素总数。例如,
dense_shape=[3,6]
表示一个二维 3x6 张量,dense_shape=[2,3,4]
表示一个三维 2x3x4 张量,而dense_shape=[9]
表示一个一维的包含9个元素的张量。 -
indices
张量中包含非零值的元素的索引。获取一个 terms 列表,每个 term 也是一个列表,包含了非零元素的索引。(元素为零的索引——例如[0,0]是一个二维张量第一行第一列的元素的索引值。) 例如,
indices=[[1,3], [2,4]]
指索引为 [1,3] 和 [2,4] 的元素有非零值。 -
values
一维张量值。
values
的 termi
对应于indices
的 termi
,并指定它的值。例如,给定indices=[[1,3], [2,4]]
,参数values=[18, 3.6]
指定了张量元素 [1,3] 值为 18,张量元素 [2,4] 的值是 3.6。
以下代码定义了一个 3 行 5 列的二维 SparseTensor
。索引 [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])
对应下面的稠密 (dense) 张量:
[[0, 6, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0.5]]
欲了解更多 SparseTensor
,请查阅 tf.SparseTensor
。
Passing input_fn Data to Your Model
提供数据给你的模型以便训练,你传递你创建的输入函数到你的 train
函数中,作为input_fn
参数的值,例如:
classifier.train(input_fn=my_input_fn, steps=2000)
注意input_fn
参数必须接收一个函数对象(例如,input_fn=my_input_fn
),而不是函数调用的返回值(input_fn=my_input_fn()
) 。这意味着,如果你尝试在你的train
调用中传递值给input_fn
,如下代码,将产生 TypeError
:
classifier.train(input_fn=my_input_fn(training_set), steps=2000)
然而,如果你想要能够参数化你的输入函数,还有其他的方法。你可以使用一个 不带参数的 wrapper 函数作为你的 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
调用包装在 lambda
表达式中,并将其传递给 input_fn
参数:
classifier.train(input_fn=lambda: my_input_fn(training_set), steps=2000)
设计如上所示的输入管道来接收数据集的参数的一个巨大的优势,是你可以传递相同的input_fn
给 evaluate
和 predict
操作而只需要改变数据集参数,例如:
classifier.evaluate(input_fn=lambda: my_input_fn(test_set), steps=2000)
这种方法增强了代码的可维护性:不需要为每种操作定义多个input_fn
(例如,input_fn_train
, input_fn_test
, input_fn_predict
)。
最后,你可以使用 tf.estimator.inputs
中的方法来从 numpy 或者 pandas 数据集创建input_fn
。额外的好处是你可以使用更多的参数,比如 num_epochs
和 shuffle
来控制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)
A Neural Network Model for Boston House Values
在本教程剩余部分,你将写一个输入函数来预处理从 UCI Housing Data Set 提取出的波士顿房价的子集,并用它传递数据给一个神经网络回归,以便预测房价的中位数。
你将使用 Boston CSV data sets 来训练你的神经网络,包含了以下波士顿郊区的 特征数据 :
特征 | 描述 |
---|---|
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,自住住宅的价值的中位数,单位千美元。
Setup
下载以下数据集:boston_train.csv, boston_test.csv 和 boston_predict.csv 。
以下部分提供了逐步介绍如何创建一个输入函数,传递这些数据集给一个神经网络回归,训练和评估模型,并预测房价。最终完整的代码 available here 。
Importing the Housing Data
首先,设置 imports(包含 pandas
和 tensorflow
) 并设置日志标志为 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
中定义数据集的列名。为了从标签中区分特征,还定义了FEATURES
和 LABEL
。然后读取三个 CSV(tf.train
, tf.test
, 和predict) 到 pandas 的 DataFrame
:
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)
Defining FeatureColumns and Creating the Regressor
接下来,为输入数据创建一列 FeatureColumn
,它指定用于训练的特征 columns 。因为房屋数据集的所有特征含有连续值,可以使用tf.contrib.layers.real_valued_column()
函数创建它们的 FeatureColumn
:
feature_cols = [tf.feature_column.numeric_column(k) for k in FEATURES]
注意:有关特征 columns 更深入的了解,请查看 这个介绍 ,例如说明如何定义 分类数据的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")
Building the input_fn
传递输入数据给regressor
,编写一个接收 pandas Dataframe
的工厂方法并返回一个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)
请注意,输入数据使用data_set
参数传递给input_fn
,这意味着函数可以处理你导入的任意的DataFrame
: training_set
, test_set
, 和prediction_set
。
提供另外两个参数:num_epochs
:控制迭代所有数据的 epochs 次数 。对于训练,设置这个值为 None,这样input_fn
保持返回数据知道达到所需的训练次数。对于评估和预测,设置这个值为 1,这样input_fn
将迭代所有数据一次,然后产生OutOfRangeError
错误。这个错误会告诉Estimator
停止评估和预测。shuffle
:是否打乱数据。对于评估和预测,设置为False
,这样input_fn
将顺序迭代所有的数据。对于训练,设置为 True
。
Training the Regressor
为了训练神经网络回归器,运行将training_set
传递给input_fn
的train
,如下所示:
regressor.train(input_fn=get_input_fn(training_set), steps=5000)
你将看到类似下面的输入日志,记录了每一百次的训练损失:
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.
Evaluating the Model
接下来,看看对于测试数据集训练模型的性能如何。运行evaluate
,传递test_set
给input_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
Making Predictions
最后,你可以在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]
Additional Resources
本教程重点在于创建一个神经网络回归器的input_fn
。想要学习更多其他模型类型的input_fn
,请查看以下资源:
- Large-scale Linear Models with TensorFlow: 对于线性模型,介绍了在 TensorFlow 中提供了一个高层次的特征 columns 的概述和技术转换输入数据。
- TensorFlow Linear Model Tutorial: 本教程将介绍如何创建根据人口普查数据预测收入范围的线性分类模型的
FeatureColumn
和input_fn
。 - TensorFlow Wide & Deep Learning Tutorial: 基于 Linear Model Tutorial ,本教程介绍使用结合了线性模型和使用
DNNLinearCombinedClassifier
神经网络的一个“又深又广”的模型,创建FeatureColumn
和input_fn
。