深度學習模型的訓練依賴於梯度計算,而計算圖和反向傳播演算法是實作梯度計算的關鍵。計算圖以視覺化的方式展現了計算過程,方便理解複雜的運算流程。反向傳播演算法則利用鏈式法則,高效地計算梯度,進而更新模型引數。本文將逐步介紹計算圖、矩陣運算、啟用函式以及反向傳播演算法的原理和 Python 程式碼實作,幫助讀者深入理解深度學習的基本。
1.18 圖表翻譯:新增啟用函式的計算圖
現在,我們將新增一個啟用函式 $\sigma$ 到計算圖中。這個函式將矩陣乘法的結果作為輸入,並輸出一個新的值 $S$。
程式碼實作
import numpy as np
def matmul_backward_first(X: np.ndarray, W: np.ndarray) -> np.ndarray:
"""
計算矩陣乘法的反向傳播相對於第一個引數的梯度。
"""
# 計算梯度
dNdX = np.transpose(W, (1, 0))
return dNdX
def matrix_forward_extra(X: np.ndarray, W: np.ndarray, sigma: callable) -> np.ndarray:
"""
計算矩陣乘法的結果並將其傳入啟用函式。
"""
# 驗證矩陣形狀
assert X.shape[1] == W.shape[0]
# 進行矩陣乘法
N = np.dot(X, W)
# 將結果傳入啟用函式
S = sigma(N)
return S
內容解密:矩陣乘法的反向傳播
在上面的程式碼中,我們定義了兩個函式:matmul_backward_first
和 matrix_forward_extra
。第一個函式計算了矩陣乘法的反向傳播相對於第一個引數的梯度,而第二個函式則計算了矩陣乘法的結果並將其傳入啟用函式。
圖表翻譯:計算圖
以下是計算圖的視覺化表示:
flowchart TD X[輸入矩陣 X] -->|矩陣乘法|> N[矩陣乘法結果] W[輸入矩陣 W] -->|矩陣乘法|> N N -->|傳入啟用函式|> S[啟用函式結果]
這個計算圖顯示了矩陣乘法和啟用函式之間的關係。
向量函式的導數:進一步探討
數學表示
考慮向量函式 $S = \sigma(N)$,其中 $\sigma$ 是一個嵌入函式,且 $N$ 是矩陣 $X$ 和 $W$ 的乘積。根據鏈式法則,$S$ 對 $X$ 的偏導數可以表示為:
$$ \frac{\partial S}{\partial X} = \frac{\partial S}{\partial N} \cdot \frac{\partial N}{\partial X} $$
由於 $\sigma$ 是一個連續函式,其導數可以在任何點計算,因此我們可以將 $N$ 的值代入 $\sigma$ 中,得到:
$$ \frac{\partial S}{\partial N} = \sigma’(N) $$
而 $N$ 對 $X$ 的偏導數可以表示為:
$$ \frac{\partial N}{\partial X} = W^T $$
因此,$S$ 對 $X$ 的偏導數可以表示為:
$$ \frac{\partial S}{\partial X} = \sigma’(N) \cdot W^T $$
視覺化
反向傳播的流程可以使用以下圖表表示:
γ [x]
[w] N
(N) Sσ ∂ γ ∂ x ∂ γ ∂ w ∂ σ ∂ u
圖 1.19:向量函式的反向傳播
程式碼實作
以下是反向傳播的程式碼實作:
import numpy as np
def matrix_function_backward_1(X: np.ndarray, W: np.ndarray, sigma: callable) -> np.ndarray:
"""
計算函式 S 對 X 的偏導數。
Parameters:
X (np.ndarray): 輸入矩陣
W (np.ndarray): 權重矩陣
sigma (callable): 啟用函式
Returns:
np.ndarray: 函式 S 對 X 的偏導數
"""
assert X.shape[1] == W.shape[0]
# 矩陣乘法
N = np.dot(X, W)
# 將結果傳入啟用函式
S = sigma(N)
# 計算導數
dSdN = deriv(sigma, N)
dNdX = np.transpose(W, (1, 0))
# 傳回結果
return np.dot(dSdN, dNdX)
注意到,在程式碼中,我們首先計算矩陣乘法的結果 $N$,然後將其傳入啟用函式 $\sigma$ 中。接著,我們計算導數,並傳回結果。
驗證結果
為了驗證結果的正確性,我們可以稍微修改輸入值,並觀察結果的變化。例如,我們可以將輸入矩陣 $X$ 修改為:
print(X)
這樣,我們就可以觀察到結果的變化,並驗證導數的正確性。
重新組織和重寫內容
1.
在機器學習中,瞭解數學基礎是非常重要的。這章節將介紹如何使用計算圖來理解矩陣運算的梯度計算。
2. 計算圖
計算圖是一種視覺化工具,幫助我們理解複雜的計算過程。下面是一個簡單的計算圖範例:
flowchart TD A[輸入] --> B[矩陣乘法] B --> C[啟用函式] C --> D[輸出]
3. 矩陣運算
矩陣運算是機器學習中的一個基本概念。給定兩個矩陣 X 和 W,我們可以計算它們的乘法:
import numpy as np
X = np.array([[1, 2], [3, 4]])
W = np.array([[5, 6], [7, 8]])
N = np.dot(X, W)
4. 啟用函式
啟用函式是一種非線性函式,常用於神經網路中。下面是一個簡單的啟用函式範例:
def sigmoid(x):
return 1 / (1 + np.exp(-x))
S = sigmoid(N)
5. 梯度計算
梯度計算是機器學習中的一個重要概念。給定一個輸出值,我們可以計算它對於輸入值的梯度:
def matrix_function_backward_1(X, W, sigmoid):
# 計算梯度
dS_dN = sigmoid(N) * (1 - sigmoid(N))
dN_dX = W
dN_dW = X
# 計算梯度
dL_dX = dS_dN * dN_dX
dL_dW = dS_dN * dN_dW
return dL_dX, dL_dW
dL_dX, dL_dW = matrix_function_backward_1(X, W, sigmoid)
圖表翻譯:
上述 Mermaid 圖表展示了計算圖的流程,從輸入到輸出,包括矩陣乘法、啟用函式和梯度計算等步驟。這個圖表幫助我們理解複雜的計算過程,使得我們可以更好地掌握機器學習中的數學基礎。
內容解密:
上述程式碼展示瞭如何計算矩陣運算的梯度。首先,我們計算矩陣乘法的結果 N,然後將其傳入啟用函式中,得到 S。接著,我們計算梯度,包括 dS_dN、dN_dX 和 dN_dW 等。最後,我們得到梯度 dL_dX 和 dL_dW。這個過程展示瞭如何使用計算圖來理解矩陣運算的梯度計算。
線性迴歸的反向傳遞
在深度學習中,反向傳遞(Backpropagation)是一種用於訓練神經網路的演算法。它可以用於計算損失函式對模型引數的梯度,從而實作模型的最佳化。在這裡,我們將探討線性迴歸中的反向傳遞。
線性迴歸模型
線性迴歸是一種基本的機器學習模型,假設輸出變數與輸入變數之間存線上性關係。給定輸入資料 $X$ 和權重 $W$,線性迴歸模型可以表示為:
$$N = X \cdot W$$
其中 $N$ 是預測輸出。
損失函式
損失函式(Loss Function)是用於衡量模型預測值與實際值之間差異的函式。常用的損失函式包括均方差(Mean Squared Error, MSE)等。在這裡,我們使用均方差作為損失函式:
$$L = \frac{1}{2} \sum_{i=1}^{n} (y_i - N_i)^2$$
其中 $y_i$ 是實際值,$N_i$ 是預測值。
反向傳遞
反向傳遞是計算損失函式對模型引數的梯度的過程。首先,我們需要計算損失函式對預測輸出 $N$ 的梯度:
$$\frac{\partial L}{\partial N} = - (y - N)$$
接下來,我們需要計算預測輸出 $N$ 對權重 $W$ 的梯度:
$$\frac{\partial N}{\partial W} = X$$
利用鏈式法則(Chain Rule),我們可以計算損失函式對權重 $W$ 的梯度:
$$\frac{\partial L}{\partial W} = \frac{\partial L}{\partial N} \cdot \frac{\partial N}{\partial W} = - (y - N) \cdot X$$
實作
以下是線性迴歸模型的反向傳遞實作:
import numpy as np
def linear_regression(X, W, y):
# 預測輸出
N = np.dot(X, W)
# 損失函式
L = np.sum((y - N) ** 2) / 2
# 反向傳遞
dL_dN = - (y - N)
dN_dW = X
dL_dW = np.dot(dL_dN, dN_dW)
return dL_dW
在這個實作中,我們首先計算預測輸出 $N$,然後計算損失函式 $L$。接下來,我們計算損失函式對預測輸出 $N$ 的梯度,然後計算預測輸出 $N$ 對權重 $W$ 的梯度。最後,我們利用鏈式法則計算損失函式對權重 $W$ 的梯度。
簡介
在深度學習中,計算梯度是訓練模型的關鍵步驟。梯度代表了模型輸出的變化率與輸入的變化率之間的關係。在本文中,我們將探討如何使用鏈式法則(chain rule)計算矩陣函式的梯度。
鏈式法則
鏈式法則是一種用於計算複合函式梯度的方法。給定一個複合函式 $L = f(g(x))$,其中 $f$ 和 $g$ 是兩個函式,鏈式法則可以用於計算 $L$ 對 $x$ 的梯度:
$$ \frac{dL}{dx} = \frac{dL}{dg} \cdot \frac{dg}{dx} $$
在矩陣函式中,我們需要計算矩陣對元素的梯度。假設我們有一個矩陣函式 $L = f(XW)$,其中 $X$ 和 $W$ 是兩個矩陣,$f$ 是一個函式,我們需要計算 $L$ 對 $X$ 的梯度。
矩陣函式的梯度
使用鏈式法則,我們可以將 $L$ 對 $X$ 的梯度計算為:
$$ \frac{dL}{dX} = \frac{dL}{d(XW)} \cdot \frac{d(XW)}{dX} $$
其中,$\frac{dL}{d(XW)}$ 是 $L$ 對 $XW$ 的梯度,$\frac{d(XW)}{dX}$ 是 $XW$ 對 $X$ 的梯度。
實際計算
假設我們有一個矩陣函式 $L = \sum \sigma(XW)$,其中 $\sigma$ 是一個啟用函式,我們需要計算 $L$ 對 $X$ 的梯度。
首先,我們計算 $L$ 對 $XW$ 的梯度:
$$ \frac{dL}{d(XW)} = \frac{d}{d(XW)} \sum \sigma(XW) = \sigma’(XW) $$
其中,$\sigma’$ 是 $\sigma$ 的導數。
接下來,我們計算 $XW$ 對 $X$ 的梯度:
$$ \frac{d(XW)}{dX} = W^T $$
其中,$W^T$ 是 $W$ 的轉置。
最後,我們計算 $L$ 對 $X$ 的梯度:
$$ \frac{dL}{dX} = \frac{dL}{d(XW)} \cdot \frac{d(XW)}{dX} = \sigma’(XW) \cdot W^T $$
程式碼實作
以下是使用 Python 和 NumPy 實作的程式碼:
import numpy as np
def matrix_function_backward_sum_1(X, W, sigma):
# 計算 XW
N = np.dot(X, W)
# 計算 L 對 XW 的梯度
dLdN = sigma(N)
# 計算 XW 對 X 的梯度
dNdX = np.transpose(W, (1, 0))
# 計算 L 對 X 的梯度
dLdX = dLdN * dNdX
return dLdX
在這個程式碼中,我們首先計算 $XW$,然後計算 $L$ 對 $XW$ 的梯度,接下來計算 $XW$ 對 $X$ 的梯度,最後計算 $L$ 對 $X$ 的梯度。
神經網路的基礎:從矩陣運算到反向傳播
在深度學習中,神經網路的核心是矩陣運算和反向傳播。要了解神經網路的工作原理,我們需要從基本的矩陣運算開始。
矩陣運算
矩陣運算是神經網路中最基本的運算單元。給定兩個矩陣 X
和 W
,我們可以計算其乘積 X * W
。在 Python 中,我們可以使用 NumPy 函式庫來實作矩陣運算。
import numpy as np
# 初始化隨機數
np.random.seed(190204)
# 定義矩陣 X 和 W
X = np.random.randn(3, 3)
W = np.random.randn(3, 2)
# 計算矩陣乘積
result = np.dot(X, W)
sigmoid 函式
sigmoid 函式是一種常用的啟用函式,用於將輸入對映到 (0, 1) 的範圍內。sigmoid 函式的公式為:
$$\sigma(x) = \frac{1}{1 + e^{-x}}$$
在 Python 中,我們可以使用以下程式碼來實作 sigmoid 函式:
def sigmoid(x):
return 1 / (1 + np.exp(-x))
前向傳播
前向傳播是神經網路中的一個過程,用於計算輸出的值。給定輸入 X
和權重 W
,我們可以計算輸出 L
。
def matrix_function_forward_sum(X, W, sigmoid):
# 計算矩陣乘積
result = np.dot(X, W)
# 應用 sigmoid 函式
result = sigmoid(result)
# 傳回結果
return result
反向傳播
反向傳播是神經網路中的一個過程,用於計算梯度。給定輸入 X
、權重 W
和損失函式 L
,我們可以計算梯度 dLdX
。
def matrix_function_backward_sum_1(X, W, sigmoid):
# 計算矩陣乘積
result = np.dot(X, W)
# 應用 sigmoid 函式
result = sigmoid(result)
# 計算梯度
dSdN = 1 # 假設損失函式為 1
dNdX = result * (1 - result) # sigmoid 函式的導函式
# 計算梯度 dLdX
dLdX = np.dot(dSdN, dNdX)
# 傳回結果
return dLdX
測試
現在,我們可以測試以上程式碼了。
print("X:")
print(X)
print("L:")
print(round(matrix_function_forward_sum(X, W, sigmoid), 4))
print()
print("dLdX:")
print(matrix_function_backward_sum_1(X, W, sigmoid))
這些程式碼將會輸出矩陣 X
、輸出 L
和梯度 dLdX
。
簡介神經網路的反向傳播
在神經網路中,反向傳播(Backpropagation)是一種用於訓練人工神經網路的演算法。它的主要目的是計算神經網路中每個引數的梯度,以便於使用最佳化演算法更新這些引數,從而最小化損失函式。
基本概念
在反向傳播中,我們首先計算輸出層的誤差梯度,然後將其反向傳播到隱藏層和輸入層。這個過程涉及到計算每個神經元的輸出對於損失函式的梯度。
步驟
- 前向傳播:首先,我們需要計算神經網路的前向傳播結果,也就是輸出層的輸出。
- 計算誤差梯度:然後,我們計算輸出層的誤差梯度,也就是損失函式對於輸出層輸出的梯度。
- 反向傳播:接下來,我們將誤差梯度反向傳播到隱藏層和輸入層,計算每個神經元的輸出對於損失函式的梯度。
- 更新引數:最後,我們使用最佳化演算法更新神經網路中的引數,以最小化損失函式。
實作
在實作反向傳播時,我們需要計算每個神經元的輸出對於損失函式的梯度。這可以透過以下公式實作:
$$ \frac{\partial L}{\partial x_i} = \frac{\partial L}{\partial y_i} \cdot \frac{\partial y_i}{\partial x_i} $$
其中,$L$ 是損失函式,$x_i$ 是第 $i$ 個神經元的輸入,$y_i$ 是第 $i$ 個神經元的輸出。
範例
假設我們有一個簡單的神經網路,包含一個輸入層、一個隱藏層和一個輸出層。輸入層有兩個神經元,隱藏層有三個神經元,輸出層有一個神經元。損失函式是均方差。
import numpy as np
# 定義神經網路的結構
input_dim = 2
hidden_dim = 3
output_dim = 1
# 初始化權重和偏置
weights1 = np.random.rand(input_dim, hidden_dim)
weights2 = np.random.rand(hidden_dim, output_dim)
bias1 = np.zeros((1, hidden_dim))
bias2 = np.zeros((1, output_dim))
# 定義啟用函式
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 定義損失函式
def loss(y_pred, y_true):
return np.mean((y_pred - y_true) ** 2)
# 前向傳播
def forward(x):
hidden_layer = sigmoid(np.dot(x, weights1) + bias1)
output_layer = sigmoid(np.dot(hidden_layer, weights2) + bias2)
return hidden_layer, output_layer
# 反向傳播
def backward(x, y_true, hidden_layer, output_layer):
d_output_layer = 2 * (output_layer - y_true) * output_layer * (1 - output_layer)
d_weights2 = np.dot(hidden_layer.T, d_output_layer)
d_bias2 = np.sum(d_output_layer, axis=0, keepdims=True)
d_hidden_layer = np.dot(d_output_layer, weights2.T) * hidden_layer * (1 - hidden_layer)
d_weights1 = np.dot(x.T, d_hidden_layer)
d_bias1 = np.sum(d_hidden_layer, axis=0, keepdims=True)
return d_weights1, d_bias1, d_weights2, d_bias2
# 訓練神經網路
x = np.array([[0.5, 0.3]])
y_true = np.array([[0.8]])
for i in range(1000):
hidden_layer, output_layer = forward(x)
d_weights1, d_bias1, d_weights2, d_bias2 = backward(x, y_true, hidden_layer, output_layer)
weights1 -= 0.01 * d_weights1
bias1 -= 0.01 * d_bias1
weights2 -= 0.01 * d_weights2
bias2 -= 0.01 * d_bias2
print(loss(output_layer, y_true))
這個範例展示瞭如何使用反向傳播演算法訓練一個簡單的神經網路。
深度學習基礎
在前一章中,您已經學習了深度學習的基礎數學知識,包括巢狀函式、連續函式和可微分函式。您還學習瞭如何將這些函式表示為計算圖,每個節點代表一個簡單的函式。此外,您已經知道如何計算巢狀函式的導數,即透過計算每個組成部分的導數並將它們相乘。
現在,我們將進一步探討深度學習的基礎知識。首先,我們將建立一個線性迴歸模型,然後觀察其訓練過程。接下來,我們將擴充套件這個模型為單層神經網路。
線性迴歸模型
線性迴歸是一種最常見的機器學習模型,它試圖找到一條直線來最好地描述輸入資料和輸出資料之間的關係。給定輸入資料 $X$ 和輸出資料 $y$,我們可以建立一個線性迴歸模型來預測輸出資料。
線性迴歸模型的建立
假設我們有 $n$ 個樣本,每個樣本有 $m$ 個特徵。輸入資料 $X$ 可以表示為一個 $n \times m$ 的矩陣,每行代表一個樣本,每列代表一個特徵。輸出資料 $y$ 可以表示為一個 $n \times 1$ 的矩陣,每行代表一個樣本的輸出值。
線性迴歸模型可以表示為:
$$y = Xw + b$$
其中 $w$ 是一個 $m \times 1$ 的權重矩陣,$b$ 是一個偏差項。
線性迴歸模型的訓練
線性迴歸模型的訓練目的是找到最佳的權重 $w$ 和偏差 $b$,使得模型對輸入資料的預測值與實際輸出值之間的誤差最小。
給定輸入資料 $X$ 和輸出資料 $y$,我們可以使用以下損失函式來評估模型的效能:
$$L = \frac{1}{2} \sum_{i=1}^n (y_i - (Xw + b)_i)^2$$
其中 $y_i$ 是第 $i$ 個樣本的實際輸出值,$(Xw + b)_i$ 是第 $i$ 個樣本的預測值。
單層神經網路
單層神經網路是一種簡單的神經網路,它只有一個隱藏層。給定輸入資料 $X$,單層神經網路可以表示為:
$$y = \sigma(Xw + b)$$
其中 $\sigma$ 是啟用函式,$w$ 是權重矩陣,$b$ 是偏差項。
單層神經網路的訓練
單層神經網路的訓練目的是找到最佳的權重 $w$ 和偏差 $b$,使得模型對輸入資料的預測值與實際輸出值之間的誤差最小。
給定輸入資料 $X$ 和輸出資料 $y$,我們可以使用以下損失函式來評估模型的效能:
$$L = \frac{1}{2} \sum_{i=1}^n (y_i - \sigma(Xw + b)_i)^2$$
其中 $y_i$ 是第 $i$ 個樣本的實際輸出值,$\sigma(Xw + b)_i$ 是第 $i$ 個樣本的預測值。
從技術架構視角來看,本文逐步拆解了神經網路反向傳播的計算過程,從單個啟用函式的引入到線性迴歸模型,再到單層神經網路,層層遞進,清晰地闡述了梯度計算的原理和方法。 分析段落中,程式碼示例與數學公式的結合,有效地降低了理解難度,同時也展現了反向傳播的實際應用。文章雖然聚焦於基礎概念,但深入淺出地解釋了鏈式法則在矩陣運算中的應用,並藉由計算圖的視覺化,更進一步強化了讀者對梯度計算流程的理解。技術限制深析方面,文章可以更明確地指出不同啟用函式的選擇對梯度計算的影響,以及在高維資料和複雜網路結構下可能遇到的計算挑戰。展望未來,隨著深度學習模型的日益複雜,更高效的梯度計算方法和硬體加速技術將成為研究熱點。對於初學者,理解這些基礎概念至關重要,它將為進一步學習更複雜的神經網路架構奠定堅實基礎。 玄貓認為,掌握反向傳播的原理和實作方法,是深入理解和應用深度學習技術的關鍵所在。