Python 运行时警告:除以零错误:如何避免?蟒蛇,NUMPY

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25087769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 19:42:40  来源:igfitidea点击:

RuntimeWarning: Divide by Zero error: How to avoid? PYTHON, NUMPY

pythonnumpy

提问by pg2455

I am running in to RuntimeWarning: Invalid value encountered in divide

我遇到了 RuntimeWarning: 在除法中遇到无效值

 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 

There are some vectors in my a which have norm as 0. so while calculating angles it is giving runtime warning.

我的 a 中有一些向量的范数为 0。所以在计算角度时它会发出运行时警告。

Is there a one line pythonic way to compute angles while taking into account norms which are 0?

考虑到0的范数,是否有一种单行pythonic方法来计算角度?

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

But it takes a lot of time. Since all angles will have values between 1 and -1 and I need only 10 max values this will help me. This takes around 10.6 seconds which is insane.

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

采纳答案by jtaylor

you can ignore warings with the np.errstatecontext manager and later replace nans with what you want:

您可以使用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

回答by agconti

You can use np.where( condition )to perform a conditional slice of where norms does not equal 0 before dividing:

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

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

回答by unutbu

You could use angles[~np.isfinite(angles)] = ...to replace nanvalues with some other value.

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

For example:

例如:

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

Note that division by zero may result in infs, rather than nans,

请注意,除以零可能会导致infs,而不是nans,

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

so it is better to call np.isfiniterather than np.isnanto identify the places where there was division by zero.

所以最好打电话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)


Note that if you only want the top ten values from an NumPy array, using the np.argpartitionfunction may be quicker than fully sorting the entire array, especially for large arrays:

请注意,如果您只想要 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])

This shows np.argpartitionis quicker for even only moderately large arrays:

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

回答by Roger Fan

You want to be using np.where. See the documentation.

您想使用np.where. 请参阅文档

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

Angles will consist of downs/normswhenever norms != 0, and will be -2 otherwise. You will still get the RuntimeWarning, as np.wherewill still calculate the entire vector dots/normsinternally, but you can safely ignore it.

角度将包括downs/norms无论何时norms != 0,并将于-2不然。您仍将获得 RuntimeWarning,因为np.where仍会在dots/norms内部计算整个向量,但您可以放心地忽略它。

回答by DStauffman

In newer versions of numpy there is a third alternative option that avoids needing to use the errstate context manager.

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

All Numpy ufuncsaccept an optional "where" argument. This acts slightly differently than the np.where function, in that it only evaluates the function "where" the mask is true. When the mask is False, it doesn't change the value, so using the "out" argument allows us to preallocate any default we want.

所有 Numpy ufunc 都接受一个可选的“where”参数。这与 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)