【问题标题】:Why does float64 produce a RuntimeWarning where float produces a nan?为什么 float64 会产生 RuntimeWarning 而 float 会产生 nan?
【发布时间】:2015-12-02 11:50:25
【问题描述】:

我正在使用warnings 模块将警告作为错误发出。

当我调用我的函数plot_fig_4 时,我收到以下错误:

In [5]: plot_amit.plot_fig_4()
g: 1 of 3
theta_E: 1 of 1000
---------------------------------------------------------------------------
RuntimeWarning                            Traceback (most recent call last)
<ipython-input-5-5a631d2493d7> in <module>()
----> 1 plot_amit.plot_fig_4()

/home/dan/Science/dopa_net/plot_amit.pyc in plot_fig_4()
    130                                                                     tau_0, tau,
    131                                                                     theta_E_,
--> 132                                                                     H)
    133 
    134             # Iterate through theta_I, starting at the lowest value.

/home/dan/Science/dopa_net/plot_support.py in _get_d_phi(mu, sigma, tau_0, tau_i, theta_i, H)
   2059     for (i, mu_), (j, sigma_) in itertools.product(enumerate(mu),
   2060                                                    enumerate(sigma)):
-> 2061         phi[i, j] = _get_phi(tau_0, tau_i, theta_i, mu_, sigma_, H)
   2062     import pdb
   2063     pdb.set_trace()

/home/dan/Science/dopa_net/plot_support.py in _get_phi(tau_0, tau, theta_over_J, mu_over_J, sigma_over_J, H)
   1835 
   1836     # Compute the integral.
-> 1837     integral = _integrate_little_phi(lower, alpha)
   1838 
   1839     # Compute phi.

/home/dan/Science/dopa_net/plot_support.py in _integrate_little_phi(lower, upper)
   1869     upper_int = _integrate(upper)
   1870     lower_int = _integrate(lower)
-> 1871     return upper_int - lower_int
   1872 
   1873 

RuntimeWarning: invalid value encountered in double_scalars

好的。所以我在_integrate_little_phi 中贴了一个pdb.set_trace,就在引发错误的那一行之前,重新运行,并检查相关变量的值:

In [7]: plot_amit.plot_fig_4()
g: 1 of 3
theta_E: 1 of 1000
> /home/dan/Science/dopa_net/plot_support.py(1873)_integrate_little_phi()
-> return upper_int - lower_int
(Pdb) upper_int
inf
(Pdb) lower_int
inf
(Pdb) type(upper_int)
<type 'numpy.float64'>
(Pdb) type(lower_int)
<type 'numpy.float64'>

嗯。所以引发了错误,因为我从无穷大中减去了无穷大。我可以复制吗?

(Pdb) upper_int - lower_int
*** RuntimeWarning: invalid value encountered in double_scalars

是的。但是等一下。让我们再尝试一件事:

(Pdb) np.inf
inf
(Pdb) type(np.inf)
<type 'float'>
(Pdb) np.inf - np.inf
nan

什么什么?当我使用np.inf(其中npnumpy)直接从无穷大中减去无穷大时,我得到nan,而不是RuntimeWarning

为什么我在这个例子中得到nan 而在另一个例子中得到RuntimeWarning我故意发布了类型的差异(floatfloat64)。问题是,为什么这些(微不足道的)不同类型会产生不同的结果?

【问题讨论】:

    标签: python numpy runtime-error warnings infinity


    【解决方案1】:

    因为在 np.inf 的情况下,类型是 float (基本数据类型),而在 upper_int / lower_int 的情况下,数据类型是 numpy.float64 。类似的问题可以通过 -

    重现
    In [7]: a = np.float64('inf')
    
    In [8]: type(a)
    Out[8]: numpy.float64
    
    In [9]: a - a
    RuntimeWarning: invalid value encountered in double_scalars
      if __name__ == '__main__':
    Out[9]: nan
    

    对于np.inf/float的情况-

    In [3]: float('inf') - float('inf')
    Out[3]: nan
    
    In [11]: np.inf
    Out[11]: inf
    
    In [12]: type(np.inf)
    Out[12]: float
    

    我认为这可能是因为在正常情况下 inf ,您无法从计算中得到它。示例 -

    >>> 123123123123. ** 2
    1.5159303447561418e+22
    >>> _ ** 2
    2.298044810152475e+44
    >>> _ ** 2
    5.281009949468725e+88
    >>> _ ** 2
    2.788906608638767e+177
    >>> _ ** 2
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    OverflowError: (34, 'Result too large')
    

    相反,您总是会遇到溢出错误。

    而在使用 np.float64 时,您可以通过计算获得无穷大值(尽管即使在那个时候它也会引发警告)-

    In [63]: n = np.float64('123123123123123123123')
    
    In [64]: n
    Out[64]: 1.2312312312312313e+20
    
    In [65]: n = n ** 2
    
    In [66]: n = n ** 2
    
    In [67]: n = n ** 2
    
    In [68]: n = n ** 2
    C:\Anaconda3\Scripts\ipython-script.py:1: RuntimeWarning: overflow encountered in double_scalars
      if __name__ == '__main__':
    
    In [69]: n
    Out[69]: inf
    

    因此,由于您可以通过计算获得np.float64 infinity,因此当您尝试对其进行更多计算时,它们会发出更多警告,可能会尝试将数字从无穷大减少到更小的值,即减去/除以无穷大(无穷大的乘法或加法很好,因为将无穷大加到无穷大只会返回无穷大)。示例 -

    In [71]: n - n
    C:\Anaconda3\Scripts\ipython-script.py:1: RuntimeWarning: invalid value encountered in double_scalars
      if __name__ == '__main__':
    Out[71]: nan
    
    In [72]: n/n
    C:\Anaconda3\Scripts\ipython-script.py:1: RuntimeWarning: invalid value encountered in double_scalars
      if __name__ == '__main__':
    Out[72]: nan
    
    In [73]: n*n
    Out[73]: inf
    

    尽管在您的情况下,我相信您可能已经从源代码中获得了直接的无限价值。

    【讨论】:

    • 正确。我并没有忘记类型是不同的。我特意检查了这些类型,并发布了它们,因为它们不同。问题是,当类型(微不足道)不同时,为什么结果会不同?
    • 啊,不错的更新。值得注意的是,我在我的函数中获得了 float64 作为 scipy.special 函数的输出。也许scipy 开发人员在决定在他们的函数中使用float64 而不是float 时意识到了这种差异。
    • 此外,在各种情况下,您都会收到np.float64('inf') 而不是np.inf 的警告:例如,0 * x,其中x 是其中之一。跨度>
    • 是的,任何会导致 nan 的东西。
    【解决方案2】:

    似乎没有任何理由减去两个float64s 会引发警告,而减去两个floats 不会。

    因此,这似乎是numpy 中的一个错误。

    我的建议(对我自己)是在减法时将 float64s 转换为 floats:即,

    return upper_int - lower_int
    

    变成

    return float(upper_int) - float(lower_int).
    

    这可以防止警告。

    (当然,在某些情况下,可能需要对这种减法发出警告——对于这些,我会给出相反的建议——即,保持原样。从某种意义上说,有这个很好切换警告。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-28
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 2015-11-20
      • 2020-08-05
      • 2012-08-08
      • 1970-01-01
      相关资源
      最近更新 更多