深度学习实验手册
目标:从张量、自动微分和训练循环开始,建立一个可复用的 PyTorch 实验模板,再逐步扩展到 CNN、Transformer 和论文复现。
1. 环境与设备
python -m venv .venv
# Windows: .venv\Scripts\activate
# macOS/Linux: source .venv/bin/activate
pip install torch torchvision torchaudio matplotlib安装命令应根据操作系统、CUDA 版本和 PyTorch 官方安装选择器调整:PyTorch Get Started。
import torch
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("PyTorch:", torch.__version__)
print("Device:", device)
if torch.cuda.is_available():
print("GPU:", torch.cuda.get_device_name(0))2. 必须理解的训练数学
单层线性变换:。
激活函数引入非线性,例如 ReLU:。
分类交叉熵衡量预测分布与真实类别的差异。反向传播利用链式法则计算参数梯度:
优化器根据梯度更新参数。SGD 的基本形式为:
其中学习率 决定更新步长。学习率过大可能发散,过小则收敛缓慢。
3. 可运行 MLP:Fashion-MNIST
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
torch.manual_seed(42)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
transform = transforms.ToTensor()
train_ds = datasets.FashionMNIST("data", train=True, download=True, transform=transform)
test_ds = datasets.FashionMNIST("data", train=False, download=True, transform=transform)
train_loader = DataLoader(train_ds, batch_size=128, shuffle=True)
test_loader = DataLoader(test_ds, batch_size=256)
model = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, 10)
).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-4)
def evaluate():
model.eval()
total, correct, loss_sum = 0, 0, 0.0
with torch.no_grad():
for x, y in test_loader:
x, y = x.to(device), y.to(device)
logits = model(x)
loss_sum += criterion(logits, y).item() * y.size(0)
correct += (logits.argmax(1) == y).sum().item()
total += y.size(0)
return loss_sum / total, correct / total
for epoch in range(5):
model.train()
for x, y in train_loader:
x, y = x.to(device), y.to(device)
optimizer.zero_grad(set_to_none=True)
logits = model(x)
loss = criterion(logits, y)
loss.backward()
optimizer.step()
test_loss, test_acc = evaluate()
print(f"epoch={epoch+1} test_loss={test_loss:.4f} test_acc={test_acc:.4f}")
torch.save({"model": model.state_dict()}, "fashion_mnist_mlp.pt")这是教学基线,不是追求榜单成绩的架构。正式实验应增加验证集、最佳 checkpoint 保存、日志和多随机种子评估。
4. CNN 实验升级
把 MLP 换成卷积网络,观察局部感受野和参数共享如何改变图像建模:
from torch import nn
cnn = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(64 * 7 * 7, 128),
nn.ReLU(),
nn.Linear(128, 10)
)将模型移到 device 后,复用前面的训练循环。比较参数量、训练时间、验证准确率和错误样本,不要只看单一指标。
5. 训练调试顺序
- 小样本过拟合测试:先只取几十个样本,模型应能显著降低训练损失。
- 检查数据:可视化输入、标签、增强结果;确认归一化和维度。
- 检查梯度:确认梯度非 None、无 NaN/Inf,必要时统计梯度范数。
- 检查损失输入:CrossEntropyLoss 接收未经过 Softmax 的 logits 和整数类别标签。
- 观察曲线:训练损失下降而验证损失上升,通常提示过拟合。
- 保存最佳模型:依据验证集指标选择 checkpoint,测试集只用于最终评估。
6. 训练稳定性与效率
- 优化器:SGD、Momentum、Adam、AdamW。
- 学习率策略:StepLR、CosineAnnealingLR、Warmup。
- 正则化:Weight Decay、Dropout、数据增强、Early Stopping。
- 稳定性:梯度裁剪、合理初始化、归一化层。
- 性能:混合精度、梯度累积、DataLoader worker、Pinned Memory。
- 可复现:随机种子、数据版本、代码 commit、依赖、硬件和配置。
7. 从 CNN 走向 Transformer
建议依次完成:
- 手写 scaled dot-product attention。
- 实现多头注意力,理解 Q/K/V 的形状变化。
- 加入位置编码、残差连接和 LayerNorm。
- 完成小型文本分类或字符级语言模型。
- 阅读 Transformer 原论文,逐模块对照代码。
- 复现时记录参数量、训练 token 数、计算预算和评测设置。
注意:不同硬件、数据顺序和算子实现会造成数值差异;“同一随机种子”不保证跨设备完全一致。
8. 资料与代码
- PyTorch Tutorials
- Dive into Deep Learning 中文版
- fast.ai Practical Deep Learning
- Papers with Code
- The Annotated Transformer