具有无穷大的复数的 numpy 平均值

numpy mean of complex numbers with infinities

numpy 似乎不是复无穷大的好朋友

虽然我们可以评估:

In[2]: import numpy as np

In[3]: np.mean([1, 2, np.inf])
Out[3]: inf

下面的结果比较繁琐:

In[4]: np.mean([1 + 0j, 2 + 0j, np.inf + 0j])
Out[4]: (inf+nan*j)
...\_methods.py:80: RuntimeWarning: invalid value encountered in cdouble_scalars
  ret = ret.dtype.type(ret / rcount)

我不确定虚部对我有意义。但如果我错了,请发表评论。

对在 numpy 中与复杂的无限交互有任何见解吗?

当您 运行 数组中带有 np.inf 的函数时,结果将是 np.mean 或其他函数(例如 np.max())的无限对象。但是在这种情况下计算 mean(),因为你有复数并且无穷大复数被定义为 复数平面中的一个无限数,其复参数未知或未定义 ,您得到 non*j 作为虚部。

为了解决这个问题,您应该忽略此类数学运算中的无穷项。您可以使用 isfinite() 函数来检测它们并将该函数应用于有限项:

In [16]: arr = np.array([1 + 0j, 2 + 0j, np.inf + 0j])

In [17]: arr[np.isfinite(arr)]
Out[17]: array([ 1.+0.j,  2.+0.j])

In [18]: np.mean(arr[np.isfinite(arr)])
Out[18]: (1.5+0j)

因为类型提升。

当您将复数除以实数时,例如 (inf + 0j) / 2,(实数)除数会提升为 2 + 0j

并且通过复数除法,虚部等于(0 * 2 - inf * 0) / 4。注意这里的 inf * 0 是一个不确定的形式,它的计算结果是 NaN。这使得虚部 NaN.

回到主题。当numpy计算复数数组的均值时,它真的没有试图做任何聪明的事情。首先,它使用 "addition" 操作减少数组,获得总和。之后,总和除以计数。此和在实部包含 inf,当除数(计数)从整数类型提升为复数浮点数时会导致上述问题。

编辑:关于解决方案的一句话

IEEE 浮点数 "infinity" 确实是一个非常原始的结构,表示像 1 / 0 这样的不确定形式。这些形式不是常数,而是可能的极限。特殊的 infNaN "floating point numbers" 是占位符,用于通知您存在不确定形式。它们对极限的存在或类型没有任何影响,您必须根据数学上下文来确定。

即使对于实数,潜在限制也可能取决于您接近限制的方式。表面的 1 / 0 形式可以达到正无穷大或负无穷大。在复杂的平面上,事情甚至更加复杂(嗯)。例如,您可以 运行 进入分支切割和(不同种类的)奇点。没有适合所有人的通用解决方案。

Tl;dr:修复ambiguous/incomplete/corrupted数据中的底层问题,或者证明最终的计算结果可以承受这种损坏(可能发生)。

解决方案

为了计算平均值,我们将总和除以一个实数。由于类型提升(见下文),这种划分会导致问题。为了避免类型提升,我们可以手动对总和的实部和虚部分别执行此除法:

n = 3
s = np.sum([1 + 0j, 2 + 0j, np.inf + 0j])
mean = np.real(s) / n + 1j * np.imag(s) / n
print(mean)  # (inf+0j)

理由

这个问题与 numpy 无关,而是与执行复数除法的方式有关。观察 ((1 + 0j) + (2 + 0j) + (np.inf + 0j)) / (3+0j) 也会导致 (inf+nanj).

结果需要分为实部和虚部。对于除法,两个操作数都会提升为复数,即使您除以实数也是如此。所以基本上划分是:

 a + bj
--------
 c + dj

除法运算不知道d=0。因此,要将结果分为实部和虚部,必须去掉分母中的 j。这是通过将分子和分母与复共轭相乘来完成的:

 a + bj     (a + bj) * (c - dj)     ac + bd + bcj - adj
-------- = --------------------- = ---------------------
 c + dj     (c + dj) * (c - dj)        c**2 + d**2

现在,如果 a=infd=0a * d * j = inf * 0 * j = nan * j