当前位置: 首页 > 知识库问答 >
问题:

数值稳定softmax

廖弘伟
2023-03-14

有没有一种数值稳定的方法来计算下面的softmax函数?我得到的值在神经网络代码中变成了Nans。

np.exp(x)/np.sum(np.exp(y))

共有3个答案

谭高峯
2023-03-14

扩展@kmario23的答案以支持 1 维或 2 维 numpy 数组或列表(如果您通过 softmax 函数传递一批结果,则很常见):

import numpy as np


def stable_softmax(x):
    z = x - np.max(x, axis=-1, keepdims=True)
    numerator = np.exp(z)
    denominator = np.sum(numerator, axis=-1, keepdims=True)
    softmax = numerator / denominator
    return softmax


test1 = np.array([12345, 67890, 99999999])  # 1D numpy
test2 = np.array([[12345, 67890, 99999999], # 2D numpy
                  [123, 678, 88888888]])    #
test3 = [12345, 67890, 999999999]           # 1D list
test4 = [[12345, 67890, 999999999]]         # 2D list

print(stable_softmax(test1))
print(stable_softmax(test2))
print(stable_softmax(test3))
print(stable_softmax(test4))

 [0. 0. 1.]

[[0. 0. 1.]
 [0. 0. 1.]]

 [0. 0. 1.]

[[0. 0. 1.]]
席弘图
2023-03-14

Softmax函数容易出现两个问题:上溢和下溢

溢出:当非常大的数字近似为无穷大时发生

下溢:当非常小的数字(数字行中接近零)被近似(即四舍五入)为< code >零时,就会发生下溢

为了在进行softmax计算时解决这些问题,一个常见的技巧是通过从所有元素中减去其中的最大元素来移动输入向量。对于输入向量x,定义z如下:

z = x-max(x)

然后取新(稳定)向量的softmaxz

示例:

def stable_softmax(x):
    z = x - max(x)
    numerator = np.exp(z)
    denominator = np.sum(numerator)
    softmax = numerator/denominator

    return softmax

# input vector
In [267]: vec = np.array([1, 2, 3, 4, 5])
In [268]: stable_softmax(vec)
Out[268]: array([ 0.01165623,  0.03168492,  0.08612854,  0.23412166,  0.63640865])

# input vector with really large number, prone to overflow issue
In [269]: vec = np.array([12345, 67890, 99999999])
In [270]: stable_softmax(vec)
Out[270]: array([ 0.,  0.,  1.])

在上述情况下,我们使用stable_softmax()安全地避免了溢出问题

更多详细信息,请参见深度学习一书中的“数值计算”章节。

牛兴安
2023-03-14

软最大 exp(x)/总和(exp(x)) 实际上在数值上表现良好。它只有正项,所以我们不必担心失去意义,分母至少和分子一样大,所以结果保证落在0到1之间。

唯一可能发生的事故是指数级流量过大或过小。单个x元素的溢出或所有x元素的下溢将使输出或多或少变得无用。

但是,通过使用对任何标量 c 成立的恒等式 softmax(x) = softmax(x c) 来说,很容易防止这种情况:从 x 中减去 max(x) 会留下一个只有非正条目的向量,排除溢出和至少一个零元素,排除一个消失的分母(在某些但不是所有条目中,下溢是无害的)。

脚注:从理论上讲,总和中的灾难性事故是可能的,但你需要一个荒谬的术语数量。例如,即使使用只能解析 3 位小数的 16 位浮点数---与“正常”64 位浮点数的 15 位小数相比---我们需要介于 2^1431 (~6 x 10^431) 和 2^1432 之间才能得到相差 2 倍的总和。

 类似资料:
  • 问题内容: 下面有没有一种数值稳定的方法来计算softmax函数?我得到的价值在神经网络代码中变成Nans。 问题答案: softmax exp( x )/ sum(exp( x ))实际上在数字上表现良好。它只有正数项,因此我们不必担心重要性下降,并且分母至少与分子一样大,因此可以保证结果介于0到1之间。 唯一可能发生的事故是指数溢出或溢出。 x 的单个元素的上溢或所有元素的下溢将使输出或多或少

  • 理解了正向传播与反向传播以后,我们来讨论一下深度学习模型的数值稳定性问题以及模型参数的初始化方法。深度模型有关数值稳定性的典型问题是衰减(vanishing)和爆炸(explosion)。 衰减和爆炸 当神经网络的层数较多时,模型的数值稳定性容易变差。假设一个层数为$L$的多层感知机的第$l$层$\boldsymbol{H}^{(l)}$的权重参数为$\boldsymbol{W}^{(l)}$,输

  • 本文向大家介绍Java版基数排序[稳定]相关面试题,主要包含被问及Java版基数排序[稳定]时的应答技巧和注意事项,需要的朋友参考一下 原理:分配加收集 复杂度: O(d(n+r)) r为基数d为位数 空间复杂度O(n+r)

  • 我正在为Android开发一款游戏。游戏:有一个身体(比如说小盒子)。我想:玩家和它碰撞,玩家会跳。在每次碰撞中,它都会跳,但不会跳到相同的高度(在我的代码100px中)!我的代码如下: 盒体的特点是: 和玩家:

  • 我有一个很长的浮点正数列表(