深入理解交叉熵损失CrossEntropyLoss - Softmax

深入理解交叉熵损失CrossEntropyLoss - Softmax

flyfish

Softmax 函数可以将一个包含任意实数的向量转换为一个范围在 (0, 1) 之间且总和为 1 的概率分布。Softmax 函数的定义如下:

softmax ( z i ) = e z i ∑ j = 1 K e z j \text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}} softmax(zi)=j=1Kezjezi

其中 z z z 是输入向量, z i z_i zi 是第 i i i 个元素, K K K 是向量的长度。

具体例子

步骤 :计算 Softmax

按照标准的 Softmax 公式:

softmax ( z i ) = e z i ∑ j = 1 K e z j \text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}} softmax(zi)=j=1Kezjezi

我们需要计算每个 z i z_i zi 的指数值并求和:

  1. 计算指数值:
  • e 2.0 ≈ 7.389056 e^{2.0} \approx 7.389056 e2.07.389056
  • e 1.0 ≈ 2.718282 e^{1.0} \approx 2.718282 e1.02.718282
  • e 0.1 ≈ 1.105171 e^{0.1} \approx 1.105171 e0.11.105171
  1. 求和:
  • ∑ j = 1 3 e z j = 7.389056 + 2.718282 + 1.105171 ≈ 11.212509 \sum_{j=1}^{3} e^{z_j} = 7.389056 + 2.718282 + 1.105171 \approx 11.212509 j=13ezj=7.389056+2.718282+1.10517111.212509
  1. 计算 Softmax 值:
  • softmax ( 2.0 ) = 7.389056 11.212509 ≈ 0.659001 \text{softmax}(2.0) = \frac{7.389056}{11.212509} \approx 0.659001 softmax(2.0)=11.2125097.3890560.659001
  • softmax ( 1.0 ) = 2.718282 11.212509 ≈ 0.242432 \text{softmax}(1.0) = \frac{2.718282}{11.212509} \approx 0.242432 softmax(1.0)=11.2125092.7182820.242432
  • softmax ( 0.1 ) = 1.105171 11.212509 ≈ 0.098567 \text{softmax}(0.1) = \frac{1.105171}{11.212509} \approx 0.098567 softmax(0.1)=11.2125091.1051710.098567
    因此, Softmax 结果是 [ 0.659001 , 0.242432 , 0.098567 ] [0.659001, 0.242432, 0.098567] [0.659001,0.242432,0.098567]

数值稳定的 Softmax 推导

在实际计算中,直接使用上述公式可能会导致数值不稳定性,尤其是当 z z z 中的某些值非常大或非常小时,可能会导致指数函数溢出。因此,我们需要对 Softmax 函数进行数值稳定性的改进。具体的改进方法如下:

  1. 减去最大值:为了避免指数函数溢出,我们可以在计算 Softmax 前减去输入向量中的最大值。因为指数函数的特性,这样的操作不会改变最终的结果,但可以显著提高数值稳定性。令 z max ⁡ = max ⁡ ( z ) z_{\max} = \max(z) zmax=max(z),则改进后的 Softmax 函数为: softmax ( z i ) = e z i − z max ⁡ ∑ j = 1 K e z j − z max ⁡ \text{softmax}(z_i) = \frac{e^{z_i - z_{\max}}}{\sum_{j=1}^{K} e^{z_j - z_{\max}}} softmax(zi)=j=1Kezjzmaxezizmax通过这种方式,我们可以确保所有的指数计算都不会出现数值溢出的问题。

数学推导

为了证明减去最大值不改变 Softmax 的结果,我们可以从公式入手:

z ′ = z − z max ⁡ z' = z - z_{\max} z=zzmax,即 z i ′ = z i − z max ⁡ z'_i = z_i - z_{\max} zi=zizmax,则 Softmax 函数变为:

softmax ( z i ′ ) = e z i ′ ∑ j = 1 K e z j ′ \text{softmax}(z'_i) = \frac{e^{z'_i}}{\sum_{j=1}^{K} e^{z'_j}} softmax(zi)=j=1Kezjezi

z i ′ z'_i zi 代入,得到:

softmax ( z i ′ ) = e z i − z max ⁡ ∑ j = 1 K e z j − z max ⁡ \text{softmax}(z'_i) = \frac{e^{z_i - z_{\max}}}{\sum_{j=1}^{K} e^{z_j - z_{\max}}} softmax(zi)=j=1Kezjzmaxezizmax

因为 e z i − z max ⁡ = e z i e z max ⁡ e^{z_i - z_{\max}} = \frac{e^{z_i}}{e^{z_{\max}}} ezizmax=ezmaxezi,所以:

softmax ( z i ′ ) = e z i e z max ⁡ ∑ j = 1 K e z j e z max ⁡ = e z i e z max ⁡ ∑ j = 1 K e z j e z max ⁡ = e z i ∑ j = 1 K e z j \text{softmax}(z'_i) = \frac{\frac{e^{z_i}}{e^{z_{\max}}}}{\sum_{j=1}^{K} \frac{e^{z_j}}{e^{z_{\max}}}} = \frac{e^{z_i}}{e^{z_{\max}} \sum_{j=1}^{K} \frac{e^{z_j}}{e^{z_{\max}}}} = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}} softmax(zi)=j=1Kezmaxezjezmaxezi=ezmaxj=1Kezmaxezjezi=j=1Kezjezi

可以看到,最终结果与最初定义的 Softmax 函数是一致的。

具体例子

假设我们有一个向量 z = [ 2.0 , 1.0 , 0.1 ] z = [2.0, 1.0, 0.1] z=[2.0,1.0,0.1],我们将计算其 Softmax 值。

步骤 :数值稳定的 Softmax

为了避免数值不稳定性,我们先减去输入向量中的最大值。在这个例子中,最大值是 2.0。

  1. 减去最大值后的向量:
  • z ′ = [ 2.0 − 2.0 , 1.0 − 2.0 , 0.1 − 2.0 ] = [ 0.0 , − 1.0 , − 1.9 ] z' = [2.0 - 2.0, 1.0 - 2.0, 0.1 - 2.0] = [0.0, -1.0, -1.9] z=[2.02.0,1.02.0,0.12.0]=[0.0,1.0,1.9]
  1. 计算新的指数值:
  • e 0.0 = 1.0 e^{0.0} = 1.0 e0.0=1.0
  • e − 1.0 ≈ 0.367879 e^{-1.0} \approx 0.367879 e1.00.367879
  • e − 1.9 ≈ 0.149569 e^{-1.9} \approx 0.149569 e1.90.149569
  1. 求和:
  • ∑ j = 1 3 e z j ′ = 1.0 + 0.367879 + 0.149569 ≈ 1.517448 \sum_{j=1}^{3} e^{z'_j} = 1.0 + 0.367879 + 0.149569 \approx 1.517448 j=13ezj=1.0+0.367879+0.1495691.517448
  1. 计算稳定后的 Softmax 值:
  • softmax ( 0.0 ) = 1.0 1.517448 ≈ 0.659001 \text{softmax}(0.0) = \frac{1.0}{1.517448} \approx 0.659001 softmax(0.0)=1.5174481.00.659001
  • softmax ( − 1.0 ) = 0.367879 1.517448 ≈ 0.242432 \text{softmax}(-1.0) = \frac{0.367879}{1.517448} \approx 0.242432 softmax(1.0)=1.5174480.3678790.242432
  • softmax ( − 1.9 ) = 0.149569 1.517448 ≈ 0.098567 \text{softmax}(-1.9) = \frac{0.149569}{1.517448} \approx 0.098567 softmax(1.9)=1.5174480.1495690.098567
    因此,数值稳定的 Softmax 结果也是 [ 0.659001 , 0.242432 , 0.098567 ] [0.659001, 0.242432, 0.098567] [0.659001,0.242432,0.098567]

Python 实现

import numpy as np

def stable_softmax(x):
    # 减去最大值以提高数值稳定性
    shift_x = x - np.max(x)
    exp_x = np.exp(shift_x)
    softmax_x = exp_x / np.sum(exp_x)
    return softmax_x

# 示例向量
logits = np.array([2.0, 1.0, 0.1])

# 计算 Softmax
softmax_values = stable_softmax(logits)
print(softmax_values)

输出

tensor([0.6590, 0.2424, 0.0986])

Pytorch 实现

import torch
import torch.nn as nn

logits = torch.tensor([2.0, 1.0, 0.1])
softmax = nn.Softmax(dim=0)
probs = softmax(logits)

print(probs)

输出:

tensor([0.6590, 0.2424, 0.0986])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西笑生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值