Skip to content

损失函数与输出层

本页速览 损失函数是梯度信号的源头,也是"模型在优化什么"的直接定义。本文讲透输出层与损失必须匹配的原理,覆盖分类(交叉熵/BCE/标签平滑/Focal)、回归(MSE/MAE/Huber)、排序与对比损失,并给出多任务平衡与调试要点。

损失函数与输出层

一句话定义:损失函数(loss function)量化"模型的预测离真实答案有多远",是所有梯度信号的源头。反向传播把 ∂L/∂W 一层层传回参数,见反向传播与自动微分;而损失函数本身长什么样,决定了这个信号的质量与训练方向——"损失定义目标,优化负责抵达"。

一、为什么损失函数必须与输出层匹配

这是全篇最重要的原则:输出层的设计(要不要激活、用什么激活)和损失函数是一套的,不能拆开选

  • 多分类:输出层输出 logits(未归一化得分),配合 Softmax + 交叉熵
  • 二分类:输出层一个 logit,配合 Sigmoid + 二元交叉熵
  • 回归:输出层通常不激活(线性输出),配合 MSE/MAE 等。

数学原因是交叉熵需要"概率分布"形式的输入,而 Softmax/Sigmoid 恰好把 logits 归一化成概率;两者结合还有数值稳定上的讲究。在 PyTorch 里,nn.CrossEntropyLoss 已经在内部把 logits 做 Softmax 再算交叉熵,不要再手动接 nn.Softmax——那会双重归一化还损失数值精度(详见神经网络基础中"输出层返回 logits"的说明)。

输出层与损失不匹配的典型症状

手动在输出层接了 Softmax 又把结果传给 CrossEntropyLoss,训练初期 loss 偏大、收敛慢、精度受损——因为 softmax(logits) 后梯度被扭曲。排查思路见调试与诊断

二、分类损失:CrossEntropy、BCE、标签平滑、Focal

交叉熵(Cross-Entropy)

多分类的标准损失。对单个样本,真实类别是 y(one-hot 视角),模型预测分布 p

L = −log p_y

它等价于"负对数似然":让正确类别的预测概率尽量接近 1。直觉:正确类概率 0.9 → loss ≈ 0.105;概率 0.1 → loss ≈ 2.3,惩罚随着"错得多"而急剧上升。

二元交叉熵(BCE)

二分类(或"每个标签独立是/否"的多标签)用:

L = −[y·log σ(z) + (1−y)·log(1−σ(z))]

σ 是 Sigmoid。多标签分类就是把它按每个标签维度求和,输出层是"每个 logit 一个 Sigmoid"。

标签平滑(Label Smoothing)

硬标签 0/1 在交叉熵下会鼓励 logits 无限大、过度自信,也容易过拟合。标签平滑把目标改成 y' = (1−ε)·y + ε/KK 类、ε≈0.1),防止模型把概率推到 1。它在 ImageNet 分类、机器翻译、乃至 GPT 系列训练中都是标配技巧,与过拟合与正则化里的其他手段协同工作。

Focal Loss

类别极度不平衡时,普通交叉熵会被"易分类的大类样本"主导。Focal Loss 在交叉熵上乘一个调制因子 (1−p_t)^γ

L = −(1−p_t)^γ · log p_t

p_t 越接近 1(分类越容易),权重越小——模型把注意力集中到"难的、少数类的"样本上。它由 Lin 等人在 2017 年提出,最初用于密集目标检测(RetinaNet)。更系统的类别不平衡处理见深度学习评估与实验

三、回归损失:MSE、MAE、Huber

损失公式特点适用
MSE(ŷ−y)²处处可导、对大误差惩罚平方级放大;对异常值极度敏感误差服从高斯分布、无异常值
MAE|ŷ−y|对大误差只线性惩罚,异常值鲁棒;但零点不可导含异常值、鲁棒优先
Huber小误差用 MSE,大误差用线性兼具两者优点,有一个超参数 δ 控制拐点工程默认折中

为什么 MSE 对异常值敏感?因为梯度是 2(ŷ−y),一个偏离 10 倍的样本产生的梯度是正常样本的 10 倍,会主导整步更新。而 MAE 的梯度有界(±1)。选择回归损失,本质是回答"离群点应该多影响模型"

直觉

MSE 假设误差服从高斯分布,MAE 隐含拉普拉斯分布——两者分别对应"均值回归"与"中位数回归"。如果你的数据有重尾,MAE 或 Huber 更诚实。

四、排序损失:pairwise 与 listwise

排序问题(推荐、检索)里,我们往往不在乎精确得分,只在乎相对顺序。典型做法:

  • Pointwise:把排序当成回归/分类,对每个条目独立打分,简单但没直接优化排序。
  • Pairwise:对"正例应排在负例前"的样本对构造损失,如 RankNet、LambdaRank 的成对约束。
  • Listwise:直接优化整列排序质量,如 ListNet,直接优化 NDCG 等排序指标(用可微代理)。

在推荐系统里,BPR(Bayesian Personalized Ranking)就是最常用的 pairwise 损失:对一个用户,让"已交互项"的得分高于"未交互项",见深度学习推荐系统

五、对比损失:Triplet、InfoNCE 与度量学习

对比损失的目标不是拟合标签,而是把同类样本在表示空间中拉近、异类推远——这直接服务于表征学习与预训练

Triplet Loss(FaceNet,2015):三元组(锚点 a、正例 p、负例 n):

L = max( d(a,p) − d(a,n) + margin, 0 )

直觉:让"和正例的距离"至少比"和负例的距离"小一个 margin。

InfoNCE(2018,Oord 等):把对比学习建模成"在 N 个候选里挑出正样本"的分类任务:

L = −log [ exp(sim(a,p)/τ) / Σⱼ exp(sim(a,qⱼ)/τ) ]

τ 是温度,控制分布的锐利度。SimCLR、MoCo 等自监督方法都用它,是当前对比学习的标准损失。它把"相似性"变成"多分类概率",天然与 Softmax 交叉熵同源。

六、多任务损失平衡:GradNorm 简述

多任务模型要最小化加权和 L = Σₖ wₖ·Lₖ。问题来了:各任务梯度量级差异巨大,wₖ 调不好,小 loss 的任务直接"被淹没"。常见做法:

  • 手动调 wₖ 或按量级归一化。
  • 不确定性加权:把每个任务的方差也当参数学(Kendall 等,2018)。
  • GradNorm(Chen 等,2018):训练中动态调整 wₖ,让所有任务的梯度范数回归到同一个"目标范数",防止某个任务主导。

多任务平衡没有银弹,但工程上记住一条:先让各任务 loss 量级接近,再谈权重。多任务架构设计(shared backbone + task heads)见深度学习总体架构解剖

七、损失函数设计要点与调试

首要铁律

loss 不降,先查数据与代码,而不是换损失函数。80% 的"loss 卡住"是数据问题:标签错位、NaN、类别严重失衡、数据没 shuffle。先看数据与数据工程调试与诊断

设计或选用损失函数时,按这个清单过一遍:

  1. 任务类型是否匹配:分类/回归/排序/对比?输出层和损失是否配套(第一节)?
  2. 数据分布:类别不平衡?异常值多?→ 考虑 Focal/加权/MAE。
  3. 你真正要优化的指标:评估时用准确率/NDCG/FID 等业务指标,但训练损失是它的可微代理。代理和指标之间可能有差距,这叫"优化目标错位"——评估口径见深度学习评估与实验
  4. 损失的数值稳定性:优先用框架内置的 fused 实现(如 CrossEntropyLoss),避免手写 log-sum-exp 溢出。
  5. 训练初期盯住 loss 数量级:交叉熵的初始期望值 ≈ log(类别数),如果差很远,说明初始化或数据有问题。

八、权衡与取舍

权衡与取舍

拟合目标 vs 优化难度:MSE 光滑易优化但被异常值牵着走;MAE 鲁棒但零点不可导、收敛慢;Huber 折中但多一个超参数。没有"最优损失",只有"与数据分布匹配的损失"

任务指标 vs 可微代理:NDCG、AUC、FID 这些评价指标大多不可微,必须换成代理损失(排序损失、对比损失、生成目标)。代理与指标越接近,训练越"诚实",但通常也更难优化。

单一损失 vs 多损失加权:多损失(如 GAN 的对抗 + 特征匹配、多任务)能注入更多监督信号,但带来平衡问题与调参负担。越简单的损失越容易调试。

损失函数是"模型要成为什么"的宣言。它和输出层、评估指标三者必须构成一个自洽的闭环——输出层给形状,损失给梯度方向,评估指标给真相。评估这一环的完整方法论见评估章节,常用损失与术语对照见术语表

延伸阅读

参考资料