4. Tensorflow的Estimator實踐原理


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'])

image

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)

image

5.3 輸出層

# Compute logits (1 per class).
logits = tf.layers.dense(net, params['n_classes'], activation=None)

tf.nn.softmax 函數會將這些對數轉換為概率。

image

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. 工作流程

  1. 假設存在合適的預創建的Estimator,使用它構建第一個模型並使用其結果確定基准。
  2. 使用此預創建的Estimator構建和測試整體管道,包括數據的完整性和可靠性。
  3. 如果存在其他合適的預創建的Estimator,則運行實驗來確定哪個預創建的Estimator效果最好。
  4. 可以通過構建自定義Estimator進一步改進模型。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM