反向傳播(Backpropagation)
反向傳播是計算梯度的算法,核心作用是高效求解 “損失函數對模型所有參數的偏導數”(即梯度)。沒有反向傳播,深度學習的大規模訓練幾乎不可能實現。?
?
整個過程像 “從終點回溯到起點”,因此稱為 “反向傳播”。?
# 測試損失函數
loss=nn.CrossEntropyLoss()
for data in dataloader:imgs, targets = dataoutput = module(imgs)result_loss=loss(output,targets)# print(result_loss)# 反向傳播result_loss.backward()
優化器(Optimizer)
優化器的作用是根據反向傳播計算的梯度,更新模型參數,最終目的是減小損失。它是 “梯度→參數更新” 的執行者。
1. 核心目標
根據梯度調整參數,使損失函數盡可能小。基本邏輯是: \(參數_{新} = 參數_{舊} - 學習率 \times 梯度\) (“減梯度” 是因為梯度方向是損失增大的方向,反向才能減小損失)
2. 常見優化器及特點
不同優化器通過改進 “梯度使用方式” 提升效果,以下是主流優化器對比:
優化器 | 核心特點 | 適用場景 |
---|---|---|
SGD | 基礎版:直接用當前梯度更新(\(W = W - lr \cdot \nabla Loss\)) | 簡單模型、需要穩定收斂 |
SGD + 動量 | 模擬物理動量:保留部分歷史梯度,減少震蕩(適合非凸損失函數) | 復雜模型(如 CNN)、避免局部最優 |
Adam | 結合動量和自適應學習率(對不同參數用不同學習率),收斂快且穩定 | 大部分場景(推薦新手首選) |
RMSprop | 自適應學習率:對頻繁變化的參數用小學習率,稀疏參數用大學習率 | 處理非平穩目標(如 RNN) |
?
無論哪種優化器,都需要指定兩個基礎參數:
參數 | 含義 | 作用 |
---|---|---|
params | 模型需要更新的參數(如?model.parameters() ) | 告訴優化器 “要調整哪些參數”(必須指定,否則無法定位更新對象) |
lr (learning rate) | 學習率(核心超參數,通常取值?1e-3 、1e-4 ?等) | 控制參數更新的 “步長”: - 過大:可能跳過最優解(不收斂); - 過小:收斂太慢或陷入局部最優 |
?其他參數 依據各個優化器算法的不同而不同
?
代碼案例:?
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoaderdataset = torchvision.datasets.CIFAR10("../torchvision_dataset", train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset, batch_size=1)class MyModule(nn.Module):def __init__(self):super().__init__()self.model1 = Sequential(Conv2d(3, 32, 5, stride=1, padding=2),MaxPool2d(2),Conv2d(32, 32, 5, stride=1, padding=2),MaxPool2d(2),Conv2d(32, 64, 5, stride=1, padding=2),MaxPool2d(2),Flatten(),Linear(1024, 64),Linear(64, 10),)def forward(self, x):x = self.model1(x)return xmodule = MyModule()
loss=nn.CrossEntropyLoss()
# 隨機梯度下降(SGD)優化器
optim=torch.optim.SGD(module.parameters(),lr=0.001)
for epo in range(20):running_loss=0for data in dataloader:# 每次訓練前,先把各個梯度設為0optim.zero_grad()imgs, targets = dataoutput = module(imgs)result_loss=loss(output,targets)# 反向傳播,依據鏈式法則計算各個梯度result_loss.backward()optim.step()running_loss=result_loss+running_lossprint(running_loss)
看幾輪訓練結果的損失函數值變化?
?