【问题标题】:Why is `NaN` considered "smaller" than `-np.inf` in numpy?为什么在 numpy 中“NaN”被认为比“-np.inf”“小”?
【发布时间】:2017-01-05 13:35:46
【问题描述】:

在涉及np.minnp.argmin 的任何比较中,NaN 被认为小于-np.inf 的原因是什么?

import numpy as np
In [73]: m = np.array([np.nan, 1., 0., -np.inf])
In [74]: n = np.array([-np.inf, 1., 0., np.nan])

# Huh??
In [75]: np.min(m)
Out[75]: nan
In [76]: np.min(n)
Out[76]: nan

# Same for np.argmin
In [77]: np.argmin(m)
Out[77]: 0
In [78]: np.argmin(n)
Out[78]: 3

# Its all false!
In [79]: np.nan < -np.inf
Out[79]: False

In [80]: np.nan > -np.inf
Out[80]: False

# OK, that seems to fix it, but its not necessarily elegant
In [81]: np.nanmin(m)
Out[81]: -inf

In [82]: np.nanargmin(m)
Out[82]: 3

我猜这可能是与返回FalseNaN 值进行任何比较的副作用,但是当您“碰巧”有时会在你的阵列。 np.nanminnp.nanargmin 的使用感觉像是一种快速修复,以某种方式固定在现有行为之上。

除了docs 中的注释:“传播 NaN 值,即如果至少一项为 NaN,则相应的最小值也将为 NaN。忽略 NaN 值(MATLAB 行为) ,请使用 nanmin。,我没有找到任何解释该行为背后的基本原理的东西。这是想要的还是 NaN 值的特定内部表示的副作用?为什么?

【问题讨论】:

  • 您可能会发现这个答案很有帮助:stackoverflow.com/questions/1565164/…
  • 这是一种合乎逻辑的行为:如果某物不是数字,则不能与任何数字比较,因此,任何比较都会返回 false。不仅如此 - 人们可能会争辩说,在大多数情况下,NaN 不是某些操作的预期结果,因此它应该像任何其他异常一样传播。
  • 查看这个最近的答案,stackoverflow.com/a/41324751/901925nan 在此函数和相关函数中显式编码为 maximal
  • 你的前提不正确。 np.nan 相对于任何其他数字(包括其本身)是无序的,不会引发错误。虽然它小于,但它也大于且不等于任何其他数字——包括它自己。这是IEEE 754 的一部分。实现细节是 NaN 是否被信号处理或 NaN 是否被安静地处理。 Numpy 安静地对待。

标签: python numpy nan


【解决方案1】:

正如@Dunno 在评论中提到的那样,将 NaN 与数字进行比较并没有多大意义,因此这种行为可能是可以的。 IEEE 754 标准说明了将 NaN 与数字进行比较:

可能有四种互斥关系:小于、等于、大于和无序。最后一个案例 当至少一个操作数是 NaN 时出现。每个 NaN 都应与所有内容进行无序比较,包括 自己

按照标准:

# Its all false!
In [79]: np.nan < -np.inf
Out[79]: False

将导致“无序”结果,因此它属于“小于”关系是不正确的。

【讨论】:

  • 这种解释的问题在于 Python 中没有“无序”类别,因此 np.nan &lt; 5np.nan &gt; 5np.nan == 5 不能全部计算为 False,但它们确实如此。如果您开始在常规 Python 语句中使用 np.nan,这会导致各种麻烦。例如:min([5, np.nan]) -> 5min([np.nan, 5]) -> np.nan。我想知道为什么np.nan 支持比较并且不会像None 那样引发 TypeError。
【解决方案2】:

所以,你可能已经知道了:-

“inf”是无穷大 - 一个大于任何其他值的值。因此,“-inf”比任何其他值都小,记住这个值是一个数字。

“nan”代表非数字。

因此,如果根据您在上面声明的数组“ m,n ”,并且一旦您对其中任何一个执行“ np.min() ”,实际上只要遇到“ nan ”就会发生另一个不检查或比较元素,执行以下语句并返回值:

 if (@isnan@(mp)) { /* nan encountered; it's maximal */ return 0; } 

因此返回一个“nan”作为函数的答案!

在遇到第一个“nan”时检查它返回的代码,并在相应的函数中返回它的位置

    In [1]: import numpy as np

    In [2]: m = np.array([1., 0., -np.inf, np.nan])

    In [3]: n = np.array([np.nan, 1., np.nan, 0.])

    In [4]: np.argmin(m)
    Out[4]: 3

    In [5]: np.argmin(n)
    Out[5]: 0

并且诸如“ np.nan -np.inf ”之类的操作返回“ False ”,因为“ nan ”不能与任何数字“ -inf ”在这里和上述操作中的“假”不是比较的答案,而是由于一种异常或上述代码的执行,这是由于逻辑错误,因为虽然无穷大,但它不能与事物“无”进行比较" 关于一个数字!

因此,如果您删除数组中的所有“nan”,然后通过“np.nanmin()”计算 min,您将得到预期的输出“-inf”,这不会出现问题!

因此,“Nan”不小于或大于“inf”或“-inf”,因为实际上它不能与任何这些或任何数字进行比较,与任何数字相比它会返回“False”!

    In [1]: np.nan < 1
    Out[1]: False

    In [2]: np.nan > 1
    Out[2]: False

等等......

希望对你有帮助!!

【讨论】:

  • 从技术上讲,numpy c 代码不会引发异常,它只是返回。 if (@isnan@(mp)) { /* nan encountered; it's maximal */ return 0; }stackoverflow.com/questions/41320568/…
  • 是的,通过引发异常,我的意思是一旦遇到“nan”,正常执行就会停止我不知道谢谢@hpaulj
猜你喜欢
  • 2020-12-01
  • 2013-12-17
  • 2012-01-02
  • 2011-09-15
  • 2016-04-03
  • 2018-07-11
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
相关资源
最近更新 更多