一、CNN簡介
卷積神經網絡(Convolutional Neural Network,簡稱CNN)已經成為計算機視覺領域內的一種重要的深度學習網絡結構,主要用於圖像識別、目標檢測、圖像分割等任務。與傳統的神經網絡相比,CNN利用局部感受野、參數共享、下採樣等操作可以大大減少網絡參數數量,並且可以有效提取圖像特徵。
二、CNN反向傳播介紹
CNN反向傳播是CNN的訓練算法,是一種基於梯度下降的方法,用於權值(weight)的優化,從而讓網絡能夠更好地擬合數據。它的基本思想是通過計算預測值與真實值之間的誤差,通過鏈式法則將誤差從輸出層一直向前傳遞,最終得到每一層的梯度,以此來更新每一層的權值和偏差(bias)。它的前提條件是我們已經有一批已經標註的數據,通過CNN反向傳播算法來調整權重和偏差,使得損失函數最小。
三、CNN反向傳播原理
3.1 前向傳播
在訓練CNN之前,需要我們先對一張圖像進行前向傳播,計算出卷積層、池化層、全連接層的輸出層數據(預測值)。具體步驟如下:
for each conv layer do:
conv_output = convolve(filter, input)
pooled_output = max_pool(conv_output)
input = pooled_output
flatten_input = flatten(pooled_output)
for each fc layer do:
fc_output = active_function(W * flatten_input + b)
flatten_input = fc_output
3.2 反向傳播
在計算出預測值之後,我們需要計算誤差以及梯度,為接下來的優化提供基礎。CNN反向傳播的流程可以分為以下幾個步驟:
3.2.1 計算第n層的誤差$\delta_n$
在反向傳播的過程中,我們需要從輸出層開始計算誤差,從而逐層往回傳遞,計算出每一層的誤差。具體計算公式如下:
$$\delta_n = \frac{\partial L}{\partial z_n}$$
其中,$z_n$表示第n層的加權輸入,$L$表示最終的損失函數,對於分類問題,通常採用交叉熵(Cross-Entropy)作為損失函數。
3.2.2 計算第n層的權重梯度$\frac{\partial L}{\partial W_n}$和偏差梯度$\frac{\partial L}{\partial b_n}$
根據鏈式法則,我們可以根據上層的誤差$\delta_{n+1}$和當前層的加權輸入$z_n$,計算出當前層的誤差$\delta_n$。然後,利用誤差和上一層輸出(或者輸入)的值,計算出該層的權重和偏差的梯度。
$$\frac{\partial L}{\partial W_n} = a_{n-1} \delta_n$$
$$\frac{\partial L}{\partial b_n} = \delta_n$$
3.2.3 計算第n-1層的誤差$\delta_{n-1}$
通過誤差反向傳播的過程,我們可以計算出每一層的誤差$\delta_n$,然後通過$\delta_{n-1} = f'(\phi_{n-1})W_n^T\delta_n $(其中$f'(\phi_{n-1})$表示激活函數的導數,$\phi_{n-1}$表示第n-1層的加權輸入)來計算前一層的誤差。
3.2.4 更新權重和偏差
我們可以根據之前計算出的權重和偏差梯度,利用梯度下降的算法,更新權重和偏差,來不斷縮小損失函數。具體算法如下:
$$W_n = W_n – \alpha\frac{\partial L}{\partial W_n}$$
$$b_n = b_n – \alpha\frac{\partial L}{\partial b_n}$$
其中,$\alpha$是學習率,表示每次更新的步長。
四、CNN反向傳播代碼實現
4.1 前向傳播
def forward_propagation(X, parameters):
"""
Implement the forward propagation of the CNN
Arguments:
X -- input data of shape (input_shape, number of examples)
parameters -- python dictionary with parameters "W1", "b1", ..., "WL", "bL"
W1 -- filter matrix of shape (f1, f1, depth_prev, channels)
b1 -- bias vector of shape (1, 1, 1, channels)
...
WL -- filter matrix of shape (fL, fL, depth_L-1, channels_L)
bL -- bias vector of shape (1, 1, 1, channels_L)
Returns:
output_layer -- output of the last fully connected layer
caches -- list of caches for each layer
"""
caches = []
A = X
L = len(parameters) // 2
# conv and pooling layers
for l in range(1, L+1):
W = parameters['W' + str(l)]
b = parameters['b' + str(l)]
conv_output, conv_cache = conv_forward(A, W, b, stride=1, padding='valid') # convolutional layer
pooled_output, pool_cache = pool_forward(conv_output, mode='max', pool_size=2, stride=2) # pooling layer
cache = (conv_cache, pool_cache)
caches.append(cache)
A = pooled_output
# flatten layer
flatten_input, shape_input = flatten(A)
# fully connected layers
for l in range(L+1, 2*L):
W = parameters['W' + str(l)]
b = parameters['b' + str(l)]
fc_output, fc_cache = fc_forward(flatten_input, W, b, activation='relu')
cache = (fc_cache, shape_input)
caches.append(cache)
flatten_input = fc_output
# output layer
W = parameters['W' + str(2*L)]
b = parameters['b' + str(2*L)]
output_layer, output_cache = fc_forward(flatten_input, W, b, activation='softmax')
caches.append(output_cache)
return output_layer, caches
4.2 反向傳播
def backward_propagation(Y, output_layer, caches):
"""
Implement the backward propagation of the CNN
Arguments:
Y -- true "label" vector (containing 0 and 1) of shape (output_shape, number of examples)
output_layer -- output of the last fully connected layer
caches -- list of caches for each layer
Returns:
gradients -- python dictionary with gradients for each parameter
"""
gradients = {}
L = len(caches)
m = Y.shape[1]
# output layer
delta = softmax_backward(output_layer, Y)
cache = caches[L-1]
fc_cache, _ = cache
dflatten_input, dW, db = fc_backward(delta, fc_cache, activation='softmax')
gradients['dW' + str(L)] = dW
gradients['db' + str(L)] = db
# fully connected layers
for l in reversed(range(L-1, L//2, -1)):
cache = caches[l]
fc_cache, shape_input = cache
dflatten_input, dW, db = fc_backward(dflatten_input, fc_cache, activation='relu')
gradients['dW' + str(l+1)] = dW
gradients['db' + str(l+1)] = db
# flatten layer
dA = flatten_backward(dflatten_input, shape_input)
# conv and pooling layers
for l in reversed(range(L//2)):
cache = caches[l]
conv_cache, pool_cache = cache
dpooled_output = pool_backward(dA, pool_cache, mode='max', pool_size=2, stride=2)
dA, dW, db = conv_backward(dpooled_output, conv_cache)
gradients['dW' + str(l+1)] = dW
gradients['db' + str(l+1)] = db
return gradients
五、總結
通過對CNN反向傳播原理和代碼實現的講解,我們對CNN的訓練過程有了更深入的認識。在CNN的訓練過程中,反向傳播算法是非常重要的一環,通過鏈式法則計算出誤差和梯度,再利用梯度下降的方法更新權重和偏差,從而達到訓練的目的。我們可以看到,雖然CNN的網絡結構很複雜,但藉助於反向傳播算法,我們可以非常簡單地實現CNN的訓練過程。相信通過深入地學習和練習,我們一定可以創建出更加優秀的CNN模型。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/246187.html
微信掃一掃
支付寶掃一掃