RuntimeWarning:除以零错误:如何避免? PYTHON,NUMPY

时间:2014-08-01 19:57:55

标签: python numpy

我正在运行RuntimeWarning:在div

中遇到无效值
 import numpy
 a = numpy.random.rand((1000000, 100))
 b = numpy.random.rand((1,100))
 dots = numpy.dot(b,a.T)/numpy.dot(b,b)
 norms = numpy.linalg.norm(a, axis =1)
 angles = dots/norms ### Basically I am calculating angle between 2 vectors 

我的a中有一些向量的范数为0.因此在计算角度时它会给出运行时警告。

是否有一种单线pythonic方法来计算角度,同时考虑到0的规范?

angles =[i/j if j!=0 else -2 for i,j in zip(dots, norms)] # takes 10.6 seconds

但这需要很多时间。由于所有角度的值都在1到-1之间,我只需要10个最大值,这对我有帮助。这需要大约10.6秒,这是疯了。

5 个答案:

答案 0 :(得分:6)

您可以忽略与np.errstate上下文管理器的警告,然后将nans替换为您想要的内容:

import numpy as np
angle = np.arange(-5., 5.) 
norm = np.arange(10.)
with np.errstate(divide='ignore'):
    print np.where(norm != 0., angle / norm, -2)
# or:
with np.errstate(divide='ignore'):
    res = angle/norm
res[np.isnan(res)] = -2

答案 1 :(得分:2)

您可以使用angles[~np.isfinite(angles)] = ...nan值替换为其他值。

例如:

In [103]: angles = dots/norms

In [104]: angles
Out[104]: array([[ nan,  nan,  nan, ...,  nan,  nan,  nan]])

In [105]: angles[~np.isfinite(angles)] = -2

In [106]: angles
Out[106]: array([[-2., -2., -2., ..., -2., -2., -2.]])

请注意,除以零可能会导致inf s,而不是nan s,

In [140]: np.array([1, 2, 3, 4, 0])/np.array([1, 2, 0, -0., 0])
Out[140]: array([  1.,   1.,  inf, -inf,  nan])

所以最好拨打np.isfinite而不是np.isnan来识别除以零的地方。

In [141]: np.isfinite(np.array([1, 2, 3, 4, 0])/np.array([1, 2, 0, -0., 0]))
Out[141]: array([ True,  True, False, False, False], dtype=bool)

请注意,如果您只想要NumPy数组中的前十个值,那么使用np.argpartition函数可能比完全排序整个数组更快,特别是对于大型数组:

In [110]: N = 3

In [111]: x = np.array([50, 40, 30, 20, 10, 0, 100, 90, 80, 70, 60])

In [112]: idx = np.argpartition(-x, N)

In [113]: idx
Out[113]: array([ 6,  7,  8,  9, 10,  0,  1,  4,  3,  2,  5])

In [114]: x[idx[:N]]
Out[114]: array([100,  90,  80])

这表明即使只有中等大小的数组,np.argpartition也会更快:

In [123]: x = np.array([50, 40, 30, 20, 10, 0, 100, 90, 80, 70, 60]*1000)

In [124]: %timeit np.sort(x)[-N:]
1000 loops, best of 3: 233 µs per loop

In [125]: %timeit idx = np.argpartition(-x, N); x[idx[:N]]
10000 loops, best of 3: 53.3 µs per loop

答案 2 :(得分:2)

您想要使用np.where。请参阅documentation

angles = np.where(norms != 0, dots/norms, -2)

每当downs/norms时,角度将由norms != 0组成,否则将为-2。您仍会获得RuntimeWarning,因为np.where仍将在内部计算整个向量dots/norms,但您可以放心地忽略它。

答案 3 :(得分:2)

在较新版本的numpy中,有第三个替代选项可以避免需要使用errstate上下文管理器。

所有Numpy ufuncs接受一个可选的"其中"论点。这与np.where函数的作用略有不同,因为它只评估函数"其中"面具是真的。当掩码为False时,它不会更改该值,因此使用" out"参数允许我们预先分配我们想要的任何默认值。

import numpy as np

angle = np.arange(-5., 5.)
norm = np.arange(10.)

# version 1
with np.errstate(divide='ignore'):
    res1 = np.where(norm != 0., angle / norm, -2)

# version 2
with np.errstate(divide='ignore'):
    res2 = angle/norm
res2[np.isinf(res2)] = -2

# version 3
res3 = -2. * np.ones(angle.shape)
np.divide(angle, norm, out=res3, where=norm != 0)

print(res1)
print(res2)
print(res3)

np.testing.assert_array_almost_equal(res1, res2)
np.testing.assert_array_almost_equal(res1, res3)

答案 4 :(得分:0)

您可以使用np.where( condition )执行条件切片,其中规范在除以之前不等于0:

norms = np.where(norms != 0 ) 
angles = dots/norms