首先,回顾softmax函数的定义:?
按照这个定义,softmax()在Python解释器中可以这样实现:
import numpy as np
def softmax(a):
exp_a = np.exp(a)
sum_exp_a = np.sum(exp_a)
return exp_a/sum_exp_a
这样的实现当然没什么问题,下面考虑这样的一种情况,输入如下:
x = np.array([1010,1000,990])
我们采用Python3.8环境下的IDE对其进行计算,结果如:
Warning (from warnings module): ? File "E:/编程语言练习/python/深度学习入门/IDLE的对话实现/softmax.py", line 3 ? ? exp_a = np.exp(a) RuntimeWarning: overflow encountered in exp
Warning (from warnings module): ? File "E:/编程语言练习/python/深度学习入门/IDLE的对话实现/softmax.py", line 5 ? ? return exp_a/sum_exp_a RuntimeWarning: invalid value encountered in true_divide array([nan, nan, nan])
#nan:not a number.也就是不确定的地方
此时在这样的定义下我们无法给出一个正确的结果,从而需要对softmax()进行修改:
在(1)的上下两端同时乘一个因数C,由
?
?可得
令
?就可以得到
至此到(3)就完成了对softmax()函数的改进。
让我们再次回到上面出错的代码当中:
>>> c = np.max(a)
>>> a-c
array([ 0, -10, -20])
>>> np.exp(a-c)/np.sum(np.exp(a-c))
array([9.99954600e-01, 4.53978686e-05, 2.06106005e-09])
>>>
通过减去输入信号的最大值,我们为防止softmax()溢出提供了一种有效的对策,把最大值C作为任意常数带入(3)中,就可以有效防止softmax()作为激活函数时溢出。(减去输入信号的最大值)。
从而,提出一种新的softmax()函数代码作为纠正: ?
def softmax(a):
c = np.max(a)
exp_a = np.exp(a-c)#溢出对策
sum_exp_a = np.sum(exp_a)
y = exp_a/sum_exp_a
return y
|