2015-10-17 72 views
7

我有以下numpy的陣列和功能:使用numpy的陣列評估函數返回INF和楠

import numpy 
import scipy.special 

i = numpy.linspace(0, 500, 501, dtype = int) 

def func(x, n): 
    return scipy.special.eval_hermite(n, x) 

我使用兩種不同的appraoches評價我numpy的陣列i每個元素的功能方法1:

hermites = func(0, i) 

方法2:

hermites = [func(0, idx) for idx in i] 

這兩種方法導致兩種不同的答案。他們是不同的,因爲元素50,方法1開始返回infnan方法2也不給每個元素i正確的值。但是,它可以計算出更多。方法2對於i >= 64失敗。

兩種方法大致在同一時間給出答案(len(i) = 15000爲0.7秒,使用timeit確定)。我不明白的是不同的結果。這是因爲我學會盡可能避免使用Python中的for loops。這次似乎並非如此。

它與記憶有關的想法也跨越了我的想法。然而,評估一個單一元素,即print func(0, 64)也返回0.(等於輸出方法2)。

這是怎麼回事?

回答

5

這是一個scipy中由numpy的「ufuncs」偶爾令人驚訝的投射規則創建的錯誤。問題是,在scipy版本爲0.16和更高版本時,當eval_hermite的第一個參數是整數數組,第二個參數是整數標量時,返回值的數據類型是單精度浮點數(numpy.float32)。當第二個參數是64位浮點值時,返回類型是numpy.float64。可用float32表示的最大值遠小於float64,因此當第二個參數爲整數時,eval_hermite會很快溢出到無窮大。

例如,這是具有SciPy的0.16.0和1.10.1 numpy的:

In [26]: from scipy.special import eval_hermite 

注意,返回值的數據類型爲float32

In [27]: eval_hermite([20, 50, 100, 200], 0) 
Out[27]: 
array([ 6.70442586e+11,    -inf,    inf, 
        inf], dtype=float32) 

如果第二個參數是浮點數,返回類型爲float64,並且可以表示較大的值:

In [28]: eval_hermite([20, 50, 100, 200], 0.0) 
Out[28]: 
array([ 6.70442573e+011, -1.96078147e+039, 3.06851876e+093, 
     8.45055019e+216]) 

代碼的解決方法是始終確保eval_hermite的第二個參數是浮點值。例如,

hermites = func(0.0, i) 

此問題已得到(見https://github.com/scipy/scipy/pull/4896)固定在SciPy的開發版本,所以SciPy的0.17推出時應該不會有這個問題。

+0

我們應該編輯標題嗎?問題的有趣部分不是關於「爲什麼inf和nan」,而是「爲什麼不傳遞數組並使用listcomp來遍歷元素返回相同的結果?」 – DSM

+0

升級到scipy 0.16.0後獲得更好的結果。然而,現在對於'i> = 270'我再次獲得'inf'或'nan'。這個bug已經完全(所有可能的'我')修復在scipy開發版本?有沒有辦法獲得這個版本? –

+0

對於'i> = 270','x = 0'處的Hermite多項式的值大於可以用64位浮點值表示的值,所以'inf'是可以預期的。對於'i> = 300',我得到'nan';我沒有看過它,但我懷疑有些代碼最終會做'inf - inf'。 –