optim.SGD(model.parameters(), lr=0.01) 是 PyTorch 中创建随机梯度下降(Stochastic Gradient Descent)优化器的标准写法。
🎯 核心作用
这行代码创建了一个优化器对象,它的工作是使用梯度下降算法更新模型的参数,让模型的损失函数逐渐减小。
📝 参数详解
python
import torch.optim as optim
optimizer = optim.SGD(
model.parameters(), # 要优化的参数(模型的权重和偏置)
lr=0.01 # 学习率(learning rate)
)
| 参数 | 含义 | 典型值 | 作用 |
|---|---|---|---|
model.parameters() |
模型的所有可训练参数 | 自动获取 | 指定要更新哪些参数 |
lr |
学习率 | 0.001, 0.01, 0.1 | 控制参数更新的步长 |
💡 SGD 工作原理
参数更新公式
新参数 = 旧参数 - 学习率 × 梯度
手动实现 vs 优化器
python
import torch
import torch.nn as nn
import torch.optim as optim
model = nn.Linear(10, 1)
# 方式1:手动更新参数(不推荐)
loss.backward()
with torch.no_grad():
for param in model.parameters():
param -= 0.01 * param.grad # 手动应用梯度
model.zero_grad()
# 方式2:使用优化器(推荐)
optimizer = optim.SGD(model.parameters(), lr=0.01)
loss.backward()
optimizer.step() # 自动更新所有参数
optimizer.zero_grad() # 清零梯度
🔧 完整使用流程
python
import torch
import torch.nn as nn
import torch.optim as optim
# 1. 定义模型
model = nn.Linear(5, 1)
# 2. 定义损失函数
criterion = nn.MSELoss()
# 3. 创建优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 4. 训练循环
for epoch in range(100):
# 假设有数据
x = torch.randn(32, 5) # 32个样本,5个特征
y = torch.randn(32, 1) # 32个标签
# 前向传播
pred = model(x)
loss = criterion(pred, y)
# 反向传播
optimizer.zero_grad() # 清零梯度(重要!)
loss.backward() # 计算梯度
optimizer.step() # 更新参数
if epoch % 20 == 0:
print(f"Epoch {epoch}, Loss: {loss.item():.4f}")
📊 常用优化器对比
| 优化器 | 特点 | 适合场景 | 代码示例 |
|---|---|---|---|
| SGD | 经典,简单 | 标准任务,需要精细调参 | optim.SGD(params, lr=0.01) |
| SGD + Momentum | 加速收敛,减少震荡 | 大多数任务 | optim.SGD(params, lr=0.01, momentum=0.9) |
| Adam | 自适应学习率,鲁棒 | 深度学习,Transformer | optim.Adam(params, lr=0.001) |
| AdamW | Adam + 权重衰减解耦 | 推荐替代Adam | optim.AdamW(params, lr=0.001) |
| RMSprop | 自适应学习率 | RNN, 强化学习 | optim.RMSprop(params, lr=0.01) |
🎨 SGD 的高级参数
python
# 1. 带动量的 SGD(常用)
optimizer = optim.SGD(
model.parameters(),
lr=0.01,
momentum=0.9, # 动量,加速收敛
nesterov=True # Nesterov 动量(进阶版)
)
# 2. 带权重衰减的 SGD(L2正则化)
optimizer = optim.SGD(
model.parameters(),
lr=0.01,
weight_decay=1e-4 # 防止过拟合
)
# 3. 完整配置
optimizer = optim.SGD(
model.parameters(),
lr=0.01,
momentum=0.9,
weight_decay=1e-5,
nesterov=True
)
💻 实际训练示例
python
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
# 创建数据
X = torch.randn(1000, 10)
y = torch.randn(1000, 1)
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
# 创建模型、损失函数、优化器
model = nn.Sequential(
nn.Linear(10, 50),
nn.ReLU(),
nn.Linear(50, 1)
)
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# 训练
epochs = 50
for epoch in range(epochs):
running_loss = 0.0
for batch_X, batch_y in dataloader:
# 前向
pred = model(batch_X)
loss = criterion(pred, batch_y)
# 反向
optimizer.zero_grad() # ← 清零梯度
loss.backward() # ← 计算梯度
optimizer.step() # ← 更新参数
running_loss += loss.item()
avg_loss = running_loss / len(dataloader)
if (epoch + 1) % 10 == 0:
print(f"Epoch {epoch+1}/{epochs}, Loss: {avg_loss:.4f}")
⚙️ 学习率调度器
python
# 动态调整学习率
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
for epoch in range(100):
# 训练代码...
scheduler.step() # 每30个epoch,学习率乘以0.1
print(f"Epoch {epoch}, LR: {scheduler.get_last_lr()[0]}")
📈 学习率的选择
| 场景 | 推荐学习率 |
|---|---|
| 简单任务(小模型) | 0.01 - 0.1 |
| 标准任务(CNN/MLP) | 0.001 - 0.01 |
| 微调预训练模型 | 0.0001 - 0.001 |
| Transformer/BERT | 1e-5 - 3e-4 |
🎯 关键要点总结
python
# 训练三步曲(记住这个模式)
optimizer.zero_grad() # 1. 清零梯度(防止累积)
loss.backward() # 2. 计算梯度
optimizer.step() # 3. 更新参数
| 步骤 | 方法 | 作用 |
|---|---|---|
| 清零 | optimizer.zero_grad() |
清除上一次的梯度 |
| 计算 | loss.backward() |
计算当前批次的梯度 |
| 更新 | optimizer.step() |
用梯度更新参数 |
💡 常见问题
Q: 为什么需要 zero_grad()?
A: PyTorch 默认梯度会累积,不清零的话每次的梯度会累加。
Q: SGD 和 Adam 怎么选?
A: 初学者推荐 Adam,稳定;想深入调优用 SGD + momentum。
Q: 学习率怎么设置?
A: 从 0.01 开始尝试,观察 loss 曲线,如果震荡就降低学习率。
一句话总结 :optim.SGD(model.parameters(), lr=0.01) 创建了一个优化器,它会按照学习率 0.01 的方向,沿着梯度的反方向更新模型的所有参数,让损失函数一步步变小。