-
Notifications
You must be signed in to change notification settings - Fork 16
backProp2
本文為 ChatGPT 寫的,但有點不好懂,Karpathy 有寫一個簡單的《梯度引擎》(反傳遞演算法的核心) 程式,然後我利用 ChatGPT 來解說,請參考下文。
在深度學習中,前向傳遞和反向傳遞是深度學習模型中最重要的兩個步驟。這兩個步驟分別是模型的預測和模型參數的更新,是實現深度學習的核心步驟。
前向傳遞是指將輸入通過神經網絡進行運算,得到預測值的過程。它包括以下步驟:
- 將輸入送入神經網絡中的第一層;
- 通過第一層的運算,得到第二層的輸入;
- 通過第二層的運算,得到第三層的輸入;
- 以此類推,直到得到輸出。
在這個過程中,每一層的運算都是由神經網絡中的權重和偏置所決定的。
反向傳遞是指通過梯度下降法,計算出每個參數的梯度,以此來更新參數的過程。它包括以下步驟:
- 計算出損失函數對輸出的偏導數;
- 將輸出的偏導數通過每一層的運算,計算出每一層的偏導數;
- 通過偏導數和鏈式法則,計算出每個參數的梯度;
- 使用梯度下降法,更新每個參數的值。
- 反向傳遞的過程中,每一層的偏導數都是由上一層的偏導數和該層的運算所決定的。
前向傳遞和反向傳遞是密切相關的,它們共同完成了深度學習模型的訓練。具體來說,前向傳遞計算出了預測值,而反向傳遞計算出了每個參數的梯度,這些梯度用於更新參數的值,使得預測值更接近實際值。
在深度學習模型中,模型的訓練過程就是通過損失函數反向傳遞誤差,更新模型參數的過程。反向傳遞算法就是用來計算損失函數對模型參數的梯度。
假設我們有一個前向傳遞的計算過程:
其中,
反向傳遞算法的主要思路是利用鏈式法則(chain rule)來計算損失函數對模型參數的偏導數。具體來說,反向傳遞算法分為以下幾步:
- 正向傳遞計算模型輸出
$y$ - 計算損失函數
$L$ 對$y$ 的偏導數$\frac{\partial L}{\partial y}$ - 用鏈式法則計算
$L$ 對每一個參數的偏導數$\frac{\partial L}{\partial f_3}$ 、$\frac{\partial L}{\partial f_2}$ 和$\frac{\partial L}{\partial f_1}$ - 利用計算出來的偏導數,應用梯度下降等最優化算法來更新參數。
其中,步驟 2 和 3 是反向傳遞算法的核心。在進行反向傳遞之前,需要先將模型的參數進行初始化。在每一次迭代中,將損失函數對模型參數的偏導數通過梯度下降法更新模型參數,直到損失函數收斂或達到最大迭代次數為止。
在反向傳遞的過程中,我們需要計算每個參數的梯度,以便更新它們以最小化損失函數。使用鏈式法則,我們可以通過將損失函數的梯度向量乘以每個參數的局部梯度來計算每個參數的梯度。
具體來說,對於一個參數
其中
對於一個具有多個參數的模型,我們可以通過將每個參數的梯度存儲在一個梯度向量
在實現反向傳遞時,我們通常使用自動微分框架(例如 PyTorch)來計算梯度,該框架可以根據正向計算圖自動計算梯度,從而省去手動計算梯度的繁瑣過程。
反傳遞演算法(backpropagation algorithm)是深度學習中常用的一種訓練神經網絡的方法。該算法利用梯度下降法對神經網絡的參數進行更新,以使得神經網絡的輸出盡可能地接近標籤(label)。
反傳遞演算法的實現包括以下幾個步驟:
- 前向傳遞(forward propagation):計算神經網絡的輸出。
- 計算損失(loss):根據神經網絡的輸出和標籤計算損失。
- 反向傳遞(backward propagation):計算每個參數對損失的梯度。
- 參數更新:根據梯度下降法對參數進行更新。
以下是反傳遞演算法的具體實現步驟:
-
前向傳遞(forward propagation):
對於每一個訓練樣本,計算神經網絡的輸出。
以多層感知機(MLP)為例,對於一個訓練樣本
$x_i$ ,其輸出可以表示為:$$y_i = f(W_2 f(W_1 x_i + b_1) + b_2)$$ 其中,
$W_1$ 和$W_2$ 分別表示第一層和第二層的權重矩陣,$b_1$ 和$b_2$ 分別表示第一層和第二層的偏差向量,$f$ 表示激活函數。 -
計算損失(loss):
根據神經網絡的輸出和標籤計算損失。
以分類問題為例,訓練樣本的標籤可以表示為
$y_{i, label}$ ,損失可以表示為:$$L_i = -\sum_{k=1}^K y_{i, label}^k \log y_i^k$$ 其中,
$K$ 表示分類的類別數。 -
反向傳遞(backward propagation):
計算每個參數對損失的梯度。
在實現反向傳播演算法時,需要注意以下幾個細節:
-
梯度初始化:在訓練模型之前,需要將權重和偏差的梯度初始化為0。這可以通過在模型中定義一個zero_grad函數來實現。
-
參數更新:在計算完每個參數的梯度後,需要使用梯度下降法或其他優化算法來更新參數值。
-
梯度裁剪:由於深度學習模型中存在梯度爆炸或梯度消失的問題,因此需要對梯度進行裁剪。這可以通過計算梯度的L2範數並將其截斷為一個給定的閾值來實現。
-
批次處理:通常在訓練過程中使用批次處理來加快訓練速度。在反向傳播過程中,需要將每個批次的損失和梯度相加,然後將其除以批次大小,以獲得平均損失和梯度。
以下是一個使用PyTorch實現反向傳播的例子:
import torch
import torch.nn as nn
import torch.optim as optim
# 定義一個簡單的線性模型
class LinearModel(nn.Module):
def __init__(self):
super(LinearModel, self).__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x):
return self.linear(x)
# 初始化模型和優化器
model = LinearModel()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 設置損失函數
criterion = nn.MSELoss()
# 設置訓練數據
x_train = torch.Tensor([[1.0], [2.0], [3.0], [4.0]])
y_train = torch.Tensor([[2.0], [4.0], [6.0], [8.0]])
# 訓練模型
for epoch in range(100):
# 前向傳播
y_pred = model(x_train)
# 計算損失
loss = criterion(y_pred, y_train)
# 反向傳播
optimizer.zero_grad()
loss.backward()
nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) # 梯度裁剪
optimizer.step()
# 輸出損失
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, 100, loss.item()))