我正在运行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秒,这是疯了。
答案 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