1. 爲什麼需要損失函數和訓練循環?¶
在機器學習中,模型的目標是“學習”數據中的規律,而損失函數(Loss Function)和訓練循環(Training Loop)是實現這一目標的核心工具。
- 損失函數:衡量模型預測結果與真實標籤的差距,相當於給模型“打分”。差距越小,分數越高,模型越“優秀”。
- 訓練循環:通過調整模型參數,不斷減小損失的過程。就像學生做題時根據錯題(損失)修正答案(參數),最終讓分數(模型精度)提高。
2. 損失函數:模型的“差距度量”¶
2.1 什麼是損失函數?¶
損失函數是一個數學公式,輸入模型的預測值(如分類的概率、迴歸的數值)和真實標籤,輸出一個非負的“差距值”。Pytorch提供了多種預定義損失函數,針對不同任務(分類/迴歸)設計。
2.2 常用損失函數(新手必學)¶
- MSE損失(均方誤差):適用於迴歸任務(預測連續值,如房價、溫度)。
- 公式:\(L = \frac{1}{n}\sum_{i=1}^{n}(y_{pred,i} - y_{true,i})^2\)
- Pytorch調用:
loss_fn = torch.nn.MSELoss() -
例子:預測房價時,MSE衡量“預測房價”與“真實房價”的平均平方差。
-
CrossEntropy損失(交叉熵):適用於分類任務(預測離散類別,如“貓/狗”“0-9數字”)。
- 公式:\(L = -\frac{1}{n}\sum_{i=1}^{n}\sum_{c=1}^{C}y_{true,i,c} \log(y_{pred,i,c})\)
- Pytorch調用:
loss_fn = torch.nn.CrossEntropyLoss() - 注意:輸入需是模型輸出的“原始分數”(logits,未經過softmax),目標標籤是類別索引(如0、1、2)。
3. 訓練循環:模型如何“學習”?¶
訓練循環是模型通過調整參數減小損失的具體步驟,核心分爲4步:前向傳播→計算損失→反向傳播→參數更新。
3.1 訓練循環核心步驟¶
-
前向傳播(Forward Pass):將輸入數據送入模型,得到預測結果(y_pred)。
- 代碼:y_pred = model(x)(x是輸入數據,model是定義的模型) -
計算損失(Compute Loss):用損失函數對比y_pred和真實標籤(y_true),得到損失值。
- 代碼:loss = loss_fn(y_pred, y_true) -
反向傳播(Backward Pass):計算損失對模型參數的梯度(即“哪裏需要改”)。
- 代碼:loss.backward()(Pytorch自動計算梯度,無需手動推導) -
參數更新(Update Parameters):通過優化器(如SGD、Adam)根據梯度調整模型參數。
- 代碼:optimizer.step()(優化器會根據梯度更新參數,如optimizer = torch.optim.Adam(model.parameters(), lr=0.01))
4. 完整訓練流程示例(以線性迴歸爲例)¶
下面用一個簡單的線性迴歸任務(預測房價)演示訓練循環,數據和模型都極度簡化。
4.1 準備數據¶
假設我們有100個樣本,每個樣本是1個特徵(如房屋面積),真實關係爲:y = 2x + 3(真實斜率=2,截距=3),並加入隨機噪聲模擬真實數據。
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
# 生成模擬數據
np.random.seed(42) # 固定隨機種子便於復現
x = np.random.randn(100, 1) # 100個樣本,1個特徵
y = 2 * x + 3 + 0.1 * np.random.randn(100, 1) # 真實關係+噪聲
# 轉爲Pytorch張量
x = torch.from_numpy(x).float()
y = torch.from_numpy(y).float()
4.2 定義模型(簡單線性層)¶
用一個線性層模擬房價預測:輸入1個特徵,輸出1個預測值。
class LinearRegression(nn.Module):
def __init__(self):
super(LinearRegression, self).__init__()
self.linear = nn.Linear(1, 1) # 輸入維度1,輸出維度1(即 y = w*x + b)
def forward(self, x):
return self.linear(x) # 前向傳播:返回預測值
model = LinearRegression()
4.3 初始化損失函數和優化器¶
- 損失函數:迴歸任務用MSE。
- 優化器:用Adam優化器,學習率
lr=0.01(控制參數更新幅度)。
loss_fn = nn.MSELoss() # 均方誤差損失
optimizer = optim.Adam(model.parameters(), lr=0.01) # Adam優化器
4.4 訓練循環(核心!)¶
遍歷多個epoch(整個數據集),每次迭代完成“前向→損失→反向→更新”:
epochs = 1000 # 訓練輪數:每個epoch遍歷全部數據
for epoch in range(epochs):
# 1. 前向傳播:計算預測值
y_pred = model(x)
# 2. 計算損失:預測值 vs 真實值
loss = loss_fn(y_pred, y)
# 3. 反向傳播前必須清零梯度(否則梯度會累積)
optimizer.zero_grad()
# 4. 反向傳播:計算梯度
loss.backward()
# 5. 參數更新:根據梯度調整模型參數
optimizer.step()
# 打印進度(每100輪輸出一次)
if (epoch + 1) % 100 == 0:
print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
4.5 訓練結果驗證¶
訓練後,模型參數(w和b)會接近真實值2和3:
# 打印最終參數
print("模型參數 w:", model.linear.weight.item()) # 接近2
print("模型參數 b:", model.linear.bias.item()) # 接近3
5. 關鍵細節與注意事項¶
- 梯度清零:
optimizer.zero_grad()必須在loss.backward()前調用,否則梯度會累加,導致訓練失控。 - 模型模式:訓練時用
model.train()(啓用Dropout等),推理時用model.eval()(關閉Dropout,保證結果穩定)。 - 優化器選擇:
- SGD(隨機梯度下降):基礎版,適合簡單模型;
- Adam:更高效,默認參數即可,適合大多數場景(推薦新手優先用)。
- batch_size:若數據量大,可通過
DataLoader分批訓練(如batch_size=32),加快訓練速度。
6. 總結¶
損失函數是模型的“糾錯尺子”,訓練循環是模型“自我修正”的過程。通過調整參數最小化損失,模型就能從數據中學習到規律。
- 迴歸任務(連續值)→ 用MSE損失;
- 分類任務(離散類別)→ 用CrossEntropy損失;
- 訓練循環核心:前向→損失→反向→更新。
掌握這些基礎後,你可以嘗試更復雜的模型(如CNN、RNN)或更復雜的任務(圖像分類、文本生成),Pytorch的強大之處在於這些基礎組件的可複用性。加油!