损失函数

 

交叉熵

分类

二分类交叉熵损失函数

首先,我们回顾一下这个损失函数的作用:它衡量的是模型预测的概率分布与真实的概率分布(标签)之间的“差距”

对于一个二分类问题(标签 y = 0 或 1),它的公式通常如下:

对于单个样本: Loss = - [ y * log(p) + (1 - y) * log(1 - p) ]

其中:

  • y 是真实标签,取值为 0 或 1。
  • p 是模型预测该样本属于类别 1 的概率(取值范围在 0 到 1 之间)。

这个公式可以拆开理解:

  • 当真实标签 y = 1,损失函数变为 Loss = -log(p)。这意味着:
    • 模型预测 p 越接近 1(判断正确且很自信),-log(p) 的值越小(接近 0)。
    • 模型预测 p 越接近 0(判断错误且很自信),-log(p) 的值会急剧增大(趋向于无穷大)。惩罚很重!
  • 当真实标签 y = 0,损失函数变为 Loss = -log(1 - p)。这意味着:
    • 模型预测 p 越接近 0(判断正确且很自信),-log(1 - p) 的值越小(接近 0)。
    • 模型预测 p 越接近 1(判断错误且很自信),-log(1 - p) 的值会急剧增大。同样惩罚很重!

整个训练集的总损失通常是所有样本损失的平均值。

log是以什么为底?

在机器学习和深度学习的绝大多数框架和库中(如 TensorFlow, PyTorch, scikit-learn),二分类交叉熵损失函数中使用的对数 log,默认是以自然常数 *e* 为底的,即自然对数(ln)

所以,更准确的写法应该是: Loss = - [ y * ln(p) + (1 - y) * ln(1 - p) ]

尽管默认使用自然对数,但你可能会在有些资料中看到以2或10为底的情况。这其实并不影响模型的训练和结果,原因如下:

1. 本质是衡量“差距” 交叉熵损失的核心思想是衡量两个概率分布的差异。无论以什么为底,对数函数 log(x) 的曲线形状是相似的:都是单调递增函数,当 x 接近 1 时值接近 0,当 x 接近 0 时值趋向于负无穷。

2. 相差一个常数缩放因子 不同底数的对数之间只相差一个常数倍。例如:

  • log₂(x) = ln(x) / ln(2)
  • log₁₀(x) = ln(x) / ln(10)

这意味着,如果你使用以2为底的对数,那么计算出的整个损失函数值将是使用自然对数计算结果的 1 / ln(2)1.4427 倍。

Focal_loss

Focal Loss 是为解决类别不平衡问题而对标准交叉熵损失的改进,通过降低简单样本的权重,使模型聚焦于难分类样本。


公式定义

令 $p \in [0, 1]$ 为模型对真实类别的预测概率,$y \in {0, 1}$ 为真实标签。定义 $p_t$ 为: \(p_t = \begin{cases} p & \text{if } y = 1 \\ 1 - p & \text{if } y = 0 \end{cases}\)

Focal Loss 的表达式为:

\[\text{FL}(p_t) = -\alpha_t (1 - p_t)^\gamma \log(p_t)\]

其中:

  • $p_t$:模型对真实类别的预测概率
    • 若真实标签为正类,则 $p_t = p$(预测为正的概率)
    • 若真实标签为负类,则 $p_t = 1 - p$(预测为负的概率)
  • $\alpha_t \in [0, 1]$ 是类别权重因子,用于平衡类别不平衡。 根据类别频率设置,过大可能导致训练不稳定,通常设为 $\alpha = 0.25$
  • $\gamma \geq 0$ 是聚焦参数,控制简单样本权重的降低程度。 聚焦参数(focusing parameter) 通常取 1-5(常用值为 2),越大则对困难样本的聚焦越强

核心机制

聚焦困难样本:当 $p_t$ 很大(分类正确且置信度高)时,$(1 - p_t)^{\gamma} \approx 0$,该样本的损失被大幅降低;当 $p_t$ 很小(分类错误或不确定)时,$(1 - p_t)^{\gamma} \approx 1$,损失基本保留。

处理类别不平衡:通过 $\alpha_t$ 为少数类设置较大权重(通常按类别频率的倒数设置),确保模型充分关注 underrepresented 的类别。


Focal Loss PyTorch 实现代码解析

数学公式回顾

Focal Loss 的完整表达式为:

\[\text{FL}(p, y) = \begin{cases} -\alpha (1 - p)^\gamma \log(p) & \text{if } y = 1 \\ -(1 - \alpha) p^\gamma \log(1 - p) & \text{if } y = 0 \end{cases}\]

其中:

  • $p$: 模型预测为正类的概率
  • $y$: 真实标签 (0 或 1)
  • $\alpha$: 正样本权重
  • $\gamma$: 聚焦参数

PyTorch 代码实现

# 第一行:处理正样本 (y=1) 的损失项
loss_pos = - self.alpha * (1 - pt) ** self.gamma * target * torch.log(pt)

# 第二行:处理负样本 (y=0) 的损失项
loss_neg = - (1 - self.alpha) * pt ** self.gamma * (1 - target) * torch.log(1 - pt)

# 总损失
focal_loss = loss_pos + loss_neg

标签平滑

Label Smoothing(标签平滑)

1. 基本概念

问题背景

  • 在标准分类任务中,我们通常使用 one-hot编码 的标签:[0, 0, 1, 0, 0]
  • 这会鼓励模型对正确类别预测概率为1,对错误类别预测概率为0
  • 可能导致:
    • 模型过度自信(over-confident)
    • 泛化能力下降
    • 对噪声标签敏感

Label Smoothing 解决方案

将 hard labels(硬标签)转换为 soft labels(软标签):

原始 one-hot 标签:

text

[0, 0, 1, 0, 0]  # 类别2为正确类别

平滑后的标签:

text

[0.01, 0.01, 0.96, 0.01, 0.01]  # 依然以类别2为主,但给其他类别小概率

2. 数学原理

公式

对于有 K 个类别的分类任务:

平滑前(hard label):

text

q(k|x) = 1  if k = y (真实类别)
         0  otherwise

平滑后(soft label):

text

q'(k|x) = (1 - ε) * 1  if k = y
          ε / (K - 1)   otherwise

其中:

  • ε 是平滑系数(通常 0.05-0.2)
  • K 是类别总数