數據集採用的是手寫數據集(http://yann.lecun.com/exdb/mnist/):python
本文構建的CNN網絡圖以下:git
像素點:28*28 = 784,55000張手寫數字圖片。網絡
# -*- coding: UTF-8 -*- import numpy as np import tensorflow as tf # 下載並載入 MNIST 手寫數字庫(55000 * 28 * 28)55000 張訓練圖像 from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets('mnist_data', one_hot=True)#將數據保存在mnist_data下 # one_hot 獨熱碼的編碼(encoding)形式 # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 的十位數字 # 0 : 1000000000 # 1 : 0100000000 # 2 : 0010000000 # 3 : 0001000000 # 4 : 0000100000 # 5 : 0000010000 # 6 : 0000001000 # 7 : 0000000100 # 8 : 0000000010 # 9 : 0000000001 # None 表示張量(Tensor)的第一個維度能夠是任何長度 # 除以 255 是爲了作 歸一化(Normalization),把灰度值從 [0, 255] 變成 [0, 1] 區間 # 歸一話能夠讓以後的優化器(optimizer)更快更好地找到偏差最小值 input_x = tf.placeholder(tf.float32, [None, 28 * 28]) / 255. # 輸入 output_y = tf.placeholder(tf.int32, [None, 10]) # 輸出:10個數字的標籤 # -1 表示自動推導維度大小。讓計算機根據其餘維度的值 # 和總的元素大小來推導出 -1 的地方的維度應該是多少 input_x_images = tf.reshape(input_x, [-1, 28, 28, 1]) # 改變形狀以後的輸入 # 從 Test(測試)數據集裏選取 3000 個手寫數字的圖片和對應標籤 test_x = mnist.test.images[:3000] # 圖片 test_y = mnist.test.labels[:3000] # 標籤 # 構建咱們的卷積神經網絡: # 第 1 層卷積 conv1 = tf.layers.conv2d( #conv2d指的是2維卷積 inputs=input_x_images, # 形狀 [28, 28, 1] filters=32, # 32 個過濾器,輸出的深度(depth)是32 kernel_size=[5, 5], # 過濾器在二維的大小是 (5 * 5) strides=1, # 步長是 1 padding='same', # same 表示輸出的大小不變,所以須要在外圍補零 2 圈 activation=tf.nn.relu # 激活函數是 Relu ) # 通過第一層卷積後輸出的形狀爲 [28, 28, 32] # 第 1 層池化(亞採樣) pool1 = tf.layers.max_pooling2d( inputs=conv1, # 形狀 [28, 28, 32] pool_size=[2, 2], # 過濾器在二維的大小是(2 * 2) strides=2 # 步長是 2 ) # 通過第 1 層池化後輸出的形狀 [14, 14, 32] # 第 2 層卷積 conv2 = tf.layers.conv2d( inputs=pool1, # 形狀 [14, 14, 32] filters=64, # 64 個過濾器,輸出的深度(depth)是64 kernel_size=[5, 5], # 過濾器在二維的大小是 (5 * 5) strides=1, # 步長是 1 padding='same', # same 表示輸出的大小不變,所以須要在外圍補零 2 圈 activation=tf.nn.relu # 激活函數是 Relu ) # 通過第二層卷積後輸出的形狀爲 [14, 14, 64] # 第 2 層池化(亞採樣) pool2 = tf.layers.max_pooling2d( inputs=conv2, # 形狀 [14, 14, 64] pool_size=[2, 2], # 過濾器在二維的大小是(2 * 2) strides=2 # 步長是 2 ) # 形狀 [7, 7, 64] # 平坦化(flat)。降維 flat = tf.reshape(pool2, [-1, 7 * 7 * 64]) # 形狀 [7 * 7 * 64, ] # 1024 個神經元的全鏈接層 dense = tf.layers.dense(inputs=flat, units=1024, activation=tf.nn.relu) # Dropout : 丟棄 50%(rate=0.5) dropout = tf.layers.dropout(inputs=dense, rate=0.5) # 10 個神經元的全鏈接層,這裏不用激活函數來作非線性化了 logits = tf.layers.dense(inputs=dropout, units=10) # 輸出。形狀 [1, 1, 10] # 計算偏差(先用 Softmax 計算百分比機率, # 再用 Cross entropy(交叉熵)來計算百分比機率和對應的獨熱碼之間的偏差) loss = tf.losses.softmax_cross_entropy(onehot_labels=output_y, logits=logits) #onehot_labels指的是實際的標籤值,logits指的是卷積神經網絡的預測輸出 # Adam 優化器來最小化偏差,學習率 0.001 train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) # 精度。計算 預測值 和 實際標籤 的匹配程度 # 返回 (accuracy, update_op), 會建立兩個局部變量 accuracy = tf.metrics.accuracy( labels=tf.argmax(output_y, axis=1),#第一個參數labels爲真實標籤 注:tf.argmax返回的是最大值的下標 predictions=tf.argmax(logits, axis=1),)[1]#第二個參數predictions爲預測標籤 # 建立會話 sess = tf.Session() # 初始化變量:全局和局部 init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer()) sess.run(init) # 訓練 5000 步。這個步數能夠調節 for i in range(5000): batch = mnist.train.next_batch(50) # 從 Train(訓練)數據集裏取 「下一個」 50 個樣本 train_loss, train_op_ = sess.run([loss, train_op], {input_x: batch[0], output_y: batch[1]}) if i % 100 == 0: test_accuracy = sess.run(accuracy, {input_x: test_x, output_y: test_y}) print("第 {} 步的 訓練損失={:.4f}, 測試精度={:.2f}".format(i, train_loss, test_accuracy)) # 測試:打印 20 個預測值 和 真實值 test_output = sess.run(logits, {input_x: test_x[:20]}) inferred_y = np.argmax(test_output, 1) print(inferred_y, '推測的數字') # 推測的數字 print(np.argmax(test_y[:20], 1), '真實的數字') # 真實的數字 # 關閉會話 sess.close()
結果:ide