亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

全部開發者教程

TensorFlow 入門教程

使用預設的 Estimator 模型

在之前的學習中,我們學習到了如何使用 Keras 來快速、簡潔地構建網絡模型,我們也認識到了使用 tf.keras 構建模型的優點。但是在 TensorFlow 之中構建網絡模型的方式遠遠不止 Keras 一種方式,那么這節課開始我們便開始學習如何使用 Estimator 來構建模型。

1. 什么是 Estimator

Estimator 是 TensorFlow 之中模型的一種高級表示,也就是說,我們可以像使用 Keras 一樣來創建自己的模型,并進行訓練、評估等操作。Estimator 主要可以提供的功能包括:

  • 模型的訓練;
  • 模型的評估;
  • 使用模型進行預測。

在 TensorFlow 之中,Estimator 的大部分 API 都集中在 tf.estimator 之中。

在 API 層面上,Keras 與 Estimator 處于相同的層面,與 Keras 相似,Estimator 也是一種模型層面的高階 API,因此也可以和 Keras 一樣快捷、方便地使用。
但是與 Keras 不同的是,Estimator 在 TensorFlow1.1 版本的時候就已經被引入了 TensorFlow,也正因如此,TensorFlow 對于 Estimator 的支持也較好一些。

2. 使用 Estimator 構建模型的一般步驟

在 TensorFlow 之中,使用 Estimator 進行模型訓練大致需要經過四個步驟,它們分別是:

  • 定義特征列;
  • 定義輸入函數;
  • 創建(實例化)一個 Estimator 模型
  • 訓練并進行相應的評估等操作。

對于這四個步驟,相信特征列和輸入函數這兩個名詞對于大家都很陌生,那么我們便來進行相應解釋:

  • 特征列:

    “特征列(feature columns)是一個對象,用于描述模型應該如何使用特征字典中的原始輸入數據”——官方定義

    簡單來說,特征列就是來告訴模型你要使用數據中的哪些數據列,其中哪些數據列為離散值,哪些數據列為連續值。

  • 輸入函數:簡單來說,輸入函數是一個函數,它返回的是一個數據集,其中的每條數據都是(特征,標簽)的形式。我們可以將輸入函數理解為“模型用來取數據的地方,通過輸入函數,模型可以不斷取得新的數據”。

因為 TensorFlow 內部提供了很多內置的 Estimator 模型,因此這節課我們會采用其預設的模型來進行分類學習。

對于這四步的具體細節,我們會在接下來的示例過程中具體演示。

3. 實例-使用 Estimator 進行泰坦尼克生存預測

首先我們需要先獲取數據集,也就是泰塔尼克數據集,我們采用之前相同的方式來獲取數據集:

import pandas as pd
import tensorflow as tf

train_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv")

columns = ['survived', 'sex', 'age', 'n_siblings_spouses', 'parch', 'fare', 'class', 'deck', 'embark_town', 'alone']

categorical = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck', 'embark_town', 'alone']
numeric = ['age', 'fare']

train_df = pd.read_csv(train_file, names=columns)

其中我們 columns 變量定義了全部的列,同時我們定義了 categorical 和 numeric 兩個數據列,分別代表離散值以及連續值,這便于我們后面的編碼處理。

然后我們進行測試集與訓練集的劃分:

test_df = train_df.sample(frac=0.2)
train_df = train_df[~train_df.index.isin(test_df.index)]

train_df_y = train_df.pop('survived')
test_df_y = test_df.pop('survived')

print(len(train_df), len(test_df))

在這里,我們使用 train_df.sample() 方法來按照 0.2 的采樣率進行隨機采樣,從來獲取我們的測試集,然后我們將原來集合中的測試集去掉,得到剩下的訓練集。然后我們又采用 pop 的方式來獲取到標簽值。這里我們按照傳統的8:2的比例進行分割。

我們可以得到輸出:

502, 125

然后我們就進行特征列的構造,在這里我們將特征列分為連續值與離散值,對于離散值,我們進行了獨熱編碼的處理,因為獨熱編碼在訓練的過程中較大的優勢:

def transfer2one_hot(feature, feature_vocab):
  return tf.feature_column.indicator_column(tf.feature_column.categorical_column_with_vocabulary_list(feature, feature_vocab))

features = []
for feature in categorical:
  features.append(
      transfer2one_hot(feature, train_df[feature].unique())
    )

for feature in numeric:
  features.append(
      tf.feature_column.numeric_column(feature, dtype=tf.float32)
    )

在這里我們使用到了三個非常重要的函數:

  • tf.feature_column.numeric_column,將某一列作為連續值視作數據特征;
  • tf.feature_column.indicator_column,將某一離散列作為獨熱編碼視作數據列;
  • tf.feature_column.categorical_column_with_vocabulary_list,接收第一個參數為某一離散特征列,第二個參數為該離散特征列的所有取值情況,將一個普通列視作離散數據列(未經過獨熱編碼)。

然后我們便可以定義我們的輸入函數,在這里我們將輸入函數分為訓練時的輸入函數以及測試時的輸入函數,具體來說:

def train_input_fn(features, labels, batch_size=8):
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels)) 
    dataset = dataset.shuffle(len(train_df))
    dataset = dataset.repeat(30000)   
    return dataset.batch(batch_size)
def test_input_fn(features, labels, batch_size=8):
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))    
    return dataset.batch(batch_size)

train_fn = lambda: train_input_fn(train_df, train_df_y)
test_fn = lambda: test_input_fn(test_df, test_df_y)

在輸入函數之中,我們使用參數中的 features 和 labels 創建了一個數據集,并且將其返回。并且對于訓練集,我們采用了數據增強,也就是隨機化以及重復操作,在這里,30000 就是我們要訓練的 Steps 數量(我們所使用的 batch_size 的數量,這里是8)。

最后因為輸入函數是一個函數,因此我們需要定義一個 lambda 函數來返回一個輸入函數,否則輸入函數將直接返回一個數據集,這是我們不希望看到的。

再者我們就可以載入一個內置的模型:

classifier = tf.estimator.DNNClassifier(
    feature_columns=feature_columns,
    hidden_units=[50, 30, 20],
    n_classes=2)

在這里我們定義了一個 Estimator 內置的分類器,它的三個參數如下:

  • feature_columns,特征列,就是我們剛剛處理過的特征列,包含連序列與離散列;
  • hidden_units,隱藏單元的數量,在這里我們定義了三層;
  • n_classes,輸出的種類,這里我們只有生存和不能生存兩類。

最后我們便可以進行模型的訓練與測試,具體的實現細節非常簡單:

classifier.train(input_fn=train_fn, steps=30000)

test_result = classifier.evaluate(input_fn=test_fn)
print(test_result)

我們首先進行了訓練,輸入函數為我們之前定義的訓練的輸入函數,然后訓練 Steps 為 30000 ,然后我們便進行了測試,此時的輸入函數為我們為測試專門定制的輸入函數。我們可以得到結果:

......
INFO:tensorflow:global_step/sec: 861.581
INFO:tensorflow:loss = 0.4950667, step = 47500 (0.114 sec)
INFO:tensorflow:global_step/sec: 885.82
INFO:tensorflow:loss = 0.30664578, step = 47600 (0.113 sec)
INFO:tensorflow:global_step/sec: 879.637
INFO:tensorflow:loss = 0.82413065, step = 47700 (0.116 sec)
INFO:tensorflow:global_step/sec: 814.178
INFO:tensorflow:loss = 0.5236651, step = 47800 (0.123 sec)
INFO:tensorflow:global_step/sec: 829.556
INFO:tensorflow:loss = 0.4500552, step = 47900 (0.118 sec)
......

{'accuracy': 0.724, 'accuracy_baseline': 0.7624, 'auc': 0.5004091, 'auc_precision_recall': 0.43117255, 'average_loss': 1.7417283, 'label/mean': 0.376, 'loss': 2.7342584, 'precision': 0.0, 'prediction/mean': 0.025458882, 'recall': 0.0, 'global_step': 0}

我們可以看到,最后我們在測試集上的準確率為 0.72 ,也是一個不錯的結果。

4. 小結

在這節課之中,我們學習了什么是 Estimator,同時也了解了使用 Estimator 進行訓練的一般步驟,最后我們也學習了如何在實戰中使用 Estimator 模型。

圖片描述