共计 2085 个字符,预计需要花费 6 分钟才能阅读完成。
1. AlexNet 与损失函数的重要性
2012 年 ImageNet 竞赛中,AlexNet 以超越第二名 10.8% 的绝对优势夺冠,标志着深度学习在计算机视觉领域的突破。该网络成功的关键之一,是采用交叉熵损失函数替代传统的均方误差(MSE)。这种选择使得模型在 1000 类分类任务中,能更有效地处理类别间竞争关系和学习特征判别性。

2. 交叉熵损失原理剖析
2.1 数学定义
给定真实标签 $y$ 和预测概率 $\hat{y}$,交叉熵损失定义为:
$$L = -\sum_{i=1}^C y_i \log(\hat{y}_i)$$
其中 $C$ 为类别数,$y_i$ 为 one-hot 编码的真实标签。
2.2 对比实验
通过 MNIST 数据集对比不同损失函数:
| 损失函数 | 测试准确率 | 训练收敛速度 |
|---|---|---|
| MSE | 97.2% | 慢(需 50 轮) |
| 交叉熵 | 98.6% | 快(20 轮) |
交叉熵的优势在于:
– 梯度与误差成正比,避免 MSE 的梯度消失问题
– 对错误预测惩罚更大,加速模型修正
3. PyTorch 完整实现
3.1 数据预处理
import torchvision.transforms as transforms
transform = transforms.Compose([transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
3.2 模型定义
import torch.nn as nn
class AlexNet(nn.Module):
def __init__(self, num_classes=1000):
super().__init__()
self.features = nn.Sequential(nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
# ... 其他层省略
)
self.classifier = nn.Sequential(nn.Dropout(),
nn.Linear(256 * 6 * 6, 4096),
nn.ReLU(),
# ... 全连接层
)
def forward(self, x):
x = self.features(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
3.3 多 GPU 训练
model = AlexNet().cuda()
model = nn.DataParallel(model) # 多卡并行
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# 训练循环
for inputs, labels in train_loader:
inputs, labels = inputs.cuda(), labels.cuda()
outputs = model(inputs)
loss = criterion(outputs, labels) # 自动聚合各 GPU 计算结果
loss.backward()
optimizer.step()
4. 实战技巧
4.1 学习率调整
使用 torch.optim.lr_scheduler 监控损失曲线:
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=5)
# 每个 epoch 后调用
scheduler.step(val_loss)
4.2 Focal Loss 实现
class FocalLoss(nn.Module):
def __init__(self, alpha=0.25, gamma=2):
super().__init__()
self.alpha = alpha
self.gamma = gamma
def forward(self, inputs, targets):
BCE_loss = F.cross_entropy(inputs, targets, reduction='none')
pt = torch.exp(-BCE_loss)
loss = self.alpha * (1-pt)**self.gamma * BCE_loss
return loss.mean()
4.3 梯度裁剪
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=5.0)
5. 延伸思考
- 当类别数量达到 10 万级时,如何优化交叉熵的计算效率?
- 在目标检测任务中,如何设计同时包含分类和定位的复合损失函数?
- 自监督学习中,对比损失(Contrastive Loss)与交叉熵有何本质区别?
通过本文的代码实践和理论分析,读者应该能够理解损失函数在深度学习中的核心作用。建议尝试在 CIFAR-10 等小规模数据集上修改损失函数,观察模型性能的变化规律。
正文完
