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 訓練循環核心步驟
  1. 前向傳播(Forward Pass):將輸入數據送入模型,得到預測結果(y_pred)。
    - 代碼:y_pred = model(x)(x是輸入數據,model是定義的模型)

  2. 計算損失(Compute Loss):用損失函數對比y_pred和真實標籤(y_true),得到損失值。
    - 代碼:loss = loss_fn(y_pred, y_true)

  3. 反向傳播(Backward Pass):計算損失對模型參數的梯度(即“哪裏需要改”)。
    - 代碼:loss.backward()(Pytorch自動計算梯度,無需手動推導)

  4. 參數更新(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的強大之處在於這些基礎組件的可複用性。加油!

小夜