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

Posted

技术标签:

【中文标题】具有无穷大的复数的 numpy 平均值【英文标题】:numpy mean of complex numbers with infinities 【发布时间】:2017-09-23 09:13:48 【问题描述】:

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 中与复杂无穷大进行交互有任何见解吗?

【问题讨论】:

Complex infinities - funny reslts - a numpy bug?的可能重复 【参考方案1】:

当您在数组中使用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)

【讨论】:

【参考方案2】:

解决方案

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

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=0 术语 a * d * j = inf * 0 * j = nan * j

【讨论】:

【参考方案3】:

因为类型提升。

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

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

回到主题。当numpy 计算一个复杂数组的平均值时,它实际上并没有尝试做任何聪明的事情。首先,它使用“加法”操作来减少数组,得到总和。之后,总和除以计数。这个总和在实部中包含一个inf,当除数(计数)从整数类型提升为复数浮点时,这会导致上述问题。

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

IEEE 浮点“无穷大”实际上是一个非常原始的构造,它表示像1 / 0 这样的不确定形式。这些形式不是常数,而是可能的限制。特殊的infNaN“浮点数”是通知您存在不确定形式的占位符。它们对限制的存在或类型没有任何作用,您必须根据数学上下文来确定。

即使对于实数,基本限制也可能取决于您如何接近限制。一个肤浅的1 / 0 形式可以去正无穷或负无穷。在复平面上,事情甚至更复杂(嗯)。例如,您可能会遇到分支切割和(不同种类的)奇点。没有万能的解决方案。

Tl;dr:解决模糊/不完整/损坏数据时的潜在问题,或证明最终计算结果可以承受这种损坏(可能发生)。

【讨论】:

以上是关于具有无穷大的复数的 numpy 平均值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用逐元素操作获取多个 numpy 保存的数组的均值和标准

Numpy中的矩阵运算+聚合操作+arg运算(2019.1.17)

平均一个很长的列表[双]而不在 Scala 中获得无穷大

numpy/python 中的加权平均值

如何使用 python + NumPy / SciPy 计算滚动/移动平均值?

均值(average)与期望(mean)