共计 1538 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点
01 损失函数(Zero-One Loss)是二分类问题中最直观的评估指标,定义为预测错误样本的比例:

$$L_{01}(y, \hat{y}) = \frac{1}{n}\sum_{i=1}^n I(y_i \neq \hat{y}_i)$$
其优势在于解释性强——直接反映分类错误率。但致命缺陷是不可导(阶梯函数性质),导致无法用梯度下降直接优化。在实际工程中,我们通常采用代理损失函数(Surrogate Loss)进行替代优化。
技术选型
代理损失函数对比
- 交叉熵损失(Cross-Entropy)
- 公式:$L_{CE} = -[y\log(p)+(1-y)\log(1-p)]$
- 特点:适用于概率输出,对错误预测施加指数级惩罚
-
适用场景:标准二分类、多分类任务
-
Hinge 损失(SVM 使用)
- 公式:$L_{hinge} = \max(0, 1 – y\cdot\hat{y})$
- 特点:产生稀疏解,对离群点鲁棒
-
适用场景:数据存在噪声、需要最大间隔分类
-
Focal Loss
- 公式:$FL(p_t) = -\alpha_t(1-p_t)^\gamma \log(p_t)$
- 特点:通过 $\gamma$ 调节难易样本权重
- 适用场景:极端类别不平衡(如 100:1)
核心实现
PyTorch 自定义损失类
import torch
import torch.nn as nn
class HingeLoss(nn.Module):
"""
实现 Hinge Loss(基于 SVM 的损失函数)注意:要求标签为±1 编码
"""
def __init__(self, margin=1.0):
super().__init__()
self.margin = margin
def forward(self, y_pred, y_true):
"""
:param y_pred: 模型原始输出(未激活), shape=[batch_size]
:param y_true: 真实标签(必须为±1), shape=[batch_size]
"""assert y_pred.dim() == 1," 输入必须是 1D 张量 "assert y_true.dim() == 1," 标签必须是 1D 张量 "
# 计算 hinge loss
losses = torch.clamp(self.margin - y_true * y_pred, min=0)
return losses.mean()
关键检查点
- 张量维度断言(防止 broadcasting 错误)
- 标签值域验证(需在训练前确保标签编码正确)
- 数值稳定性处理(如添加微小量防止 log(0))
性能考量
通过 torch.cuda.max_memory_allocated() 监控不同 batch size 下的显存占用:
| Batch Size | 显存占用(MB) |
|---|---|
| 32 | 1,245 |
| 64 | 2,387 |
| 128 | 4,512 |
注:测试环境为 NVIDIA V100 16GB,模型参数量 50M
避坑指南
- 激活函数缺失
- 错误:直接对 logits 计算交叉熵
-
修正:先通过
sigmoid获得概率输出 -
标签编码错误
- 错误:Hinge Loss 使用 0 / 1 编码标签
-
修正:转换为±1 编码(
y = 2*y_original - 1) -
验证阶段误用
- 错误:验证时仍用连续概率计算 01 损失
- 修正:应使用
(y_pred > 0.5).int()获取离散预测
思考题
当正负样本比例达到 100:1 时,可采取的损失函数调整策略:
1. 采用 Focal Loss 自动降低易分类样本权重
2. 在交叉熵中引入类别权重(pos_weight参数)
3. 对少数类样本进行过采样(需注意过拟合风险)
延伸阅读
- 关于代理损失函数的理论一致性证明可参考《Statistical Learning Theory》
- PyTorch 官方实现的 Focal Loss 见
torchvision.ops.focal_loss - 多标签场景下的 01 损失扩展可参考 Hamming Loss
正文完
