tensorflow 开始——创建定制化 Estimator(创建自定义评估器)
參考文章:創(chuàng)建定制化 Estimator
文章目錄
- 創(chuàng)建定制化 Estimator
- 預(yù)制 vs. 定制化
- 創(chuàng)建功能列
- 寫一個(gè)模型函數(shù)
- 定義模型
- 定義輸出層
- 隱藏層
- 輸出層
- 實(shí)現(xiàn)訓(xùn)練、評(píng)估、預(yù)測 {#modes}
- 預(yù)測
- 計(jì)算損失
- 評(píng)估
- 訓(xùn)練
- 定制化 Estimator
- TensorBoard
- 總結(jié)
創(chuàng)建定制化 Estimator
Premade Estimators
下載及訪問示例代碼,請(qǐng)調(diào)用以下兩個(gè)命令:
git clone https://github.com/tensorflow/models/ cd models/samples/core/get_started在本文檔中,我們將查看 custom_estimator.py。您可以使用以下命令運(yùn)行它:
python custom_estimator.py如果你感到不耐煩,可隨時(shí)將 custom_estimator.py 與 premade_estimator.py 進(jìn)行比較(對(duì)比),它們?cè)谕荒夸浿小?/p>
預(yù)制 vs. 定制化
tf.estimator.Estimator
預(yù)制和定制化 Estimator 都是 Estimator。
預(yù)制 Estimator 更加成熟。有時(shí)候您需要更多地控制 Estimator 的行為。這就是定制化 Estimator 出現(xiàn)的場景。您可以創(chuàng)建一個(gè)定制化 Estimator 來做任何事情。如果希望以某種不尋常的方式連接隱藏層,請(qǐng)編寫定制化 Estimator。如果想要計(jì)算模型的唯一度量,請(qǐng)編寫定制化 Estimator。基本上,如果想要針對(duì)特定問題優(yōu)化的 Estimator,請(qǐng)編寫定制化 Estimator。
一個(gè)函數(shù)模型(或者 model_fn)實(shí)現(xiàn)了 ML 算法,使用預(yù)制和定制化 Estimator 的唯一區(qū)別是:
- 預(yù)制 Estimator,已經(jīng)有人為您編寫了函數(shù)模型。
- 定制化 Estimator,您必須自己寫函數(shù)模型。
(Dontla:是不是就是需要自己寫算法和直接使用別人的算法的區(qū)別?)
您的函數(shù)模型可以實(shí)現(xiàn)范圍更廣的算法,定義各種隱藏層和度量。與輸入函數(shù)一樣,所有函數(shù)模型都必須接受一組標(biāo)準(zhǔn)的輸入?yún)?shù),并返回一組標(biāo)準(zhǔn)的輸出值。就像輸入函數(shù)可以利用數(shù)據(jù)集 API 一樣,函數(shù)模型可以利用層 API 和 度量 API。
讓我們看看如何使用定制化 Estimator 解決 Iris (虹膜、鳶尾花)問題??焖偬嵝?—— 這是我們嘗試模仿鳶尾花模型的組織結(jié)構(gòu):
(Dontla:sepal 萼片、petal 花瓣,Setosa、Versicolor與Virginica表示鳶尾屬植物的三種花,具體結(jié)構(gòu)參見:鳶尾花識(shí)別問題,萼片有什么用?)
我們的鳶尾花實(shí)施包含四個(gè)特征,兩個(gè)隱藏層,和一個(gè) logits 輸出層。
寫一個(gè)輸入函數(shù)
Premade Estimators
def train_input_fn(features, labels, batch_size):"""An input function for training"""# 將輸入轉(zhuǎn)換為數(shù)據(jù)集。dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))# 隨機(jī)播放,重復(fù)和批處理示例。dataset = dataset.shuffle(1000).repeat().batch(batch_size)# 返回管道讀取的結(jié)束端。return dataset.make_one_shot_iterator().get_next()這個(gè)輸入函數(shù)建立一個(gè)輸入流水線,產(chǎn)生一批 (features, labels) 對(duì),其中 features 是字典特征。
創(chuàng)建功能列
特征列
下面的代碼為每個(gè)輸入特征創(chuàng)建一個(gè)簡單的 numeric_column ,表明輸入特征值應(yīng)該直接作為模型的輸入:
# 特征列描述如何使用輸入。 my_feature_columns = [] for key in train_x.keys():my_feature_columns.append(tf.feature_column.numeric_column(key=key))寫一個(gè)模型函數(shù)
我們將使用的函數(shù)模型具有以下調(diào)用簽名:
def my_model_fn(features, # This is batch_features from input_fnlabels, # This is batch_labels from input_fnmode, # An instance of tf.estimator.ModeKeysparams): # Additional configuration前兩個(gè)參數(shù)是輸入函數(shù)返回的功能部件和標(biāo)簽的批次:也就是說,features 和 labels 是您的模型將使用的數(shù)據(jù)的句柄。mode 參數(shù)指向調(diào)用方是否請(qǐng)求訓(xùn)練、預(yù)測或評(píng)估。
tf.estimator.DNNClassifier
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,})實(shí)現(xiàn)一個(gè)典型的函數(shù)模型,你必須做如下操作:
- 定義模型
- 為三種不同模式指定附加計(jì)算:
- 預(yù)測
評(píng)估 - 訓(xùn)練
定義模型
基本的深度神經(jīng)網(wǎng)絡(luò)模型必須定義如下三個(gè)部分:
- 一個(gè)輸入層
- 一個(gè)或者更多的隱藏層
- 一個(gè)輸出層
定義輸出層
tf.feature_column.input_layer
# 使用 `input_layer` 來應(yīng)用特征列。net = tf.feature_column.input_layer(features, params['feature_columns'])上一行應(yīng)用由特征列定義的轉(zhuǎn)換,創(chuàng)建模型輸入層。
隱藏層
tf.layers.dense
# 根據(jù) 'hidden_units' 參數(shù)構(gòu)建隱藏層。for units in params['hidden_units']:net = tf.layers.dense(net, units=units, activation=tf.nn.relu)- units 參數(shù)定義了給定層中輸出神經(jīng)元的數(shù)量。
- activation 參數(shù)定義激活函數(shù) — 在本例中為 Relu。
這里的變量 net 表示網(wǎng)絡(luò)中當(dāng)前的頂層。第一次迭代時(shí),net 表示輸入層。在每次迭代循環(huán)中,tf.layers.dense 創(chuàng)建一個(gè)新層,它使用 net 將上一層的輸出作為輸入。
創(chuàng)建兩個(gè)隱藏層后,我們的網(wǎng)絡(luò)如下所示。簡而言之,該圖不顯示每層的所有單元。
tf.layers.dense
輸出層
tf.layers.dense
# 計(jì)算 logits (每個(gè) class 一個(gè))。logits = tf.layers.dense(net, params['n_classes'], activation=None)這里 net 表示最后的隱藏層。因此,現(xiàn)在這個(gè)圖層連接如下:
最后的隱藏層輸入到輸出層。
定義輸出層時(shí),units 參數(shù)指定輸出的數(shù)量。因此,將 units 設(shè)置為 params[‘n_classes’],該模型會(huì)為每個(gè)類生成一個(gè)輸出值。輸出向量的每個(gè)元素都將包含得分或 logit,為關(guān)聯(lián)的 Iris 類計(jì)算:Setosa、Versicolor 或 Virginica。
tf.nn.softmax
實(shí)現(xiàn)訓(xùn)練、評(píng)估、預(yù)測 {#modes}
創(chuàng)建函數(shù)模型的最后一步是編寫分支代碼實(shí)現(xiàn)預(yù)測、評(píng)估和訓(xùn)練。
當(dāng)有人調(diào)用 Estimator 的 train 時(shí),模型函數(shù)就會(huì)調(diào)用 evaluate 或者 predict 方法。就像這樣回調(diào)模型的簽名函數(shù):
def my_model_fn(features, # This is batch_features from input_fnlabels, # This is batch_labels from input_fnmode, # An instance of tf.estimator.ModeKeys, see belowparams): # Additional configuration關(guān)注第三個(gè)論點(diǎn) — 模式。如下表所示,當(dāng)某人調(diào)用 train,evaluate,或者 predict,Estimator 框架調(diào)用您的模型。函數(shù)模式的參數(shù)設(shè)置如下:
| tf.estimator.Estimator.train | tf.estimator.ModeKeys.TRAIN |
| tf.estimator.Estimator.evaluate | tf.estimator.ModeKeys.EVAL |
| tf.estimator.Estimator.predict | tf.estimator.ModeKeys.PREDICT |
例如,假設(shè)您實(shí)例化一個(gè)自定義 Estimator 來生成一個(gè) 叫做 classifier 的對(duì)象。然后您執(zhí)行以下調(diào)用:
classifier = tf.estimator.Estimator(...) classifier.train(input_fn=lambda: my_input_fn(FILE_TRAIN, True, 500))Estimator 框架調(diào)用您的函數(shù)模型,模式設(shè)置為 ModeKeys.TRAIN。
您的函數(shù)模型必須提供處理所有三個(gè)模式值的代碼。對(duì)于每個(gè)模式值,您的代碼必須返回 tf.estimator.EstimatorSpec,包含調(diào)用者的請(qǐng)求信息。讓我們檢查每一種模式。
預(yù)測
當(dāng) Estimator 的 predict 方法被調(diào)用時(shí),model_fn 會(huì)接收到 mode = ModeKeys.PREDICT。在這種情況下,函數(shù)模型必須返回一個(gè)包含預(yù)測的 tf.estimator.EstimatorSpec。
在進(jìn)行預(yù)測之前,模型必須經(jīng)過訓(xùn)練。經(jīng)過訓(xùn)練的模型存儲(chǔ)在實(shí)例化 Estimator 時(shí)建立的 model_dir 目錄中的磁盤上
為此模型生成預(yù)測的代碼如下所示:
# 預(yù)測計(jì)算 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)在預(yù)測模式下,預(yù)測字典包含模型運(yùn)行時(shí)返回的所有內(nèi)容。
predictions 包含以下三個(gè)鍵值對(duì):
- class_ids 保存表示模型類 的 id (0, 1, 或者 2),這個(gè)例子中最有可能出現(xiàn)的物種的預(yù)測。
- probabilities 保存三個(gè)概率 (在本例中 0.02、0.95 和 0.03)。
- logit 保存原始 logit 值 (在本例中 -1.3、2.6 和 -0.9)。
tf.estimator.Estimator.predict
計(jì)算損失
對(duì)于 training 和 evaluation 我們都需要計(jì)算模型的損失。這是將要被優(yōu)化的目標(biāo)。
tf.losses.sparse_softmax_cross_entropy
此函數(shù)返回整個(gè)批處理的平均值。
# 損失計(jì)算。 loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)評(píng)估
當(dāng) Estimator 的 evaluate 方法被調(diào)用時(shí),model_fn 接收到 mode = ModeKeys.EVAL。在這種情況下,模型函數(shù)必須返回一 tf.estimator.EstimatorSpec 包含模型損失和可選的一個(gè)或者更多的指標(biāo)。
tf.metrics.accuracy
# metrics 指標(biāo)計(jì)算。 accuracy = tf.metrics.accuracy(labels=labels,predictions=predicted_classes,name='acc_op')tf.estimator.EstimatorSpec
- loss,這是模型損失。
- eval_metric_ops,這是一個(gè)可選的度量字典。
所以我們將創(chuàng)建一個(gè)包含我們唯一度量標(biāo)準(zhǔn)的字典。如果我們計(jì)算了其他度量,我們會(huì)將它們添加為與其他鍵值對(duì)相同的字典。然后我們將在 eval_metric_ops 中傳遞該字典 tf.estimator.EstimatorSpec 的參數(shù)。代碼如下:
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)tf.summary.scalar
訓(xùn)練
當(dāng)調(diào)用 Estimator 的 train 方法時(shí),使用 mode = ModeKeys.TRAIN 調(diào)用 model_fn。在這種情況下,模型函數(shù)必須返回包含損失和培訓(xùn)操作的 EstimatorSpec 。
tf.tra.AdagradOptimizer
以下是構(gòu)建優(yōu)化器的代碼:
optimizer = tf.train.AdagradOptimizer(learning_rate=0.1)tf.train.Optimizer.minimize
tf.train.get_global_step
以下是訓(xùn)練模型的代碼:
train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())tf.estimator.EstimatorSpec
- loss 包含損失的函數(shù)值。
- train_op 執(zhí)行一個(gè)訓(xùn)練步驟。
下面是我們調(diào)用 EstimatorSpec 的代碼:
return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)模型功能現(xiàn)在已經(jīng)完成了。
定制化 Estimator
通過 Estimator 基類指定定制化 Estimator,如下所示:
# 用兩個(gè) 10 單元建立 2 個(gè)隱藏層的 DNN。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 字典的作用與關(guān)鍵字相同。DNNClassifier 的參數(shù),也就是說,params 字典允許您在不修改 model_fn 中代碼的情況下配置您的 Estimator。
Premade Estimators
# 訓(xùn)練模型 classifier.train(input_fn=lambda:iris_data.train_input_fn(train_x, train_y, args.batch_size),steps=args.train_steps)TensorBoard
您可以在 TensorBoard 中查看定制化 Estimator 的訓(xùn)練結(jié)果。查看此報(bào)告,請(qǐng)從命令行啟動(dòng) TensorBoard,如下所示:
# 將 PATH 替換為以 model_dir 形式傳遞的實(shí)際路徑 tensorboard --logdir=PATH然后在瀏覽器輸入 http://localhost:6006 來打開 TensorBoard。
所有預(yù)制 Estimator 都會(huì)自動(dòng)將大量信息記錄到 TensorBoard 中。而對(duì)于定制化的 Estimators,TensorBoard 只提供一個(gè)默認(rèn)日志(損失圖)以及顯式告訴 TensorBoard 進(jìn)行日志記錄的信息。對(duì)于您剛剛創(chuàng)建的定制化 Estimator,TensorBoard 生成以下內(nèi)容:
TensorBoard 顯示三個(gè)圖形。
簡而言之,下面三張圖將告訴您:
-
global_step/sec: 顯示多少批的性能指標(biāo)(更新),我們每秒處理的作為訓(xùn)練模型)。
-
損失:損失報(bào)告。
-
準(zhǔn)確性:準(zhǔn)確性由以下兩行記錄:
eval_metric_ops={‘my_accuracy’: accuracy},在評(píng)估期間
tf.summary.scalar(‘a(chǎn)ccuracy’, accuracy[1]),在訓(xùn)練期間
這些 tensorboard 是向優(yōu)化的 minimize 方法傳遞 global_step 的主要原因之一。沒有它,模型就不能記錄這些圖的 x 坐標(biāo)。
注意以下 my_accuracy 和 loss 圖表:
- 橙色線代表訓(xùn)練。
- 藍(lán)色點(diǎn)代表評(píng)估。
在訓(xùn)練期間,隨著批次的處理,會(huì)定期記錄摘要(橙色線),這就是為什么它會(huì)跨越 x 軸范圍的圖形。
相比之下,對(duì)于每個(gè) evaluate 調(diào)用,評(píng)估只會(huì)在圖形上產(chǎn)生一個(gè)點(diǎn)。這個(gè)點(diǎn)包含整個(gè)評(píng)估調(diào)用的平均值。這在圖上沒有寬度,因?yàn)樗耆菑奶囟ㄓ?xùn)練步驟的模型狀態(tài)(從單個(gè)檢查點(diǎn))計(jì)算的。
如下圖所示,您可以有選擇地看到。使用左側(cè)的控件禁用/啟用報(bào)告。
啟用或暫停報(bào)告。
總結(jié)
盡管預(yù)制 Estimator 是快速創(chuàng)建新模型的高效方式,通常您需要提供定制化 Estimator 額外的靈活性。幸運(yùn)的是,預(yù)制和定制化遵循相同的編程模型。唯一的實(shí)際區(qū)別是您必須寫一個(gè)模型用于自定義 Estimators 的函數(shù),其他的所有內(nèi)容都是相同的。
了解更多細(xì)節(jié),請(qǐng)務(wù)必查看:
-
使用定制化 Estimator MINIST 的官方 TensorFlow 實(shí)現(xiàn) ,
-
TensorFlow 官方模型庫,其中包含了更多使用定制化 Estimator 的示例。
-
TensorBoard 視頻
-
介紹 TensorBoard。
-
底層 API 編程介紹
總結(jié)
以上是生活随笔為你收集整理的tensorflow 开始——创建定制化 Estimator(创建自定义评估器)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Numpy 中 mean() 和 ave
- 下一篇: 如何提高clone github项目的下