概率,信息量,熵的表达式中 log \text{log} log 形式,请参考概率论和信息论解释,不再赘述,或参考 信息量的对数形式 可能得到些启示。

直接开始。

交叉熵是衡量两个概率分布相似度的重要工具。给定真实分布 q = ( q 1 , q 2 , … , q K ) \text{q} = (q_1, q_2, \ldots, q_K) q=(q1,q2,,qK) 和模型预测分布 p = ( p 1 , p 2 , … , p K ) \text{p} = (p_1, p_2, \ldots, p_K) p=(p1,p2,,pK),其中 q i ≥ 0 q_i \geq 0 qi0, p i > 0 p_i > 0 pi>0, ∑ i q i = ∑ i p i = 1 \sum_i q_i = \sum_i p_i = 1 iqi=ipi=1,交叉熵定义为:

H ( q , p ) = − ∑ i = 1 K q i log ⁡ p i H(\text{q}, \text{p}) = -\sum_{i=1}^K q_i \log p_i H(q,p)=i=1Kqilogpi

直觉上理解,当某个事件 i 的真实概率 q i q_i qi 很大时,如果模型赋予的概率 p i p_i pi 很小, log ⁡ p i \log p_i logpi 将成为一个很大的负数,前面加上负号后成为很大的正数,导致损失显著增加,反之,如果模型准确预测了高概率事件,损失就会保持较小。因此,H 受与最大的 q i q_i qi对应的 p i p_i pi影响更大,两者偏离越大,损失越大,直观上看,交叉熵更重视出类拔萃者,而忽略了卑微者,这就是一种有意义的 “拔优”,涌现正基于这种非线性操作。

y = − log y=-\text{log} y=log 曲线,它在定义域内与 x 轴交点处左边的斜率比 y = − x y=-x y=x更陡,这便放大了对应 q i q_i qi的重要性,看似 “拔优” 措施,但它真的只是措施吗?并不是,拔优不是靠某个措施,而是信息量的属性,参考文初我引用的作文,log 并非为了运算方便,而且信息量必须用 log 表示。

看名字, “交叉” 指的是真实分布和估计的交叉,H 越小越好,所以可以用来做损失函数。如果不交叉,公式就成了:

H ( p ) = − ∑ i = 1 K p i log ⁡ p i H(\text{p}) = -\sum_{i=1}^K p_i \log p_i H(p)=i=1Kpilogpi

而这正是信息熵的标准表达式。在概率分布上下文,它度量 K 个概率分布的均匀性,越尖锐,事件越确定,值越小。

而交叉熵表示当不知道系统概率分布时,用一个估计的概率分布去度量相对于目标的 “损失”,并可将此作为起点,通过梯度逼近目标的概率分布,这正是广义上学习的过程。

从信息论的角度,交叉熵可以分解为两个有物理意义的组成部分(抛开概念术语,它很容易从数学上推导):

H ( q , p ) = H ( q ) + D KL ( q ∥ p ) H(\text{q}, \text{p}) = H(\text{q}) + D_{\text{KL}}(\text{q} \parallel \text{p}) H(q,p)=H(q)+DKL(qp)

其中 H ( q ) = − ∑ i q i log ⁡ q i H(\text{q}) = -\sum_i q_i \log q_i H(q)=iqilogqi 是真实分布的熵,衡量了分布本身的不确定性, D KL ( q ∥ p ) = ∑ i q i log ⁡ q i p i D_{\text{KL}}(\text{q} \parallel \text{p}) = \sum_i q_i \log \dfrac{q_i}{p_i} DKL(qp)=iqilogpiqi 是 KL 散度,衡量两个分布之间的差异。由于 H ( q ) H(\text{q}) H(q) 是固定常数,最小化交叉熵等价于最小化 KL 散度。

在深度学习中,通常不直接对概率 p 进行计算,而是对未归一化的 logits z = ( z 1 , z 2 , … , z K ) \text{z} = (z_1, z_2, \ldots, z_K) z=(z1,z2,,zK) 进行计算,通过 Softmax 函数获得概率 p i = e z i ∑ j e z j p_i = \dfrac{e^{z_i}}{\sum_j e^{z_j}} pi=jezjezi,此时交叉熵对 logits 的梯度展现出惊人的简洁:

∂ H ∂ z i = p i − q i \dfrac{\partial H}{\partial z_i}=p_i-q_i ziH=piqi

这意味着,每个 logit 的梯度直接等于其预测概率与真实概率的差值。当模型对某个类别的预测概率高于真实概率时,梯度为正,提示应该降低相应的 logit,当预测不足时,梯度为负,提示应该增加 logit。

交叉熵损失关于预测概率 p 是严格凸函数,保证了优化过程的良好性质。Hessian 矩阵 ∂ 2 H ∂ p i ∂ p j = δ i j q i p i 2 \dfrac{\partial^2 H}{\partial p_i \partial p_j} = \delta_{ij} \dfrac{q_i}{p_i^2} pipj2H=δijpi2qi 是对角正定的,确保在概率单纯形内存在唯一的全局最小值 p ∗ = q \text{p}^*=\text{q} p=q

这种凸性结合梯度的明确指向性,使交叉熵成为训练概率模型的理想选择。它提供了清晰的优化方向,还保证了整个学习过程的稳定收敛。无论真实分布 q 是 one-hot 还是均匀的,交叉熵都能有效导向真实分布。

下面是一个使用交叉熵逼近真实分布的例子。

模型的原始输出通过一系列变换得到预测概率,计算与真实分布的差异,最后将误差通过梯度传回并更新模型,这个过程的美感体现在它的简洁性和自洽性。

从模型最后一层的原始输出 logits 开始,记作 z = [ z 1 , z 2 , … , z K ] \text{z} = [z_1, z_2, \ldots, z_K] z=[z1,z2,,zK],其中 K 是类别数量,z 没经过归一化,可理解为每个类别的 “原始分”,但由于缺乏概率解释,需 Softmax 函数将其转换为概率分布。

Softmax 定义为 p j = e z j ∑ k = 1 K e z k p_j = \dfrac{e^{z_j}}{\sum_{k=1}^K e^{z_k}} pj=k=1Kezkezj,这个归一化操作确保所有 p j p_j pj 满足 0 < p j < 1 0 < p_j < 1 0<pj<1 ∑ j p j = 1 \sum_j p_j = 1 jpj=1,这就构成一个有效的概率分布,指数的作用是放大较大 logits 的差异,使概率分布更加尖锐,突出重点,胜者通吃。

现在有了预测概率 p = [ p 1 , p 2 , … , p K ] \text{p} = [p_1, p_2, \ldots, p_K] p=[p1,p2,,pK],就可衡量它与真实分布 q = [ q 1 , q 2 , … , q K ] \text{q} = [q_1, q_2, \ldots, q_K] q=[q1,q2,,qK] 的差异。但基于概率的分类会存在不连续跃点,比如某概率 > 0.5 是工人,< 0.5 就是经理,在 0.5 这个点就发生不连续,换句话说,分类准确率不可微分,这便难以进行梯度计算。

交叉熵损失函数 L = − ∑ k = 1 K q k log ⁡ ( p k ) L = -\sum_{k=1}^K q_k \log(p_k) L=k=1Kqklog(pk) 完美承解决这个问题。当真实分布是 one-hot 向量时(即只有一个 q j = 1 q_j=1 qj=1,其余为 0),损失简化为 L = − log ⁡ ( p true ) L = -\log(p_{\text{true}}) L=log(ptrue),直观表示模型对正确类别的置信度,它是连续可微的。

为优化模型,我们需要计算损失对 logits 的梯度 ∂ L ∂ z j \dfrac{\partial L}{\partial z_j} zjL。这个计算过程展现了奇妙。根据链式法则,我们有 ∂ L ∂ z j = ∑ k ∂ L ∂ p k ∂ p k ∂ z j \dfrac{\partial L}{\partial z_j} = \sum_k \dfrac{\partial L}{\partial p_k} \dfrac{\partial p_k}{\partial z_j} zjL=kpkLzjpk

其中 ∂ L ∂ p k = − q k p k \dfrac{\partial L}{\partial p_k} = -\dfrac{q_k}{p_k} pkL=pkqk 是损失对预测概率的梯度。而 ∂ p k ∂ z j \dfrac{\partial p_k}{\partial z_j} zjpk 是 Softmax 的雅可比矩阵,需要分两种情况:

  • k = j k = j k=j 时, ∂ p j ∂ z j = p j ( 1 − p j ) \dfrac{\partial p_j}{\partial z_j} = p_j(1-p_j) zjpj=pj(1pj)
  • k ≠ j k \neq j k=j 时, ∂ p k ∂ z j = − p k p j \dfrac{\partial p_k}{\partial z_j} = -p_k p_j zjpk=pkpj

将这些项组合起来: ∂ L ∂ z j = ( − q j p j ) ⋅ p j ( 1 − p j ) + ∑ k ≠ j ( − q k p k ) ⋅ ( − p k p j ) \dfrac{\partial L}{\partial z_j} = \left(-\dfrac{q_j}{p_j}\right) \cdot p_j(1-p_j) + \sum_{k \neq j} \left(-\dfrac{q_k}{p_k}\right) \cdot (-p_k p_j) zjL=(pjqj)pj(1pj)+k=j(pkqk)(pkpj)。经过展开和简化,中间项相互抵消,最终得到简洁的高尚:

∂ L ∂ z j = p j − q j \dfrac{\partial L}{\partial z_j}=p_j-q_j zjL=pjqj

梯度直接等于预测值与真实值的差异。当 p j > q j p_j > q_j pj>qj,梯度为正,告诉模型需要降低这个 logit,当 p j < q j p_j < q_j pj<qj,梯度为负,鼓励模型增加这个 logit。梯度的幅度正好反映了错误的严重程度。

一个具体例子,设真实分布为 q = [ 0.7 , 0.2 , 0.1 ] \text{q} = [0.7, 0.2, 0.1] q=[0.7,0.2,0.1],模型 logits 为 z = [ 2.0 , 1.0 , 0.5 ] \text{z} = [2.0, 1.0, 0.5] z=[2.0,1.0,0.5]。通过 Softmax 得到预测概率 p ≈ [ 0.629 , 0.231 , 0.140 ] \text{p} \approx [0.629, 0.231, 0.140] p[0.629,0.231,0.140]。交叉熵损失约为 0.815,梯度为 ∂ L ∂ z = [ 0.629 − 0.7 , 0.231 − 0.2 , 0.140 − 0.1 ] = [ − 0.071 , 0.031 , 0.040 ] \dfrac{\partial L}{\partial \text{z}} = [0.629-0.7, 0.231-0.2, 0.140-0.1] = [-0.071, 0.031, 0.040] zL=[0.6290.7,0.2310.2,0.1400.1]=[0.071,0.031,0.040]

这梯度信号明确指示了调整方向,第一个 logit 要增加,第二个和第三个 logit 要减少,使用学习率 η = 0.1 \eta = 0.1 η=0.1 更新后,新的 logits 变为 [ 2.007 , 0.997 , 0.496 ] [2.007, 0.997, 0.496] [2.007,0.997,0.496],对应的新概率分布为 [ 0.631 , 0.230 , 0.139 ] [0.631, 0.230, 0.139] [0.631,0.230,0.139],更接近真实分布了。

虽然损失函数涉及复杂的指数对数运算,但最终的梯度却简单直观。这种简洁性不仅使计算高效,更提供了物理直觉,模型训练本质上就是不断调整输出,使其越来越接近真实,这种事重复千万遍。

其实这篇文章应该说两个事情,交叉熵和 Softmax 函数,因为后者呈现的归一化之美也同样不失单调,但如此一来是不是要把 GELU 也带上呢… 最近看大模型相关的论文和书籍,发现了宝藏,这里面全都是我感兴趣的单点,概率统计学,非线性,GPU 并行的切割方向,负反馈,矩阵,函数图像…

浙江温州皮鞋湿,下雨进水不会胖。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐