• 深入理解交叉熵损失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])
    
  • 相关阅读:
    界面拖动界面拖动
    【技巧】Git 版本控制工具没有图标提示怎么办?
    数据挖掘案列分析---LightGBM实战贷款违约预测
    软著材料编写脚本
    day5:Node.js 第三方库
    Linux孤儿进程|僵尸进程
    上古神器:十六位应用程序 Debug 的基本使用
    Spring WebFlux入门实践
    Linux ps指令介绍
    轻松玩转Vite/Rollup/webpack/esbuild/Rspack/babel插件开发(一)
  • 原文地址:https://blog.csdn.net/flyfish1986/article/details/139544229