Python 假设0*无穷大=0时,如何在NumPy中乘以.outer()?
我试图在多维数组上使用Python 假设0*无穷大=0时,如何在NumPy中乘以.outer()?,python,numpy,floating-point,infinity,Python,Numpy,Floating Point,Infinity,我试图在多维数组上使用numpy.multiply.outer,我真的需要它来假设它看到的任何0*无穷大都计算为零。我怎样才能有效地做到这一点 >>> import numpy >>> numpy.multiply.outer([0.], [float('inf')]) Warning (from warnings module): File "__main__", line 2 RuntimeWarning: invalid value encounte
numpy.multiply.outer
,我真的需要它来假设它看到的任何0*无穷大
都计算为零。我怎样才能有效地做到这一点
>>> import numpy
>>> numpy.multiply.outer([0.], [float('inf')])
Warning (from warnings module):
File "__main__", line 2
RuntimeWarning: invalid value encountered in multiply
array([[ nan]])
一种解决方案是避免使用np.multiply.outer,并对已经检查过的矩阵(一个数组中为零,另一个数组中为inf)使用元素乘法查找解决方案
然而,这可能无法通过海报的“效率”要求 您是否需要担心
nan
值的其他来源?如果没有,您可以在单独的步骤中进行修复:
import numpy as np
r = np.multiply.outer([0.], [float('inf')])
np.where(np.isnan(r), 0, r)
如果要抑制警告,由您决定。以下是抑制警告的方法: 将
nan
替换为1
:
In [542]: z[np.isnan(z)]=1
In [543]: z
Out[543]:
array([[ 1., 0., 0.],
[ inf, 3., 2.],
[ inf, 6., 4.]])
In [547]: z[np.isinf(z)]=9999
In [548]: z
Out[548]:
array([[ 1.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ 9.99900000e+03, 3.00000000e+00, 2.00000000e+00],
[ 9.99900000e+03, 6.00000000e+00, 4.00000000e+00]])
=================
我们可以使用@p-robot
演示的测试类型来创建面具
:
In [570]: np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
Out[570]:
array([[ True, False, False],
[False, False, False],
[False, False, False]], dtype=bool)
In [571]: mask=np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
In [572]: with warnings.catch_warnings():
...: warnings.simplefilter('ignore',category=RuntimeWarning)
...: z = np.outer(x,y)
...:
In [573]: z[mask]=1
In [574]: z
Out[574]:
array([[ 1., 0., 0.],
[ inf, 3., 2.],
[ inf, 6., 4.]])
或使用messier输入:
In [587]: x = np.array([0,1,2,np.inf],float)
In [588]: y = np.array([np.inf,3,np.nan,0],float)
In [589]: mask=np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
...
In [591]: with warnings.catch_warnings():
...: warnings.simplefilter('ignore',category=RuntimeWarning)
...: z = np.outer(x,y)
...:
In [592]: z[mask]=1
In [593]: z
Out[593]:
array([[ 1., 0., nan, 0.],
[ inf, 3., nan, 0.],
[ inf, 6., nan, 0.],
[ inf, inf, nan, 1.]])
虽然我同意@ShadowRanger的答案,但一个便宜的黑客可以利用它,它用大的有限数替换inf,然后得到inf*0=0 要将不需要的剩余高位有限数转换回inf(除了您的问题之外,还提供了一些其他操作),您可以将高位数乘以任何大于1的值,然后除以相同的值(以免影响其他数字)。例如:
在大量的否决票之前,这显然不是一个最佳实践,并且可能会产生副作用,具体取决于您的用例,但我想我会抛出一个替代方案。基本上有两个选择-在使用前更改
np.inf
使其合理,或者将警告更改为忽略,并在事实发生后(如果需要的话)修正值。@hpaulj:我不能事先将inf更改为合理的值,因为我不能保证它们被乘以零。我不能在事后更改它们,因为我真的不知道NAN是从哪里来的。您应该提供一个包含您所关心的所有细微差别的测试用例。您要保留的带有inf
或nan
的一个,以及您要更改的这个。是的,我仍然希望获得其他情况下的正常行为。但是+1,因为它对某些人来说是一个解决办法(尽管这是一个显而易见的办法)。呃+1因为它仍然比循环好,但是是的,不是我所希望的。是的,我很欣赏它不是最优雅(或有效)的解决方案,但它避免了抑制警告。干杯。这假设两个输入数组中都没有NAN,对吗?否则你可能会掩盖一些东西。我已经按照P-robot的回答添加了一个掩蔽测试。
In [570]: np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
Out[570]:
array([[ True, False, False],
[False, False, False],
[False, False, False]], dtype=bool)
In [571]: mask=np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
In [572]: with warnings.catch_warnings():
...: warnings.simplefilter('ignore',category=RuntimeWarning)
...: z = np.outer(x,y)
...:
In [573]: z[mask]=1
In [574]: z
Out[574]:
array([[ 1., 0., 0.],
[ inf, 3., 2.],
[ inf, 6., 4.]])
In [587]: x = np.array([0,1,2,np.inf],float)
In [588]: y = np.array([np.inf,3,np.nan,0],float)
In [589]: mask=np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
...
In [591]: with warnings.catch_warnings():
...: warnings.simplefilter('ignore',category=RuntimeWarning)
...: z = np.outer(x,y)
...:
In [592]: z[mask]=1
In [593]: z
Out[593]:
array([[ 1., 0., nan, 0.],
[ inf, 3., nan, 0.],
[ inf, 6., nan, 0.],
[ inf, inf, nan, 1.]])
In [1]: np.nan_to_num(np.inf)
Out[1]: 1.7976931348623157e+308
In [2]: np.nan_to_num(np.inf)*1.1
RuntimeWarning: overflow encountered in double_scalars
Out[2]: inf
In [3]: np.nan_to_num(np.inf)*1.1/1.1
RuntimeWarning: overflow encountered in double_scalars
Out[3]: inf