详细教程:https://www.tensorflow.org/get_started/premade_estimators
我们强烈建议使用下列 API 编写 TensorFlow 程序:
Estimator API:代表一个完整的模型。Estimator API 提供一些方法来训练模型、判断模型的准确率并生成预测。
Dataset API:构建数据输入管道。Dataset API 提供一些方法来加载和操作数据,并将数据馈送到您的模型中。Dataset API 与 Estimator API 合作无间。
##1. Estimator API
Estimator 是 TensorFlow 对完整模型的高级表示。它会处理初始化、日志记录、保存和恢复等细节部分,并具有很多其他功能,以便您可以专注于模型。
Estimator 是从 tf.estimator.Estimator 衍生而来的任何类。TensorFlow 提供一组预创建的 Estimator(例如 LinearRegressor)来实现常见的机器学习算法。除此之外,您可以编写自己的自定义 Estimator。
要根据预创建的 Estimator 编写 TensorFlow 程序,您必须执行下列任务:
###1.1 创建输入函数
您必须创建输入函数来提供用于训练、评估和预测的数据。
输入函数是返回 tf.data.Dataset 对象的函数,此对象会输出下列含有两个元素的元组:
def input_evaluation_set():
features = {'SepalLength': np.array([6.4, 5.0]),
'SepalWidth': np.array([2.8, 2.3]),
'PetalLength': np.array([5.6, 3.3]),
'PetalWidth': np.array([2.2, 1.0])} #字典类型{'特征名':包含此特征所有值的数组}
labels = np.array([2, 1]) #包含每个样本的标签值的数组
return features, labels
def train_input_fn(features, labels, batch_size):#输入函数
"""An input function for training"""
# Convert the inputs to a Dataset.
dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels)) #tf.data.Dataset 对象,包含特征和类标
# Shuffle, repeat, and batch the examples.
return dataset.shuffle(1000).repeat().batch(batch_size)
###1.2 定义特征列
特征列是一个对象,用于说明模型应该如何使用特征字典中的原始输入数据。
特征列视为原始数据和 Estimator 之间的媒介。特征列内容丰富,使您可以将各种原始数据转换为 Estimator 可以使用的格式,从而可以轻松地进行实验。
# Feature columns describe how to use the input.
my_feature_columns = []
for key in train_x.keys():
my_feature_columns.append(tf.feature_column.numeric_column(key=key))
要创建特征列,请调用 tf.feature_column 模块的函数。
# Defaults to a tf.float32 scalar.
numeric_feature_column = tf.feature_column.numeric_column(key="SepalLength")
# Represent a tf.float64 scalar.
numeric_feature_column = tf.feature_column.numeric_column(key="SepalLength",
dtype=tf.float64)
# Represent a 10-element vector in which each cell contains a tf.float32.
vector_feature_column = tf.feature_column.numeric_column(key="Bowling",
shape=10)
# Represent a 10x5 matrix in which each cell contains a tf.float32.
matrix_feature_column = tf.feature_column.numeric_column(key="MyMatrix",
shape=[10,5])
###1.3 实例化estimator
TensorFlow 提供了几个预创建的分类器 Estimator,其中包括:
# Build a DNN with 2 hidden layers and 10 nodes in each hidden layer.
classifier = tf.estimator.DNNClassifier(
feature_columns=my_feature_columns,
# Two hidden layers of 10 nodes each.
hidden_units=[10, 10],
# The model must choose between 3 classes.
n_classes=3)
###1.4 训练、评估、预测
#Train the Model.
classifier.train(
input_fn=lambda:iris_data.train_input_fn(train_x, train_y, args.batch_size),
steps=args.train_steps)
# Evaluate the model.
eval_result = classifier.evaluate(
input_fn=lambda:iris_data.eval_input_fn(test_x, test_y, args.batch_size))
print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
# Generate predictions from the model
expected = ['Setosa', 'Versicolor', 'Virginica']
predict_x = {
'SepalLength': [5.1, 5.9, 6.9],
'SepalWidth': [3.3, 3.0, 3.1],
'PetalLength': [1.7, 4.2, 5.4],
'PetalWidth': [0.5, 1.5, 2.1],
}
predictions = classifier.predict(
input_fn=lambda:iris_data.eval_input_fn(predict_x,
batch_size=args.batch_size))
for pred_dict, expec in zip(predictions, expected):
template = ('\nPrediction is "{}" ({:.1f}%), expected "{}"')
class_id = pred_dict['class_ids'][0]
probability = pred_dict['probabilities'][class_id]
print(template.format(iris_data.SPECIES[class_id],
100 * probability, expec))
##2. Dataset API
tf.data 模块包含一系列类,可让您轻松地加载数据、操作数据并通过管道将数据传送到模型中。本文档通过两个简单的示例来介绍该 API:
从 Numpy 数组中读取内存中的数据。
从 csv 文件中读取行。
###2.1 从 Numpy 数组中读取内存中的数据
####2.1.1 参数
- import iris_data
# Fetch the data
train, test = iris_data.load_data()
features, labels = train
#然后,我们使用类似以下内容的行将此数据传递给了输入函数:
batch_size=100
iris_data.train_input_fn(features, labels, batch_size)
####2.1.2 切片
在最简单的情况下,tf.data.Dataset.from_tensor_slices 函数接受一个数组并返回表示该数组切片的 tf.data.Dataset。例如,一个包含 mnist 训练数据的数组的形状为 (60000, 28, 28)。将该数组传递给 from_tensor_slices,会返回一个包含 60000 个切片的 Dataset 对象,其中每个切片都是一个 28x28 的图像。
返回此 Dataset 的代码如下所示:
train, test = tf.keras.datasets.mnist.load_data()
mnist_x, mnist_y = train
mnist_ds = tf.data.Dataset.from_tensor_slices(mnist_x)
print(mnist_ds)
这段代码将输出以下行,显示数据集中条目的形状和类型。请注意,数据集不知道自己包含多少条目。
<TensorSliceDataset shapes: (28,28), types: tf.uint8>
####2.1.3 操作
# Shuffle, repeat, and batch the examples.
dataset = dataset.shuffle(1000).repeat().batch(batch_size)
shuffle方法使用一个固定大小的缓冲区,在条目经过时执行随机化处理。将 buffer_size设置为大于Dataset中样本数的值,可确保数据完全被随机化处理。Iris 数据集仅包含 150 个样本。
repeat 方法会在结束时重启 Dataset。要限制周期数量,请设置 count 参数。
batch方法会收集大量样本并将它们堆叠起来以创建批次。这为批次的形状增加了一个维度。新的维度将添加为第一个维度。以下代码对之前的 MNIST Dataset 使用 batch方法。这样会产生一个包含表示 (28,28) 图像堆叠的三维数组的 Dataset
####2.1.4 返回
每个 Estimator 的 train、evaluate 和 predict 方法都需要输入函数返回包含 TensorFlow 张量的 (features, label) 对。train_input_fn 使用以下行将数据集转换为所需格式:
# Build the Iterator, and return the read end of the pipeline.
features_result, labels_result = dataset.make_one_shot_iterator().get_next()
结果会生成与 Dataset 中条目的布局相匹配的 TensorFlow 张量结构。
###2.2 从 csv 文件中读取行
####2.2.1 下载数据
import iris_data
train_path, test_path = iris_data.maybe_download()
iris_data.csv_input_fn 函数包含使用 Dataset 解析 csv 文件的备用实现。
####2.2.2 构建 Dataset
我们先构建一个 TextLineDataset 对象来实现一次读取文件中的一行数据。然后,我们调用 skip 方法来跳过文件的第一行,此行包含标题,而非样本:
ds = tf.data.TextLineDataset(train_path).skip(1)
####2.2.3 构建 csv 行解析器
最终,我们需要解析数据集中的每一行,以生成必要的 (features, label) 对
为了生成必要的 (features, label) 对,我们必须解析数据集中的每一行。以下 _parse_line 函数会调用 tf.decode_csv,以将单行解析为特征和标签两个部分。由于 Estimator 需要将特征表示为字典,因此我们依靠 Python 的内置 dict 和 zip 函数来构建此字典。特征名称是该字典的键。然后,我们调用字典的 pop 方法以从特征字典中移除标签字段:
# Metadata describing the text columns
COLUMNS = ['SepalLength', 'SepalWidth',
'PetalLength', 'PetalWidth',
'label']
FIELD_DEFAULTS = [[0.0], [0.0], [0.0], [0.0], [0]]
def _parse_line(line):
# Decode the line into its fields
fields = tf.decode_csv(line, FIELD_DEFAULTS)
# Pack the result into a dictionary
features = dict(zip(COLUMNS,fields))
# Separate the label from the features
label = features.pop('label')
return features, label
ds = ds.map(_parse_line)
print(ds)