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