反向傳播 - 神經網路的核心
反向傳播的目標是優化權重,以便神經網路可以學習如何正確地將任意輸入對映到輸出。
每一層都有自己的一組權重,必須調整這些權重,以便能夠準確預測給定輸入的正確輸出。
反向傳播的高階概述如下:
- 正向傳遞 - 輸入轉換為某些輸出。在每一層,使用輸入和權重之間的點積計算啟用,然後將結果與偏差相加。最後,該值通過啟用函式傳遞,以啟用該層,該層將成為下一層的輸入。
- 在最後一層中,將輸出與對應於該輸入的實際標籤進行比較,並計算錯誤。通常,它是均方誤差。
- 向後傳遞 - 將步驟 2 中計算的誤差傳播回內層,並調整所有層的權重以解決此錯誤。
1.權重初始化
權重初始化的簡化示例如下所示:
layers = [784, 64, 10]
weights = np.array([(np.random.randn(y, x) * np.sqrt(2.0 / (x + y))) for x, y in zip(layers[:-1], layers[1:])])
biases = np.array([np.zeros((y, 1)) for y in layers[1:]])
-
隱藏層 1 具有尺寸[64,784]的重量和尺寸 64 的偏差。
-
輸出層具有維度[10,64]的權重和維度的偏差
你可能想知道在上面的程式碼中初始化權重時發生了什麼。這稱為 Xavier 初始化,它比隨機初始化權重矩陣更好一步。是的,初始化確實很重要。根據你的初始化,你可能能夠在梯度下降期間找到更好的區域性最小值(反向傳播是梯度下降的美化版本)。
2.前往通行證
activation = x
hidden_activations = [np.reshape(x, (len(x), 1))]
z_list = []
for w, b in zip(self.weights, self.biases):
z = np.dot(w, np.reshape(activation, (len(activation), 1))) + b
z_list.append(z)
activation = relu(z)
hidden_activations.append(activation)
t = hidden_activations[-1]
hidden_activations[-1] = np.exp(t) / np.sum(np.exp(t))
該程式碼執行上述轉換。hidden_activations[-1]
包含 softmax 概率 - 所有類的預測,其總和為 1.如果我們預測數字,則輸出將是維度 10 的概率向量,其總和為 1。
3.後退通行證
weight_gradients = [np.zeros(w.shape) for w in self.weights]
bias_gradients = [np.zeros(b.shape) for b in self.biases]
delta = (hidden_activations[-1] - y) * (z_list[-1] > 0) # relu derivative
weight_gradients[-1] = np.dot(delta, hidden_activations[-2].T)
bias_gradients[-1] = delta
for l in range(2, self.num_layers):
z = z_list[-l]
delta = np.dot(self.weights[-l + 1].T, delta) * (z > 0) # relu derivative
weight_gradients[-l] = np.dot(delta, hidden_activations[-l - 1].T)
bias_gradients[-l] = delta
前兩行初始化漸變。計算這些梯度,並將用於稍後更新權重和偏差。
接下來的 3 行通過從目標中減去預測來計算誤差。然後將錯誤反饋傳播到內層。
現在,仔細跟蹤迴圈的工作。第 2 行和第 3 行將錯誤從 layer[i]
轉換為 layer[i - 1]
。跟蹤乘以矩陣的形狀以理解。
4.重量/引數更新
for i in xrange(len(self.weights)):
self.weights[i] += -self.learning_rate * weight_gradients[i]
self.biases[i] += -self.learning_rate * bias_gradients[i]
self.learning_rate
指定網路學習的速率。你不希望它學得太快,因為它可能不會收斂。平穩下降有利於找到一個好的最小值。通常,0.01
和 0.1
之間的比率被認為是好的。