商业稳定的softmax

Abh*_*tia 11 python numpy nan scientific-computing softmax

下面有一个数值稳定的方法来计算softmax函数吗?我在神经网络代码中获得的值变为Nans.

np.exp(x)/np.sum(np.exp(y))
Run Code Online (Sandbox Code Playgroud)

Pau*_*zer 34

softmax exp(x)/ sum(exp(x))实际上在数值上表现良好.它只有正项,所以我们不必担心重要性的损失,分母至少与分子一样大,所以结果保证在0到1之间.

唯一可能发生的事故是指数过度或不足.x的所有元素的单个或下溢的溢出将使输出或多或少无用.

但是很容易通过使用标识softmax(x)= softmax(x + c)来保护任何标量c:从x减去max(x)只留下一个只有非正条目的向量,排除了溢出并且至少有一个零元素排除了消失的分母(某些但不是所有条目的下溢都是无害的).

注意:从理论上讲,总和中的灾难性事故是可能的,但你需要一些荒谬的术语,并且是荒谬的不幸.此外,numpy使用相对强大的成对求和.


kma*_*o23 12

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

溢出:当非常大的数字近似infinity

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

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

z = x-max(x)
Run Code Online (Sandbox Code Playgroud)

然后取新(稳定)向量的softmax z


例:

In [266]: def stable_softmax(x):
     ...:     z = x - max(x)
     ...:     numerator = np.exp(z)
     ...:     denominator = np.sum(numerator)
     ...:     softmax = numerator/denominator
     ...:     return softmax
     ...: 

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])

In [269]: vec = np.array([12345, 67890, 99999999])

In [270]: stable_softmax(vec)
Out[270]: array([ 0.,  0.,  1.])
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参见章数值计算深度学习的书。


Dav*_*rks 6

扩展@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
test2 = np.array([[12345, 67890, 99999999], [123, 678, 88888888]])  # 2D
test3 = [12345, 67890, 999999999]
test4 = [[12345, 67890, 999999999]]

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.]]
Run Code Online (Sandbox Code Playgroud)