使用 Estimator 構建卷積神經網絡
來源於:https://tensorflow.google.cn/tutorials/estimators/cnn 強烈建議前往學習
tf.layers
模塊提供一個可用於輕松構建神經網絡的高級 API,還提供了一些有助於創建密集(全連接)層和卷積層、添加激活函數以及應用 dropout 正規化的方法。在本教程中,您將了解如何使用 layers
構建一個卷積神經網絡模型來識別 MNIST 數據集中的手寫數字。
MNIST 數據集包含 60000 個訓練樣本和 10000 個測試樣本,這些樣本均為 0-9 的手寫數字,格式為 28x28 像素的單色圖像。
開始構建
我們來設置 TensorFlow 程序的框架。創建一個名為 cnn_mnist.py
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# Imports
import numpy as np
import tensorflow as tf
tf.logging.set_verbosity(tf.logging.INFO)
# Our application logic will be added here
if __name__ == "__main__":
tf.app.run()
在學習本教程的過程中,您將添加構建、訓練和評估卷積神經網絡的代碼。可在此處找到完整的最終代碼。
卷積神經網絡簡介
卷積神經網絡 (CNN) 是目前用於圖像分類任務的先進模型架構。CNN 將一系列過濾器應用於圖像的原始像素數據,以提取和學習更高級別的特征,然後模型可以使用這些特征進行分類。CNN 包含下列 3 個組成部分:
-
卷積層:將指定數量的卷積過濾器應用於圖像。對於每個子區域,該層會執行一組數學運算,以在輸出特征圖中生成單個值。然後,卷積層通常會向輸出應用 ReLU 激活函數,以便在模型中引入非線性規律。
-
池化層:對卷積層提取的圖像數據進行下采樣,以降低特征圖的維度,從而縮短處理時間。常用的池化算法是最大池化,它會提取特征圖的子區域(例如 2x2 像素區塊),保留子區域的最大值,並舍棄其他所有值。
-
密集(全連接)層:對由卷積層提取並由池化層下采樣的特征進行分類。密集層中的每個節點都連接到前一層中的所有節點。
通常,CNN 包括多個執行特征提取的卷積模塊。每個模塊都由一個卷積層後跟一個池化層組成。最後一個卷積模塊後跟一個或多個執行分類的密集層。在 CNN 的最終密集層中,模型中的每個目標類別(模型會預測的所有可能類別)都對應一個節點,並應用 softmax 激活函數,該函數針對每個節點生成一個介於 0 到 1 之間的值(所有這些 softmax 值的總和等於 1)。我們可以將某張給定圖像的 softmax 值解析為相對測量值,表示該圖像屬於每個目標類別的概率。
註意:如需更全面地了解 CNN 架構,請參閱斯坦福大學的“視覺識別卷積神經網絡”課程資料。
構建 CNN MNIST 分類器
我們使用以下 CNN 架構構建一個模型,用於對 MNIST 數據集中的圖像進行分類:
- 卷積層 1:應用 32 個 5x5 過濾器(提取 5x5 像素的子區域),並應用 ReLU 激活函數
- 池化層 1:使用 2x2 過濾器和步長 2(指定不重疊的池化區域)執行最大池化運算
- 卷積層 2:應用 64 個 5x5 過濾器,並應用 ReLU 激活函數
- 池化層 2:同樣,使用 2x2 過濾器和步長 2 執行最大池化運算
- 密集層 1:包含 1024 個神經元,其中丟棄正則化率為 0.4(任何指定元素在訓練期間被丟棄的概率為 0.4)
- 密集層 2(對數層):包含 10 個神經元,每個數字目標類別 (0–9) 對應一個神經元。
tf.layers
模塊包含用於創建上述 3 種層的方法:
conv2d()
。構建一個二維卷積層。接受的參數為過濾器數量、過濾器核大小、填充和激活函數。max_pooling2d()
。構建一個使用最大池化算法的二維池化層。接受的參數為池化過濾器大小和步長。dense()
。構建密集層。接受的參數為神經元數量和激活函數。
上述這些方法都接受張量作為輸入,並返回轉換後的張量作為輸出。這樣可輕松地將一個層連接到另一個層:只需從一個層創建方法中獲取輸出,並將其作為輸入提供給另一個層即可。
打開 cnn_mnist.py
並添加以下 cnn_model_fn
函數,該函數符合 TensorFlow Estimator API 預期接口的要求(之後的創建 Estimator 部分對此進行了詳細介紹)。cnn_mnist.py
接受的參數為 MNIST 特征數據、標簽和模式(來自 tf.estimator.ModeKeys
:TRAIN
、EVAL
、PREDICT
);配置 CNN,然後返回預測、損失和訓練操作:
def cnn_model_fn(features, labels, mode): """Model function for CNN.""" # Input Layer input_layer = tf.reshape(features["x"], [-1, 28, 28, 1]) # Convolutional Layer #1 conv1 = tf.layers.conv2d( inputs=input_layer, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) # Pooling Layer #1 pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2) # Convolutional Layer #2 and Pooling Layer #2 conv2 = tf.layers.conv2d( inputs=pool1, filters=64, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2) # Dense Layer pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64]) dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu) dropout = tf.layers.dropout( inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN) # Logits Layer logits = tf.layers.dense(inputs=dropout, units=10) predictions = { # Generate predictions (for PREDICT and EVAL mode) "classes": tf.argmax(input=logits, axis=1), # Add `softmax_tensor` to the graph. It is used for PREDICT and by the # `logging_hook`. "probabilities": tf.nn.softmax(logits, name="softmax_tensor") } if mode == tf.estimator.ModeKeys.PREDICT: return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions) # Calculate Loss (for both TRAIN and EVAL modes) loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits) # Configure the Training Op (for TRAIN mode) if mode == tf.estimator.ModeKeys.TRAIN: optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001) train_op = optimizer.minimize( loss=loss, global_step=tf.train.get_global_step()) return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op) # Add evaluation metrics (for EVAL mode) eval_metric_ops = { "accuracy": tf.metrics.accuracy( labels=labels, predictions=predictions["classes"])} return tf.estimator.EstimatorSpec( mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
下面的部分(標題對應上述各個代碼塊)詳細介紹了用於創建每個層的 tf.layers
代碼,以及如何計算損失、配置訓練操作和生成預測。如果您已經熟悉 CNN 和 TensorFlow Estimator
,並認為上述代碼直觀明了,則可以簡單瀏覽這些部分,或者直接跳轉到訓練和評估 CNN MNIST 分類器。
輸入層
默認情況下,對於 layers
模塊中用於為二維圖像數據創建卷積層和池化層的方法,輸入張量的形狀應該為 [batch_size, image_height, image_width, channels]
。可以使用 data_format
參數更改這種行為;具體定義如下:
batch_size
。在訓練期間執行梯度下降法時使用的樣本子集的大小。image_height
。樣本圖像的高度。image_width
。樣本圖像的寬度。channels
。樣本圖像中顏色通道的數量。彩色圖像有 3 個通道(紅色、綠色、藍色)。單色圖像只有 1 個通道(黑色)。data_format
。一個字符串,channels_last
(默認)或channels_first
之一。channels_last
對應於形狀為(batch, ..., channels)
的輸入,而channels_first
對應於形狀為(batch, channels, ...)
的輸入。
在此教程中,我們的 MNIST 數據集由 28x28 像素的單色圖像組成,因此輸入層的形狀應該為 [batch_size, 28, 28, 1]
。
要將我們的輸入特征圖 (features
) 轉換為此形狀,我們可以執行以下 reshape
操作:
input_layer = tf.reshape(features["x"], [-1, 28, 28, 1])
請註意,我們已經指明批次大小為 -1
,表示應根據 features["x"]
中輸入值的數量動態計算此維度,同時使所有其他維度的大小保持不變。這樣一來,我們就可以將 batch_size
視為可調整的超參數。例如,如果我們按照批次大小 5 將樣本饋送到模型中,則 features["x"]
將包含 3920 個值(每個圖像中的每個像素對應一個值),並且 input_layer
的形狀將為 [5, 28, 28, 1]
。同樣,如果我們按照批次大小 100 饋送樣本,則 features["x"]
將包含 78400 個值,並且 input_layer
的形狀將為 [100, 28, 28, 1]
。
卷積層 1
在我們的第一個卷積層中,我們需要將 32 個 5x5 過濾器應用到輸入層,並應用 ReLU 激活函數。我們可以使用 layers
模塊中的 conv2d()
方法創建該層,如下所示:
conv1 = tf.layers.conv2d(
inputs=input_layer,
filters=32,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
inputs
參數指定輸入張量,該張量的形狀必須為 [batch_size, image_height, image_width,channels]
。在此教程中,我們要將第一個卷積層連接到形狀為 [batch_size, 28, 28, 1]
的 input_layer
。
註意:在傳遞參數data_format=channels_first
時,conv2d()
將接受[batch_size, channels,image_height, image_width]
這種形狀。
filters
參數指定要應用的過濾器數量(在此教程中為 32),kernel_size
將過濾器的維度指定為 [height,width]
(在此教程中為 [5, 5]
)。
提示:如果過濾器高度和寬度的值相同,則可以為 kernel_size
指定單個整數(例如 kernel_size=5
)。
padding
參數指定以下兩個枚舉值之一(不區分大小寫):valid
(默認值)或 same
。要指定輸出張量與輸入張量具有相同的高度和寬度值,我們在此教程中設置 padding=same
,它指示 TensorFlow 向輸入張量的邊緣添加 0 值,使高度和寬度均保持為 28(沒有填充的話,在 28x28 張量上進行 5x5 卷積運算將生成一個 24x24 張量,因為在 28x28 網格中,可以從 24x24 個位置提取出一個 5x5 圖塊)。
activation
參數指定要應用於卷積輸出的激活函數。在此教程中,我們使用 tf.nn.relu
指定 ReLU 激活函數。
conv2d()
生成的輸出張量的形狀為 [batch_size, 28, 28, 32]
:高度和寬度維度與輸入相同,但現在有 32 個通道,用於保存每個過濾器的輸出。
池化層 1
接下來,我們將第一個池化層連接到剛剛創建的卷積層。我們可以使用 layers
中的 max_pooling2d()
方法構建一個層,該層使用 2x2 過濾器和步長 2 執行最大池化運算:
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
同樣,inputs
指定輸入張量,形狀為 [batch_size, image_height, image_width, channels]
。在此教程中,輸入張量是 conv1
,即第一個卷積層的輸出,形狀為 [batch_size, 28, 28, 32]
。
註意:與conv2d()
一樣,在傳遞參數data_format=channels_first
時,max_pooling2d()
將接受[batch_size, channels, image_height, image_width]
這種形狀。
pool_size
參數將最大池化過濾器的大小指定為 [height, width]
(在此教程中為 [2, 2]
)。如果兩個維度的值相同,則您可以改為指定單個整數(例如 pool_size=2
)。
strides
參數指定步長的大小。在此教程中,我們將步長設置為 2,表示過濾器提取的子區域在高度和寬度維度方面均應以 2 個像素分隔(對於一個 2x2 過濾器而言,這意味著提取的任何區域都不會重疊)。如果您要為高度和寬度設置不同的步長值,則可以改為指定元組或列表(例如 stride=[3, 6]
)。
max_pooling2d()
(pool1
) 生成的輸出張量的形狀為 [batch_size, 14, 14, 32]
:2x2 過濾器將高度和寬度各減少 50%。
卷積層 2 和池化層 2
像之前一樣,我們可以使用 conv2d()
和 max_pooling2d()
將第二個卷積層和池化層連接到 CNN。對於卷積層 2,我們配置 64 個 5x5 過濾器,並應用 ReLU 激活函數;對於池化層 2,我們使用與池化層 1 相同的規格(一個 2x2 最大池化過濾器,步長為 2):
conv2 = tf.layers.conv2d(
inputs=pool1,
filters=64,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
請註意,卷積層 2 接受的輸入為第一個池化層 (pool1
) 的輸出張量,並生成輸出張量 conv2
。conv2
的形狀為 [batch_size, 14, 14, 64]
,高度和寬度與 pool1
相同(因為 padding="same"
),並有 64 個通道,對應於應用的 64 個過濾器。
池化層 2 接受輸入 conv2
,並生成輸出 pool2
。pool2
的形狀為 [batch_size, 7, 7, 64]
(將 conv2
的高度和寬度各減少 50%)。
密集層
接下來,我們需要向 CNN 添加密集層(具有 1024 個神經元和 ReLU 激活函數),以對卷積/池化層提取的特征執行分類。不過,在我們連接該層之前,我們會先扁平化特征圖 (pool2
),以將其變形為 [batch_size,features]
,使張量只有兩個維度:
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])
在上面的 reshape()
操作中,-1
表示 batch_size
維度將根據輸入數據中的樣本數量動態計算。每個樣本都具有 7(pool2
高度)* 7(pool2
寬度)* 64(pool2
通道)個特征,因此我們希望 features
維度的值為 7 * 7 * 64(總計為 3136)。輸出張量 pool2_flat
的形狀為 [batch_size, 3136]
。
現在,我們可以使用 layers
中的 dense()
方法連接密集層,如下所示:
dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
inputs
參數指定輸入張量:扁平化後的特征圖 pool2_flat
。units
參數指定密集層中的神經元數量 (1024)。activation
參數會接受激活函數;同樣,我們會使用 tf.nn.relu
添加 ReLU 激活函數。
為了改善模型的結果,我們還會使用 layers
中的 dropout
方法,向密集層應用丟棄正則化:
dropout = tf.layers.dropout(
inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)
同樣,inputs
指定輸入張量,即密集層 (dense
) 的輸出張量。
rate
參數指定丟棄率;在此教程中,我們使用 0.4
,該值表示 40% 的元素會在訓練期間被隨機丟棄。
training
參數采用布爾值,表示模型目前是否在訓練模式下運行;只有在 training
為 True
的情況下才會執行丟棄操作。在此教程中,我們檢查傳遞到模型函數 cnn_model_fn
的 mode
是否為 TRAIN
模式。
輸出張量 dropout
的形狀為 [batch_size, 1024]
。
對數層
我們的神經網絡中的最後一層是對數層,該層返回預測的原始值。我們創建一個具有 10 個神經元(介於 0 到 9 之間的每個目標類別對應一個神經元)的密集層,並應用線性激活函數(默認函數):
logits = tf.layers.dense(inputs=dropout, units=10)
CNN 的最終輸出張量 logits
的形狀為 [batch_size, 10]
。
生成預測
模型的對數層以 [batch_size, 10]
維張量中原始值的形式返回預測。我們將這些原始值轉換成模型函數可以返回的兩種不同格式:
- 每個樣本的預測類別:一個介於 0 到 9 之間的數字。
- 每個樣本屬於每個可能的目標類別的概率:樣本屬於以下類別的概率:0、1、2 等。
對於某個給定的樣本,預測的類別是對數張量中具有最高原始值的行對應的元素。我們可以使用 tf.argmax
函數查找該元素的索引:
tf.argmax(input=logits, axis=1)
input
參數指定要從其中提取最大值的張量,在此教程中為 logits
。axis
參數指定要沿著 input
張量的哪個軸查找最大值。在此教程中,我們需要沿著索引為 1 的維度查找最大值,該維度對應於預測結果(已經知道對數張量的形狀為 [batch_size, 10]
)。
我們可以使用 tf.nn.softmax
應用 softmax 激活函數,以從對數層中得出概率:
tf.nn.softmax(logits, name="softmax_tensor")
註意:我們使用name
參數明確將該操作命名為softmax_tensor
,以便稍後引用它(我們將在設置日誌記錄鉤子部分設置 softmax 值的日誌記錄)。
我們將預測編譯為字典,並返回 EstimatorSpec
對象:
predictions = {
"classes": tf.argmax(input=logits, axis=1),
"probabilities": tf.nn.softmax(logits, name="softmax_tensor")
}
if mode == tf.estimator.ModeKeys.PREDICT:
return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)
計算損失
對於訓練和評估,我們需要定義損失函數來衡量模型的預測結果與目標類別之間的匹配程度。對於像 MNIST 這樣的多類別分類問題,通常將交叉熵用作損失指標。以下代碼計算模型在 TRAIN
或 EVAL
模式下運行時的交叉熵:
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
我們來詳細了解一下上述代碼。
labels
張量包含樣本的預測索引列表,例如 [1, 9, ...]
。logits
包含最後一層的線性輸出。
tf.losses.sparse_softmax_cross_entropy
以高效的數值穩定方式計算以上兩個輸入的 softmax 交叉熵(又名:類別交叉熵、負對數似然率)。
配置訓練操作
在上一部分中,我們將 CNN 的損失定義為對數層和標簽之間的 softmax 交叉熵。下面我們配置模型以在訓練期間優化該損失值。我們將學習速率設為 0.001,並將優化算法設為隨機梯度下降法:
if mode == tf.estimator.ModeKeys.TRAIN:
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
train_op = optimizer.minimize(
loss=loss,
global_step=tf.train.get_global_step())
return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)
註意:如需深入了解如何為 Estimator 模型函數配置訓練操作,請參閱在 tf.estimator 中創建 Estimator 教程中的定義模型的訓練操作。
添加評估指標
要在模型中添加準確率指標,我們在評估模式下定義 eval_metric_ops
字典,如下所示:
eval_metric_ops = {
"accuracy": tf.metrics.accuracy(
labels=labels, predictions=predictions["classes"])}
return tf.estimator.EstimatorSpec(
mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
訓練和評估 CNN MNIST 分類器
我們已經編寫了 MNIST CNN 模型函數;現在可以開始訓練和評估了。
加載訓練和測試數據
首先,我們加載訓練和測試數據。使用以下代碼將 main()
函數添加到 cnn_mnist.py
中:
def main(unused_argv):
# Load training and eval data
mnist = tf.contrib.learn.datasets.load_dataset("mnist")
train_data = mnist.train.images # Returns np.array
train_labels = np.asarray(mnist.train.labels, dtype=np.int32)
eval_data = mnist.test.images # Returns np.array
eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)
我們在 train_data
和 train_labels
中將訓練特征數據(55000 張手寫數字圖像的原始像素值)和訓練標簽(每張圖像在 0 到 9 之間的對應值)分別存儲為 Numpy 數組。同樣,我們將評估特征數據(10000 張圖像)和評估標簽分別存儲在 eval_data
和 eval_labels
中。
創建 Estimator
接下來,我們為模型創建一個 Estimator
(一種用於執行高級模型訓練、評估和推理的 TensorFlow 類)。將以下代碼添加到 main()
中:
# Create the Estimator
mnist_classifier = tf.estimator.Estimator(
model_fn=cnn_model_fn, model_dir="/tmp/mnist_convnet_model")
model_fn
參數指定用於訓練、評估和預測的模型函數;我們將在構建 CNN MNIST 分類器部分創建的 cnn_model_fn
傳遞到該參數。model_dir
參數指定要用於保存模型數據(檢查點)的目錄(在此教程中,我們指定臨時目錄 /tmp/mnist_convnet_model
,不過您可以選擇更改為其他目錄)。
註意:如需詳細了解 TensorFlow Estimator
API,請參閱在 tf.estimator 中創建 Estimator 教程。
設置日誌記錄鉤子
由於 CNN 可能需要一段時間才能完成訓練,因此我們設置一些日誌記錄,以在訓練期間跟蹤進度。我們可以使用 TensorFlow 的 tf.train.SessionRunHook
創建 tf.train.LoggingTensorHook
,它將記錄 CNN 的 softmax 層的概率值。將以下代碼添加到 main()
中:
# Set up logging for predictions
tensors_to_log = {"probabilities": "softmax_tensor"}
logging_hook = tf.train.LoggingTensorHook(
tensors=tensors_to_log, every_n_iter=50)
我們將要記錄的張量字典存儲到 tensors_to_log
中。每個鍵都是我們選擇的將會顯示在日誌輸出中的標簽,而相應標簽是 TensorFlow 圖中 Tensor
的名稱。在此教程中,我們可以在 softmax_tensor
(我們之前在 cnn_model_fn
中生成概率時為 softmax 操作指定的名稱)中找到 probabilities
。
註意:如果您未通過 name
參數明確為操作分配名稱,則 TensorFlow 將分配默認名稱。可以通過下面兩種簡單的方法找到應用於操作的名稱:在 TensorBoard 上可視化圖或啟用 TensorFlow Debugger (tfdbg)。
接下來,我們創建 LoggingTensorHook
,將 tensors_to_log
傳遞到 tensors
參數。我們設置 every_n_iter=50
,指定每完成 50 個訓練步之後應記錄概率。
訓練模型
現在,我們可以訓練模型了,可以通過創建 train_input_fn
並在 mnist_classifier
上調用 train()
來完成該操作。將以下代碼添加到 main()
中:
# Train the model
train_input_fn = tf.estimator.inputs.numpy_input_fn(
x={"x": train_data},
y=train_labels,
batch_size=100,
num_epochs=None,
shuffle=True)
mnist_classifier.train(
input_fn=train_input_fn,
steps=20000,
hooks=[logging_hook])
在 numpy_input_fn
調用中,我們將訓練特征數據和標簽分別傳遞到 x
(作為字典)和 y
。我們將 batch_size
設置為 100
(這意味著模型會在每一步訓練 100 個小批次樣本)。 num_epochs=None
表示模型會一直訓練,直到達到指定的訓練步數。我們還設置 shuffle=True
,以隨機化處理訓練數據。在 train
調用中,我們設置 steps=20000
(這意味著模型總共要訓練 20000 步)。為了在訓練期間觸發 logging_hook
,我們將其傳遞到 hooks
參數。
評估模型
訓練完成後,我們需要評估模型以確定其在 MNIST 測試集上的準確率。我們調用 evaluate
方法,該方法將評估我們在 model_fn
的 eval_metric_ops
參數中指定的指標。將以下代碼添加到 main()
中:
# Evaluate the model and print results
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
x={"x": eval_data},
y=eval_labels,
num_epochs=1,
shuffle=False)
eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn)
print(eval_results)
要創建 eval_input_fn
,我們設置 num_epochs=1
,以便模型評估一個數據周期的指標,並返回結果。我們還設置 shuffle=False
以按順序遍歷數據。
運行模型
我們已經編寫了 CNN 模型函數 Estimator
和訓練/評估邏輯;現在我們來看看結果。運行 cnn_mnist.py
。
註意:訓練 CNN 需要進行大量計算。cnn_mnist.py
的預計完成時間因處理器而異,但在 CPU 上的時間可能會超過 1 小時。要加快訓練速度,您可以減少傳遞到train()
的steps
數量,但請註意,這樣做將影響準確率。
在模型訓練期間,您將看到如下所示的日誌輸出:
INFO:tensorflow:loss = 2.36026, step = 1
INFO:tensorflow:probabilities = [[ 0.07722801 0.08618255 0.09256398, ...]]
...
INFO:tensorflow:loss = 2.13119, step = 101
INFO:tensorflow:global_step/sec: 5.44132
...
INFO:tensorflow:Loss for final step: 0.553216.
INFO:tensorflow:Restored model from /tmp/mnist_convnet_model
INFO:tensorflow:Eval steps [0,inf) for training step 20000.
INFO:tensorflow:Input iterator is exhausted.
INFO:tensorflow:Saving evaluation summary for step 20000: accuracy = 0.9733, loss = 0.0902271
{‘loss‘: 0.090227105, ‘global_step‘: 20000, ‘accuracy‘: 0.97329998}
在此教程中,我們在測試數據集上的準確率達到了 97.3%。
其他資源
要詳細了解 TensorFlow 中的 TensorFlow Estimator 和 CNN,請參閱以下資源:
- 在 tf.estimator 中創建 Estimator 介紹了 TensorFlow Estimator API,其中詳細說明了如何配置 Estimator、編寫模型函數、計算損失以及定義訓練操作。
- 高級卷積神經網絡詳細介紹了如何使用低階 TensorFlow 操作構建一個沒有 Estimator 的 MNIST CNN 分類模型。
使用 Estimator 構建卷積神經網絡