動手實現CNN卷積神經網絡

數據集採用的是手寫數據集(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

相關文章
相關標籤/搜索