WeHelp
PyTorch 是建置、訓練、佈署現代人工智慧、深度學習、神經網路模型的核心開發套件。
  1. 簡介、安裝、快速開始
  2. Tensor 張量
  3. 定義資料集、載入器
  4. 神經網路簡介
  5. PyTorch 定義模型
  6. PyTorch 激勵函式
  7. PyTorch 損失函式
  8. PyTorch 優化器
  9. 二元分類模型範例
PyTorch 優化器
## 1. PyTorch 優化器的用途 神經網路訓練時,通常會先計算損失函數: L = loss\(y, e\) 接著利用反向傳播取得每個參數的梯度: G = backward\(L\) 優化器則根據梯度更新模型參數: optimizer\(G, LR\) 其中: - G:損失對參數的梯度 - LR:學習率 learning rate 在 PyTorch 中,優化器主要負責: 1. 儲存模型參數 2. 根據梯度更新參數 3. 清除上一輪累積的梯度 4. 可選擇使用 momentum、weight decay 等機制 --- ## 2. SGD 與 Adam 比較 ### SGD SGD,Stochastic Gradient Descent,PyTorch 中常見的 SGD 會搭配 momentum: ```python optimizer = torch.optim.SGD( model.parameters(), lr=0.1, momentum=0.9 ) ``` #### 優點 - 演算法簡單 - 計算量較低 - 適當調整學習率後,泛化能力常常不錯 - 訓練大型模型時常被使用 #### 缺點 - 對學習率較敏感 - 可能在狹長或複雜的損失曲面上收斂較慢 - 通常需要手動調整 learning rate --- ### Adam Adam 結合了 momentum 與自適應學習率,會為每個參數估計梯度的一階與二階動量。 ```python optimizer = torch.optim.Adam( model.parameters(), lr=0.001 ) ``` #### 優點 - 通常收斂速度較快 - 對初始學習率比較不敏感 - 適合快速建立模型與處理稀疏梯度 - 常作為深度學習的預設選擇 #### 缺點 - 每個參數需要額外儲存動量資訊,因此記憶體使用量較高 - 有些任務中泛化能力不如調整良好的 SGD - 不代表一定比 SGD 找到更好的最終模型 ### 簡單比較 | 特性 | SGD | Adam | |---|---|---| | 更新方式 | 固定學習率搭配梯度 | 自適應調整各參數步長 | | 常用 learning rate | `0.01 ~ 0.1` | `0.0001 ~ 0.001` | | 收斂速度 | 通常較慢 | 通常較快 | | 對學習率敏感度 | 較高 | 較低 | | 額外記憶體 | 少 | 較多 | | 常見用途 | 最終精調、影像分類 | 快速實驗、一般深度模型 | --- ## 3. PyTorch 如何使用優化器與學習率 一個典型的訓練流程如下: ```python for x, y in dataloader: optimizer.zero_grad() # 清除上一輪梯度 output = model(x) # 前向傳播 loss = loss_fn(output, y) loss.backward() # 反向傳播,計算梯度 optimizer.step() # 根據梯度更新參數 ``` ### 為什麼要呼叫 `zero_grad()`? PyTorch 預設會累積梯度。如果不清除上一輪的梯度,新的梯度會加到舊梯度上: ```python optimizer.zero_grad() ``` ### `learning rate` 的作用 學習率決定每次參數更新的幅度: - 太大:可能震盪,甚至無法收斂 - 太小:訓練很慢,可能停在不佳的位置 - 合適:損失穩定下降 可以在訓練過程中使用 scheduler 動態調整學習率: ```python scheduler = torch.optim.lr_scheduler.StepLR( optimizer, step_size=100, gamma=0.5 ) ``` 每個 epoch 結束後呼叫: ```python scheduler.step() ``` 這會讓學習率每 100 個 epoch 乘以 `0.5`。 --- ## 4. 使用 PyTorch 訓練簡單神經網路 以下範例使用神經網路學習 XOR 分類問題: | 輸入 | 標籤 | |---|---| | `[0, 0]` | 0 | | `[0, 1]` | 1 | | `[1, 0]` | 1 | | `[1, 1]` | 0 | XOR 不是線性可分,因此需要隱藏層。 ```python import torch import torch.nn as nn # 固定隨機種子,方便重現結果 torch.manual_seed(42) # XOR 訓練資料 X = torch.tensor([ [0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0] ]) y = torch.tensor([ [0.0], [1.0], [1.0], [0.0] ]) # 建立簡單的多層感知器 model = nn.Sequential( nn.Linear(2, 8), nn.ReLU(), nn.Linear(8, 1) ) # BCEWithLogitsLoss 內部會處理 sigmoid loss_fn = nn.BCEWithLogitsLoss() # 使用 Adam 優化器 optimizer = torch.optim.Adam( model.parameters(), lr=0.05 ) # 訓練模型 for epoch in range(2000): # 1. 清除上一輪累積的梯度 optimizer.zero_grad() # 2. 前向傳播 logits = model(X) # 3. 計算損失 loss = loss_fn(logits, y) # 4. 反向傳播 loss.backward() # 5. 更新模型參數 optimizer.step() if (epoch + 1) % 200 == 0: print(f"Epoch {epoch + 1}, Loss: {loss.item():.4f}") # 測試模型 with torch.no_grad(): logits = model(X) probabilities = torch.sigmoid(logits) predictions = (probabilities >= 0.5).float() print("\n預測機率:") print(probabilities) print("\n預測結果:") print(predictions) print("\n正確答案:") print(y) ``` 可能得到類似結果: ```text 預測結果: tensor([[0.], [1.], [1.], [0.]]) ``` --- ## 5. 將 Adam 改成 SGD 只需替換優化器: ```python optimizer = torch.optim.SGD( model.parameters(), lr=0.5, momentum=0.9 ) ``` 相較於 Adam,SGD 通常需要較仔細地尋找合適的 `lr`。例如可以嘗試: ```python lr=0.1 lr=0.5 lr=1.0 ``` 而 Adam 常見的起始值則是: ```python lr=0.001 ``` --- ## 6. 完整訓練概念 整個流程可以概括為: ```text 建立模型 ↓ 指定損失函數 ↓ 將模型參數交給優化器 ↓ 前向傳播 ↓ 計算損失 ↓ 反向傳播 ↓ 優化器依照 learning rate 更新參數 ↓ 重複多個 epoch ``` 實務上可以先使用 Adam 快速確認模型與資料流程是否正確;如果需要更好的最終泛化表現,再嘗試 SGD、調整 learning rate,或搭配 learning rate scheduler。
相關學習地圖、教學課程
Python 人工智慧
建議完成「Python 資料工程」教程後,繼續學習以下課程。