1. 程式人生 > >TensorFlow實踐(10)——卷積神經網路模型LeNet5

TensorFlow實踐(10)——卷積神經網路模型LeNet5

(一)前 言

卷積神經網路(Convoltional Neural Networks, CNN)是一類包含卷積或相關計算且具有深度結構的前饋神經網路(Feedforward Neural Networks),是深度學習(deep learning)的代表演算法之一 。由於卷積神經網路能夠進行平移不變分類(shift-invariant classification),因此在文獻中也被稱為“平移不變人工神經網路(Shift-Invariant Artificial Neural Networks, SIANN)” 。卷積神經網路仿造生物的視知覺(visual perception)機制構建,可以進行監督學習和非監督學習,其隱含層內的卷積引數共享和層間連線的稀疏性使得卷積神經網路能夠以較小的計算量對格點化(grid-like topology)特徵,例如畫素和音訊進行學習、有穩定的效果且對資料沒有額外的特徵工程(feature engineering)要求 。對卷積神經網路的研究始於二十世紀80至90年代,時間延遲網路和LeNet-5是最早被證實有效的卷積神經網路演算法;在二十一世紀後,隨著數值計算裝置的改進,卷積神經網路得到了快速發展,並被大量應用於計算機視覺、自然語言處理等領域。 ——引用自百度百科

本節我們要使用TensorFlow實現LeNet5模型,這是一個非常經典的卷機模型,它的結構圖如下所示: 在這裡插入圖片描述 LeNet5模型一共包含兩個卷積層、兩個池化層和一個全連線層

(二)問題描述

使用卷積神經網路識別MNIST手寫體數字資料集: 在這裡插入圖片描述

(三)LeNet5模型的TensorFlow實現

(1)模型引數設定

# 設定學習率
learning_rate = 0.01
# 設定訓練次數
train_steps = 1000

(2)匯入資料

import tensorflow.examples.tutorials.mnist.input_data as input_data
mnist = input_data.
read_data_sets('', one_hot = True)

(3)定義相關函式

# 定義卷積層
def conv(input, filter_shape, bias_shape, strides_shape):
    filter = tf.get_variable("filter", filter_shape, initializer= tf.truncated_normal_initializer())
    bias = tf.get_variable("bias", bias_shape, initializer= tf.truncated_normal_initializer(
)) conv = tf.nn.conv2d(input, filter, strides= strides_shape, padding= 'SAME') output = tf.nn.sigmoid(conv + bias) return output # 定義池化層 def pooling(input, ksize_shape, strides_shape): output = tf.nn.max_pool(input, ksize= ksize_shape, strides= strides_shape, padding = 'SAME') return output # 定義全連線層 def connection(input, weight_shape, bias_shape, flat_shape): weight = tf.get_variable("weight", weight_shape, initializer= tf.truncated_normal_initializer()) bias = tf.get_variable("bias", bias_shape, initializer= tf.truncated_normal_initializer()) flat = tf.reshape(input, flat_shape) output = tf.nn.sigmoid(tf.matmul(flat, weight) + bias) return output

(4)模型構建

with tf.name_scope('Input'):
    x_data = tf.placeholder(tf.float32, [None, 784])
    y_data = tf.placeholder(tf.float32, [None, 10])
    x_image = tf.reshape(x_data, [-1, 28, 28, 1])

with tf.variable_scope('Conv1'):
    conv1_output = conv(x_image, [5, 5, 1, 6], [6], [1, 1, 1, 1])

with tf.variable_scope('Pooling1'):
    pooling1_output = pooling(conv1_output, [1, 2, 2, 1], [1, 2, 2, 1])

with tf.variable_scope('Conv2'):
    conv2_output = conv(pooling1_output, [5, 5, 6, 16], [16], [1, 1, 1, 1])

with tf.variable_scope('Pooling2'):
    pooling2_output = pooling(conv2_output, [1, 2, 2, 1], [1, 2, 2, 1])

with tf.variable_scope('Conv3'):
    conv3_output = conv(pooling2_output, [5, 5, 16, 120], [120], [1, 1, 1, 1])

with tf.variable_scope('Connection'):
    connection_output = connection(conv3_output, [7*7*120, 80], [80], [-1, 7*7*120])

with tf.name_scope('Output'):
    weight = tf.Variable( tf.truncated_normal([80, 10]),dtype= tf.float32)
    bias = tf.Variable(tf.truncated_normal([10]),dtype= tf.float32)
    y_model = tf.nn.softmax(tf.add(tf.matmul(connection_output, weight), bias))

(5)定義損失函式和訓練精度

# 使用交叉熵作為損失函式
with tf.name_scope('Loss'):
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels = y_model, logits = y_data))
    tf.summary.scalar('The variation of the loss', loss)
    
with tf.name_scope('Accuracy'):
    prediction = tf.equal(tf.argmax(y_model, 1), tf.argmax(y_data, 1))
    accuracy = tf.reduce_mean(tf.cast(prediction, tf.float32))
    tf.summary.scalar('The variation of the accuracy', accuracy)

(6)選擇優化器及定義訓練操作

# 此處選擇Adam優化器
with tf.name_scope('Train'):
    train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)

(7)建立會話進行訓練

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    x_batch, y_batch = mnist.train.next_batch(50)
    writer = tf.summary.FileWriter("logs/", sess.graph)
    merged = tf.summary.merge_all()
    batch_x, batch_y = mnist.train.next_batch(200)
    a = []
    for _ in range(train_steps):
        sess.run(train_op, feed_dict={x_data: batch_x, y_data: batch_y})
        if _ % 50 == 0:
            print(sess.run(accuracy, feed_dict={x_data: mnist.test.images, y_data: mnist.test.labels}))
            summary, acc = sess.run([merged, accuracy],
                                    feed_dict={x_data: mnist.test.images, y_data: mnist.test.labels})
            a.append(acc)
            writer.add_summary(summary, _)
    writer.close()

    plt.plot(a)
    plt.title('The variation of the acuracy')
    plt.xlabel('The sampling point')
    plt.ylabel('Accuracy')
    plt.tight_layout()
    plt.show()
    plt.savefig('mnist_cnn_acc.png', dpi = 200)

(8)完整程式碼

import tensorflow as tf
import matplotlib.pyplot as plt
import time
from tensorflow.examples.tutorials.mnist import input_data

# 設定學習率
learning_rate = 0.01
# 設定訓練次數
train_steps = 1000

# 定義卷積層
def conv(input, filter_shape, bias_shape, strides_shape):
    filter = tf.get_variable("filter", filter_shape, initializer= tf.truncated_normal_initializer())
    bias = tf.get_variable("bias", bias_shape, initializer= tf.truncated_normal_initializer())
    conv = tf.nn.conv2d(input, filter, strides= strides_shape, padding= 'SAME')
    output = tf.nn.sigmoid(conv + bias)
    return output

# define the pooling layer
def pooling(input, ksize_shape, strides_shape):
    output = tf.nn.max_pool(input, ksize= ksize_shape, strides= strides_shape, padding = 'SAME')
    return output

# define the connection layer
def connection(input, weight_shape, bias_shape, flat_shape):
    weight = tf.get_variable("weight", weight_shape, initializer= tf.truncated_normal_initializer())
    bias = tf.get_variable("bias", bias_shape, initializer= tf.truncated_normal_initializer())

    flat = tf.reshape(input, flat_shape)
    output = tf.nn.sigmoid(tf.matmul(flat, weight) + bias)
    return output

mnist = input_data.read_data_sets('C:/Users/12394/PycharmProjects/Machine Learning/MNIST_data', one_hot = True)

with tf.name_scope('Input'):
    x_data = tf.placeholder(tf.float32, [None, 784])
    y_data = tf.placeholder(tf.float32, [None, 10])
    x_image = tf.reshape(x_data, [-1, 28, 28, 1])

with tf.variable_scope('Conv1'):
    conv1_output = conv(x_image, [5, 5, 1, 6], [6], [1, 1, 1, 1])

with tf.variable_scope('Pooling1'):
    pooling1_output = pooling(conv1_output, [1, 2, 2, 1], [1, 2, 2, 1])

with tf.variable_scope('Conv2'):
    conv2_output = conv(pooling1_output, [5, 5, 6, 16], [16], [1, 1, 1, 1])

with tf.variable_scope('Pooling2'):
    pooling2_output = pooling(conv2_output, [1, 2, 2, 1], [1, 2, 2, 1])

with tf.variable_scope('Conv3'):
    conv3_output = conv(pooling2_output, [5, 5, 16, 120], [120], [1, 1, 1, 1])

with tf.variable_scope('Connection'):
    connection_output = connection(conv3_output, [7*7*120, 80], [80], [-1, 7*7*120])

with tf.name_scope('Output'):
    weight = tf.Variable( tf.truncated_normal([80, 10]),dtype= tf.float32)
    bias = tf.Variable(tf.truncated_normal([10]),dtype= tf.float32)
    y_model = tf.nn.softmax(tf.add(tf.matmul(connection_output, weight), bias))

with tf.name_scope('Loss'):
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels = y_model, logits = y_data))
    tf.summary.scalar('The variation of the loss', loss)

with tf.name_scope('Accuracy'):
    prediction = tf.equal(tf.argmax(y_model, 1), tf.argmax(y_data, 1))
    accuracy = tf.reduce_mean(tf.cast(prediction, tf.float32))
    tf.summary.scalar('The variation of the accuracy', accuracy)

with tf.name_scope('Train'):
    train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    x_batch, y_batch = mnist.train.next_batch(50)
    writer = tf.summary.FileWriter("logs/", sess.graph)
    merged = tf.summary.merge_all()
    batch_x, batch_y = mnist.train.next_batch(200)
    a = []
    for _ in range(train_steps):
        sess.run(train_op, feed_dict={x_data: batch_x, y_data: batch_y})
        if _ % 50 == 0:
            print(sess.run(accuracy, feed_dict={x_data: mnist.test.images, y_data: mnist.test.labels}))
            summary, acc = sess.run([merged, accuracy],
                                    feed_dict={x_data: mnist.test.images, y_data: mnist.test.labels})
            a.append(acc)
            writer.add_summary(summary, _)
    writer.close()
# 繪製訓練精度變化圖
    plt.plot(a)
    plt.title('The variation of the acuracy')
    plt.xlabel('The sampling point')
    plt.ylabel('Accuracy')
    plt.tight_layout()
    plt.show()
    plt.savefig('mnist_cnn_acc.png', dpi = 200)

(9)Tensorboard視覺化

使用tensorboard讀取訓練日誌,得到如下計算圖: 在這裡插入圖片描述

(四)總 結

本文介紹瞭如何使用TensorFlow建立LeNet5卷積神經網路模型,讀者可通過修改卷積核大小、池化方法、資料批處理數、訓練迭代次數、學習率等因素調整模型,有任何的問題請在評論區留言,我會盡快回復,謝謝支援。