TensorFlow學習筆記(二)之卷積神經網絡

環境

反向傳播

神經網絡存在的問題及優化方法

存在問題

優化方法

隨機梯度下降

Mini-Batch梯度下降

動量梯度下降

解決方法

主要問題

主要解決方法

相關計算

卷積及卷積核

卷積核的物理含義

卷積處理多通道生成單通道圖像

卷積處理多通道生成多通道圖像

激活函數

卷積核的參數

池化

基本計算

池化的特點

全連接

卷積神經網絡結構

卷積神經網絡

全卷積神經網絡

代碼

參考資料


環境

python 3.6 + TensorFlow 1.13.1 + Jupyter Notebook

反向傳播

即複合函數求導,鏈式法則爲實現基礎。

神經網絡存在的問題及優化方法

存在問題

1、每次都在整個數據集上計算Loss和梯度,導致:

(1)計算量大;

(2)內存可能承載不了;

2、梯度方向確定的時候,仍然是每次走一個單位步長,導致:速度太慢。

優化方法

隨機梯度下降

每次只使用一個樣本。

缺點:不能反應整個數據集的梯度方向,導致每次訓練的收斂速度較慢。

Mini-Batch梯度下降

每次使用小部分隨機選擇的數據進行訓練。

缺點:梯度下降存在震盪問題(Mini-Batch越大,這個問題越不明顯);存在局部極值和saddle point問題。

動量梯度下降

解決了收斂速度慢、震盪、局部極值、saddle point的問題。

(1)開始訓練時,積累動量,加速訓練;

(2)局部極值附近震盪時,梯度爲0,由於動量,跳出陷阱;

(3)梯度改變方向的時候,動量緩解動盪。

    

解決方法

主要問題

神經網絡遇到的最主要問題:參數過多,導致:

(1)計算量大;

(2)容易過擬合,需要更多的訓練數據;

(3)收斂到較差的局部極值。

主要解決方法

卷積:

(1)局部連接(全連接變爲局部連接,減少數據量):圖像的區域性;

(2)參數共享:圖像特徵與位置無關。

相關計算

卷積計算:每個位置進行內積運算。

輸出size = 輸入size – 卷積核size + 1

步長:卷積核每步滑動的長度(卷積的默認步長爲1)。

Padding:使輸出size不變。

(下圖的“輸出size = 輸入size – 卷積核size + 1”,輸入size是指已經加上Padding的size)

輸出size = 輸入size + Padding * 2 – 卷積核size + 1

卷積及卷積核

卷積核的物理含義

可認爲卷積核是用於提取某個特徵的,輸入圖像若具有卷積核所標識的特徵,則輸出值較大,否則較小。

卷積處理多通道生成單通道圖像

卷積處理多通道生成多通道圖像

即增加多個參數不共享的卷積核。

激活函數

激活函數的特徵(常用ReLU,快速):

(1)具有單調性;

(2)非線性函數(原因:神經網絡層級之間全連接相當於矩陣運算,矩陣的操作具有合併性,若爲線性運算,多層神經網絡相當於單層神經網絡)。

卷積核的參數

n爲輸入圖像大小。

池化

基本計算

池化默認步長與核相等,卷積默認步長爲1。

(1)最大值池化;(2)平均值池化。

池化的特點

精度與計算量的trade off。

(1)常使用不重疊、不補零;

(2)沒有用於求導的參數;

(3)池化層參數爲步長和池化核大小;

(4)用於減少圖像尺寸,從而減少計算量;

(5)一定程度解決平移魯棒;

(6)損失了空間位置精度。

全連接

全卷積之後不能再加捲積和池化層。

全連接層的參數數目佔據整個神經網絡參數的大部分(約60%~80%)。

(1)將上一層輸出展開並連接到每一個神經元上;

(2)即普通神經網絡的層;

(3)相比於卷積層,參數數目較大。

參數數目 = Ci * Co

(Ci/Co爲輸入輸出通道數目)

卷積神經網絡結構

卷積神經網絡

卷積神經網絡 = 卷積層 + 池化層 + 全連接層

圖像 --> 圖像的操作:去除全連接層;

小圖 --> 大圖:反捲積。

全卷積神經網絡

全卷積神經網絡 = 卷積層 + 池化層

代碼

TensorFlow實現:卷積層與池化層

conv1 = tf.layers.conv2d(x_image,
                         32, # output channel number
                         (3,3), # kernel size
                         padding = 'same',
                         activation = tf.nn.relu,
                         name = 'conv1')
# 16 * 16
pooling1 = tf.layers.max_pooling2d(conv1,
                                   (2, 2), # kernel size
                                   (2, 2), # stride
                                   name = 'pool1')
conv2 = tf.layers.conv2d(pooling1,
                         32, # output channel number
                         (3,3), # kernel size
                         padding = 'same',
                         activation = tf.nn.relu,
                         name = 'conv2')
# 8 * 8
pooling2 = tf.layers.max_pooling2d(conv2,
                                   (2, 2), # kernel size
                                   (2, 2), # stride
                                   name = 'pool2')
conv3 = tf.layers.conv2d(pooling2,
                         32, # output channel number
                         (3,3), # kernel size
                         padding = 'same',
                         activation = tf.nn.relu,
                         name = 'conv3')
# 4 * 4 * 32
pooling3 = tf.layers.max_pooling2d(conv3,
                                   (2, 2), # kernel size
                                   (2, 2), # stride
                                   name = 'pool3')

TensorFlow實現:全連接層

# [None, 4 * 4 * 32]
flatten = tf.layers.flatten(pooling3)

TensorFlow實現:卷積神經網絡

x = tf.placeholder(tf.float32, [None, 3072])
y = tf.placeholder(tf.int64, [None])
# [None], eg: [0,5,6,3]
x_image = tf.reshape(x, [-1, 3, 32, 32])
# 32*32
x_image = tf.transpose(x_image, perm=[0, 2, 3, 1])

conv1 = tf.layers.conv2d(x_image,
                         32, # output channel number
                         (3,3), # kernel size
                         padding = 'same',
                         activation = tf.nn.relu,
                         name = 'conv1')
# 16 * 16
pooling1 = tf.layers.max_pooling2d(conv1,
                                   (2, 2), # kernel size
                                   (2, 2), # stride
                                   name = 'pool1')
conv2 = tf.layers.conv2d(pooling1,
                         32, # output channel number
                         (3,3), # kernel size
                         padding = 'same',
                         activation = tf.nn.relu,
                         name = 'conv2')
# 8 * 8
pooling2 = tf.layers.max_pooling2d(conv2,
                                   (2, 2), # kernel size
                                   (2, 2), # stride
                                   name = 'pool2')
conv3 = tf.layers.conv2d(pooling2,
                         32, # output channel number
                         (3,3), # kernel size
                         padding = 'same',
                         activation = tf.nn.relu,
                         name = 'conv3')
# 4 * 4 * 32
pooling3 = tf.layers.max_pooling2d(conv3,
                                   (2, 2), # kernel size
                                   (2, 2), # stride
                                   name = 'pool3')
# [None, 4 * 4 * 32]
flatten = tf.layers.flatten(pooling3)
y_ = tf.layers.dense(flatten, 10)

loss = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=y_)
# y_ -> sofmax
# y -> one_hot
# loss = ylogy_

# indices
predict = tf.argmax(y_, 1)
# [1,0,1,1,1,0,0,0]
correct_prediction = tf.equal(predict, y)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float64))

with tf.name_scope('train_op'):
    train_op = tf.train.AdamOptimizer(1e-3).minimize(loss)

參考資料

圖片、內容引自:https://coding.imooc.com/class/259.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章