1. Tensorflow高效流水線Pipeline
2. Tensorflow的數據處理中的Dataset和Iterator
3. Tensorflow生成TFRecord
4. Tensorflow的Estimator實踐原理
1. 前言
前面博文介紹了Tensorflow的一大塊,數據處理,今天介紹Tensorflow的高級API,模型的建立和簡化過程。
2. Estimator優勢
本文檔介紹了Estimator一種可極大地簡化機器學習編程的高階TensorFlow API。用了Estimator你會得到數不清的好處。
- 您可以在本地主機上或分布式多服務器環境中運行基於 Estimator 的模型,而無需更改模型。此外,您可以在CPU、GPU或TPU上運行基於Estimator 的模型,而無需重新編碼模型。
- 使用dataset高效處理數據,搭配上Estimator再GPU或者TPU上高效的運行模型,提高整體的模型運行的時間。
- 使用Estimator編寫應用時,您必須將數據輸入管道從模型中分離出來。這種分離簡化了不同數據集的實驗流程。
- Estimator提供安全的分布式訓練循環,可以控制如何以及何時:
- 構建圖
- 初始化變量
- 開始排隊
- 處理異常
- 創建檢查點文件並從故障中恢復
- 保存 TensorBoard 的摘要
- Estimator簡化了在模型開發者之間共享實現的過程。
- 您可以使用高級直觀代碼開發先進的模型。簡言之,采用Estimator創建模型通常比采用低階TensorFlow API更簡單。
- Estimator本身在tf.layers之上構建而成,可以簡化自定義過程。
3. 預創建的Estimator
- 編寫一個或多個數據集導入函數。
- 一個字典,其中鍵是特征名稱,值是包含相應特征數據的張量(或 SparseTensor)
- 一個包含一個或多個標簽的張量
def input_fn(dataset):
# manipulate dataset, extracting the feature dict and the label
return feature_dict, label
- 定義特征列。每個tf.feature_column都標識了特征名稱、特征類型和任何輸入預處理操作。
# Define three numeric feature columns.
population = tf.feature_column.numeric_column('population')
crime_rate = tf.feature_column.numeric_column('crime_rate')
median_education = tf.feature_column.numeric_column('median_education',
normalizer_fn=lambda x: x - global_education_mean)
- 實例化相關的預創建的Estimator。 例如,下面是對名為LinearClassifier的預創建Estimator進行實例化的示例代碼:
# Instantiate an estimator, passing the feature columns.
estimator = tf.estimator.LinearClassifier(
feature_columns=[population, crime_rate, median_education],
)
- 調用訓練、評估或推理方法。例如,所有 Estimator 都提供訓練模型的 train 方法。
# my_training_set is the function created in Step 1
estimator.train(input_fn=my_training_set, steps=2000)
4. 自定義Estimator
4.1 input_fn輸入函數
輸入函數可以直接返回feature_dict, label,也可以返回的是dataset.make_one_shot_iterator(),這樣就和我們高效的數據預處理接上了。
def 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))
# Shuffle, repeat, and batch the examples.
dataset = dataset.shuffle(1000).repeat().batch(batch_size)
# Return the read end of the pipeline.
return dataset.make_one_shot_iterator().get_next()
4.2 feature_columns創建特征列
您必須定義模型的特征列來指定模型應該如何使用每個特征。無論是使用預創建的Estimator還是自定義Estimator,您都要使用相同的方式定義特征列。
以下代碼為每個輸入特征創建一個簡單的 numeric_column,表示應該將輸入特征的值直接用作模型的輸入:
# 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))
4.3 model_fn模型函數
def model_fn(
features, # This is batch_features from input_fn
labels, # This is batch_labels from input_fn
mode, # An instance of tf.estimator.ModeKeys
params): # Additional configuration
前兩個參數是從輸入函數中返回的features和labels,mode參數表示調用程序是請求訓練、預測還是評估。所以在model_fn里面需要實現訓練、預測、評估3種請求方式。
調用程序可以將params傳遞給Estimator的構造函數。傳遞給構造函數的所有params 轉而又傳遞給model_fn。
classifier = tf.estimator.Estimator(
model_fn=my_model,
params={
'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,
})
5. 定義模型
5.1 定義輸入層
在 model_fn 的第一行調用 tf.feature_column.input_layer,以將特征字典和 feature_columns 轉換為模型的輸入,會應用特征列定義的轉換,從而創建模型的輸入層。如下所示:
# Use `input_layer` to apply the feature columns.
net = tf.feature_column.input_layer(features, params['feature_columns'])
5.2 隱藏層
如果您要創建深度神經網絡,則必須定義一個或多個隱藏層。Layers API 提供一組豐富的函數來定義所有類型的隱藏層,包括卷積層、池化層和丟棄層。
隱藏層是用戶自己發揮想象力,定義的可以很復雜的地方。
# Build the hidden layers, sized according to the 'hidden_units' param.
for units in params['hidden_units']:
net = tf.layers.dense(net, units=units, activation=tf.nn.relu)
5.3 輸出層
# Compute logits (1 per class).
logits = tf.layers.dense(net, params['n_classes'], activation=None)
tf.nn.softmax 函數會將這些對數轉換為概率。
5.4 實現訓練、評估和預測
創建模型函數的最后一步是編寫實現預測、評估和訓練的分支代碼。
重點關注第三個參數 mode。如下表所示,當有人調用train、evaluate或predict時,Estimator框架會調用模型函數並將mode參數設置為ModeKeys.TRAIN,ModeKeys.EVAL,ModeKeys.PREDICT。
模型函數必須提供代碼來處理全部三個mode值。對於每個mode值,您的代碼都必須返回 tf.estimator.EstimatorSpec的一個實例,其中包含調用程序所需的信息。我們來詳細了解各個mode。
- 訓練 ModeKeys.TRAIN
構建訓練操作需要優化器。我們將使用 tf.train.AdagradOptimizer。
我們使用優化器的 minimize 方法根據我們之前計算的損失構建訓練操作。
minimize 方法還具有 global_step 參數。
optimizer = tf.train.AdagradOptimizer(learning_rate=0.1)
train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
if mode == tf.estimator.ModeKeys.TRAIN:
return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
- 評估 ModeKeys.EVAL
雖然返回指標是可選的。TensorFlow 提供一個指標模塊 tf.metrics 來計算常用指標。為簡單起見,我們將只返回准確率。
# Compute evaluation metrics.
accuracy = tf.metrics.accuracy(labels=labels,
predictions=predicted_classes,
name='acc_op')
metrics = {'accuracy': accuracy}
tf.summary.scalar('accuracy', accuracy[1])
if mode == tf.estimator.ModeKeys.EVAL:
return tf.estimator.EstimatorSpec(
mode, loss=loss, eval_metric_ops=metrics)
- 預測 ModeKeys.PREDICT
該模型必須經過訓練才能進行預測。經過訓練的模型存儲在磁盤上,位於您實例化 Estimator 時建立的 model_dir 目錄中。
此模型用於生成預測的代碼如下所示:
# Compute predictions.
predicted_classes = tf.argmax(logits, 1)
if mode == tf.estimator.ModeKeys.PREDICT:
predictions = {
'class_ids': predicted_classes[:, tf.newaxis],
'probabilities': tf.nn.softmax(logits),
'logits': logits,
}
return tf.estimator.EstimatorSpec(mode, predictions=predictions)
predictions 存儲的是下列三個鍵值對:
- class_ids 存儲的是類別 ID(0、1 或 2),表示模型對此樣本最有可能歸屬的品種做出的預測。
- probabilities 存儲的是三個概率(在本例中,分別是 0.02、0.95 和 0.03)
- logit 存儲的是原始對數值(在本例中,分別是 -1.3、2.6 和 -0.9)
我們通過 predictions 參數(屬於 tf.estimator.EstimatorSpec)將該字典返回到調用程序。Estimator 的 predict 方法會生成這些字典。
6. 實例化Estimator
通過 Estimator 基類實例化自定義 Estimator,如下所示:
# Build 2 hidden layer DNN with 10, 10 units respectively.
classifier = tf.estimator.Estimator(
model_fn=my_model,
params={
'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,
})
在這里,params 字典與 DNNClassifier 的關鍵字參數用途相同;即借助 params 字典,您無需修改 model_fn 中的代碼即可配置 Estimator。
使用 Estimator 訓練、評估和生成預測要用的其余代碼與預創建的 Estimator 一章中的相同。例如,以下行將訓練模型:
# Train the Model.
classifier.train(
input_fn=lambda:iris_data.train_input_fn(train_x, train_y, args.batch_size),
steps=args.train_steps)
7. 工作流程
- 假設存在合適的預創建的Estimator,使用它構建第一個模型並使用其結果確定基准。
- 使用此預創建的Estimator構建和測試整體管道,包括數據的完整性和可靠性。
- 如果存在其他合適的預創建的Estimator,則運行實驗來確定哪個預創建的Estimator效果最好。
- 可以通過構建自定義Estimator進一步改進模型。