卷積神經網絡包括輸入層、卷積層、池化層、全連接配接層、輸出層。
其中卷積層、池化層為卷積神經網絡的重點,在一個卷積網絡中,卷積層和池化層可以有多層。
卷積層
參數:卷積核尺寸 、滑動視窗步長、邊緣填充(用來彌補一些邊界特征的損失)、卷積核個數
卷積計算如下圖所示:

卷積所得到的特征圖尺寸的計算公式:
H1、W1為輸入圖的長和寬;H2、W2為輸出特征圖的長和寬;F為卷積核的長和寬;S為滑動視窗的步長;P為邊界填充(共加了幾圈0)
池化層
由卷積層所提取到的特征圖過于龐大,由池化層對特征圖進行壓縮處理,池化層不涉及參數優化,隻是對特征圖中的特征值進行篩選。一般采用最大池化(max_pool),選取滑動視窗中的最大值作為特征值。
mnist手寫數字識别
卷積層+池化層
卷積網絡中的參數定義:
# 卷積核定義
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
# 偏置值定義
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
卷積函數、池化函數定義:
# 卷積層函數
# 滑動視窗步長為1步,對圖檔進行邊緣填充
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
# 池化函數
# 滑動視窗尺寸為[1, 2, 2, 1],滑動步長為2,邊緣填充
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
這裡 padding=‘SAME’ 是指進行邊緣填充,若為VALID則表示不進行邊緣填充。strides=[1, 2, 2, 1]指步長為2,其中第一位和最後一位固定為1。
卷積層操作:
# 第一層卷積層
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
# 進行卷積計算, relu作為激活函數
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
# 最大池化操作
h_pool1 = max_pool_2x2(h_conv1)
# 第二層卷積層
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
第一層卷積層的卷積核尺寸設為[5, 5, 1, 32],意思為第一層有10個5*5的卷積核對輸入圖像進行卷積操作,這裡1為圖像通道數,與輸入圖相同。
手動計算最後所得特征圖尺寸
采用上面所提到的特征圖尺寸計算公式,可以計算經過兩次(卷積+池化)操作後所得到的特征圖的尺寸。
全連接配接層
全連接配接層為兩層,第一層将前面所得到的特征圖轉化為多元向量
# 第一層全連接配接層
# 輸出為1024維的向量
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
# 使用Dropout, keep_prob是一個占位符,訓練時為0.5, 測試時為1
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
這裡的 7 * 7 * 64 即為我們上面手動所得到的一張特征圖的尺寸轉化為多元向量的結果。
在這裡使用了Dropout,這是防止神經網絡過拟合的一種手段,在每一步訓練時,以一定機率“去掉”網絡中的某些連接配接,但這種去除不是永久性的,隻是在目前步驟中去除,并且每一步的連接配接都是随機去除的。
在第二層全連接配接層中将所得的多元向量轉化為10個類别
# 第二層全連接配接層
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
到這裡一個用于進行MNIST手寫數字識别的卷積神經網絡建立完畢。
接下來建立交叉熵損失,使用優化算法(這裡使用Adam算法)對該網絡進行訓練。
# 定義交叉熵損失
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
# 定義梯優化算法
train_step = tf.train.AdamOptimizer(0.01).minimize(cross_entropy)
代碼位址:
https://github.com/xwzhang0724/WEI_Code/blob/master/mnist05.py