環境
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