在实际计算中,直接使用上述公式可能会导致数值不稳定性,尤其是当
z
z
z 中的某些值非常大或非常小时,可能会导致指数函数溢出。因此,我们需要对 Softmax 函数进行数值稳定性的改进。具体的改进方法如下:
减去最大值:为了避免指数函数溢出,我们可以在计算 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=1Kezj−zmaxezi−zmax通过这种方式,我们可以确保所有的指数计算都不会出现数值溢出的问题。
数学推导
为了证明减去最大值不改变 Softmax 的结果,我们可以从公式入手:
令
z
′
=
z
−
z
max
z' = z - z_{\max}
z′=z−zmax,即
z
i
′
=
z
i
−
z
max
z'_i = z_i - z_{\max}
zi′=zi−zmax,则 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=1Kezj′ezi′
将
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=1Kezj−zmaxezi−zmax
因为
e
z
i
−
z
max
=
e
z
i
e
z
max
e^{z_i - z_{\max}} = \frac{e^{z_i}}{e^{z_{\max}}}
ezi−zmax=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=ezmax∑j=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 值。