如何避免 numpy.exp() 中的溢出
How to avoid an overflow in numpy.exp()
我阅读了很多关于堆栈溢出的内容,但我仍然不明白如何避免溢出错误。我正在构建一个使用 sigmoid function 的神经网络。
但如果不转换或找到这些错误的解决方法,我就无法继续。
def activation(x):
return 1/(1+np.exp(-x))
def dactivation(x):
return activation(x)*(1-activation(x))
def propagateb(self, target, lrate=8.1, momentum=0.1):
deltas = []
error = target - self.layers[-1]
delta = error*dactivation(self.layers[-1])
deltas.append(delta)
for i in range(len(self.shape)-2,0,-1):
delta =np.dot(deltas[0],self.weights[i].T)*dactivation(self.layers[i])
deltas.insert(0,delta)
for i in range(len(self.weights)):
layer = np.atleast_2d(self.layers[i])
delta = np.atleast_2d(deltas[i])
dw = np.dot(layer.T,delta)
self.weights[i] += lrate*dw + momentum*self.dw[i]
self.dw[i] = dw
# Return error
return (error**2).sum()
提高
ann.py:5: RuntimeWarning: overflow encountered in exp
return 1/(1+np.exp(-x))
似乎传入的数据必须是一个整数,虽然这个激活函数应该return一个浮点数。我认为修复就像
一样简单
return 1./(1.+np.exp(-x))
我猜如果没有这个更改,代码会尝试进行整数除法,从而产生错误。
SciPy comes with a function to do that,不会给你那个警告:
scipy.special.expit(x)
使用 numpy 整数时必须小心,因为它们没有此处所述的任意精度 Can Integer Operations Overflow in Python?
对于 numpy double,该范围是 (-1.79769313486e+308, 1.79769313486e+308)
。
也可以看看这个answer,它描述得很好。
Here 是关于 numpy dtype 及其允许范围的更多信息。
我们的想法是您应该避免调用 exp(something)
时 something
太大。所以避免在 x >> 0
时使用 exp(x)
并避免在 x << 0
.
时使用 exp(-x)
为了实现这一点,您可以先编写一个适用于 x > 0 的表达式和另一个适用于 x < 0 的表达式。
- 如果 x > 0,您可以安全地使用您的表达式:
1/(1+exp(-x))
- 对于 x < 0,您通过将分子和分母乘以
exp(x)
重写该表达式,得到 exp(x) / (1+exp(x))
。如您所见,这里不再有 exp(-x)
。
您可以找到适用于这两种情况的表达式:
给定 x 是一个矩阵,我在这里的个人实验中使用了 np.exp(np.fmin(x, 0)) / (1 + np.exp(-np.abs(x)))
https://github.com/thirionjl/chains/blob/master/chains/operations/activation_ops.py#L42
我阅读了很多关于堆栈溢出的内容,但我仍然不明白如何避免溢出错误。我正在构建一个使用 sigmoid function 的神经网络。 但如果不转换或找到这些错误的解决方法,我就无法继续。
def activation(x):
return 1/(1+np.exp(-x))
def dactivation(x):
return activation(x)*(1-activation(x))
def propagateb(self, target, lrate=8.1, momentum=0.1):
deltas = []
error = target - self.layers[-1]
delta = error*dactivation(self.layers[-1])
deltas.append(delta)
for i in range(len(self.shape)-2,0,-1):
delta =np.dot(deltas[0],self.weights[i].T)*dactivation(self.layers[i])
deltas.insert(0,delta)
for i in range(len(self.weights)):
layer = np.atleast_2d(self.layers[i])
delta = np.atleast_2d(deltas[i])
dw = np.dot(layer.T,delta)
self.weights[i] += lrate*dw + momentum*self.dw[i]
self.dw[i] = dw
# Return error
return (error**2).sum()
提高
ann.py:5: RuntimeWarning: overflow encountered in exp
return 1/(1+np.exp(-x))
似乎传入的数据必须是一个整数,虽然这个激活函数应该return一个浮点数。我认为修复就像
一样简单return 1./(1.+np.exp(-x))
我猜如果没有这个更改,代码会尝试进行整数除法,从而产生错误。
SciPy comes with a function to do that,不会给你那个警告:
scipy.special.expit(x)
使用 numpy 整数时必须小心,因为它们没有此处所述的任意精度 Can Integer Operations Overflow in Python?
对于 numpy double,该范围是 (-1.79769313486e+308, 1.79769313486e+308)
。
也可以看看这个answer,它描述得很好。
Here 是关于 numpy dtype 及其允许范围的更多信息。
我们的想法是您应该避免调用 exp(something)
时 something
太大。所以避免在 x >> 0
时使用 exp(x)
并避免在 x << 0
.
exp(-x)
为了实现这一点,您可以先编写一个适用于 x > 0 的表达式和另一个适用于 x < 0 的表达式。
- 如果 x > 0,您可以安全地使用您的表达式:
1/(1+exp(-x))
- 对于 x < 0,您通过将分子和分母乘以
exp(x)
重写该表达式,得到exp(x) / (1+exp(x))
。如您所见,这里不再有exp(-x)
。
您可以找到适用于这两种情况的表达式:
给定 x 是一个矩阵,我在这里的个人实验中使用了 np.exp(np.fmin(x, 0)) / (1 + np.exp(-np.abs(x)))
https://github.com/thirionjl/chains/blob/master/chains/operations/activation_ops.py#L42