基於CNN的手寫數字識別程序


基於CNN的手寫數字識別程序

一、數據准備

訓練及測試數據采用Tensorflow官方提供的MNIST數據集,具體內容如下表所示:

文件 內容
圖片信息 大小為28*28的灰度手寫數字圖像,數字從0到9
train-images-idx3-ubyte.gz 訓練集圖片,55000張訓練圖片,5000張驗證圖片
train-labels-idx1-ubyte.gz 訓練集圖片對應的數字標簽
t10k-images-idx3-ubyte.gz 測試集圖片,共10000張
t10k-labels-idx1-ubyte.gz 測試集圖片對應的數字標簽

程序中數據導入代碼如下:

from tensorflow.examples.tutorials.mnist import input_data
minst = input_data.read_data_sets('/tmp/data', one_hot=True)

另外也將Tensorflow中一些常用操作封裝成函數,便於調用。

import tensorflow.compat.v1 as tf
#權重W初始化函數
def weight_variable(shape):
    initial = tf.truncated_normal(shape=shape, stddev=0.1)
    #從標准偏差為0.1的正態分布中截取數值進行初始化
    return tf.Variable(initial)
 
#偏置b初始化函數
def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    #值為0.1
    return tf.Variable(initial)

二、網絡結構

采用LeNet卷積神經網絡典型結構,結構圖如下:

2

1.卷積

(1)作用

​ 以若干個卷積核部分覆蓋在輸入圖上,按照設定的步長遍歷輸入圖並進行卷積運算,從而達到提取圖像特征的目的。

(2)卷積核

​ 卷積核一般為尺寸不大於輸入圖的方陣,以符合一定規律的隨機值(如截取自正態分布)進行初始化。本程序設兩次卷積操作,使用的卷積核設定如下:

卷積核 尺寸 輸入通道數 輸出通道數
filter_1 5*5 1 32
filter_2 5*5 32 64
(3)激活

​ 為使分類結果更符合要求,卷積計算后的結果需要再加上偏置b(初始化為0.1)。上述運算均為線性運算。在此之后,采用ReLU非線性函數繼續運算,也就是激活。

(4)程序實現

將上述步驟封裝為一個卷積層函數Conv2d()

#卷積層函數,返回值為卷積特征圖 
def Conv2d(image, shape):
    #shape為卷積核參數,格式[長,寬,輸入通道數,輸出通道數]
    w = weight_variable(shape)
    b = bias_variable([shape[3]])
    #shape[3]即shape第三維的值,即輸出通道數
    res_conv = tf.nn.conv2d(input=image, filter=w, strides=[1,1,1,1], padding='SAME') + b
    return tf.nn.relu(res_conv)

其中函數tf.nn.conv2d(input,filter,strides,padding)是Tensorflow提供的卷積函數,參數說明如下:

  • input,待卷積圖像;

  • filter,卷積核;

  • strides,步長,格式為[1,橫向步長,縱向步長,1]

  • padding,填充圖像邊緣('SAME')/不填充圖像邊緣('VALID')。若填充圖像邊緣,則使得圖像邊緣像素也能成為卷積中心。

2.池化

(1)作用

​ 在輸入特征圖上滑動一個窗口,取窗口中的某些特定數值(如最大值、平均值)構成池化特征圖。池化操作可以概括圖像局部信息,改變特征圖的大小,但不改變其通道數。

(2)池化窗

​ 類似於卷積核,需要設定尺寸和步長。程序中池化操作均采用大小為5*5,步長為1的池化窗。但不作為一個單獨變量,而體現在池化函數的參數中。

(3)程序實現

​ 程序采用最大池化,封裝為一個池化函數MaxPool()

def MaxPool(image):
    return tf.nn.max_pool(image, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

實際上只是調用了函數tf.nn.max_pool(image, ksize, strides, padding)參數說明如下:

  • input,輸入特征圖圖像;

  • ksize,池化窗的大小,取一個四維向量,一般是[1, height, width, 1];

  • strides,步長,格式為[1,橫向步長,縱向步長,1];

  • padding,填充圖像邊緣('SAME')/不填充圖像邊緣('VALID').

3.全連接

(1)作用

​ 對特征圖進行“投票”,從而得到一個特征在各個類別的概率。

(2)扁平化

​ 將經過一系列卷積和池化操作后所得到的特征圖展開成一維,便於全連接。

(3)程序實現
def Flat(input,size):
    ori_size = int(input.get_shape()[1])
    w = weight_variable(shape = [ori_size, size])
    b = bias_variable(shape = [size])
    return tf.matmul(input, w) + b
#扁平化
x_flat = tf.reshape(res_pool2, shape=[-1, 7 * 7 * 64])
res_flat = tf.nn.relu(Flat(x_flat, 1024))
#全連接
keep_prob = tf.placeholder(tf.float32)
full1_drop = tf.nn.dropout(res_flat, keep_prob=keep_prob)
#dropout防止過擬合,其中keep_prob為神經元保留率
res_y = Flat(full1_drop, 10)
#輸出分類結果,即0~9共10個標簽

三、輸出

1.Softmax

2.交叉熵損失函數

3.優化算法Adam

四、訓練結果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM