2017-10-04 59 views
0

當我有一個隨機生成的numpy數字列表並且它們最終爲0.0時,我得到一個無效的值警告和一個nan結果,而不是一個簡單的除以0的異常。爲什麼numpy生成的0.0s列表拋出<RuntimeWarning:在double_scalars中遇到無效值>,而不是被0除錯?

我可以在之前添加一個'nan'的檢查,並返回1而不是(在numsim函數中註釋),只是希望我不會在我的實際數據中隱藏問題。當我打印生成nan的列表時,數值顯示爲0.0。我已閱讀文檔(https://docs.scipy.org/doc/numpy/reference/generated/numpy.seterr.html)並在Google搜索引擎中搜索/查看,看起來最常見的情況是數量太多或數量太小,以至於四捨五入爲0.所以我認爲如果我的數字太小它會打印出這個數字而不是0.0 ---甚至更多,我會猜測numpy不會產生一個非常小的隨機數字。

我的問題是 - 爲什麼會發生這種情況,因爲數字看起來是0.0?有沒有更好的辦法可以做,除了表現無關緊要,捕捉nans並返回1?最重要的是,我可以確定0.0的實際列表將正確執行嗎? (在下面的代碼中,list2不會拋出錯誤,但是如果您運行幾次,list1將會拋出)。

簡化代碼(直到numpy的產生0.0的列表供您運行了好幾次):

import math 
import numpy as np 

list1 = list(np.random.rand(10) * np.random.randint(2)) 
list2 = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] 

def numsim(x, y): 
    try: 
     num = 1 - (abs(x - y)/(abs(x) + abs(y))) 
    except: 
     num = 1 
    ## add this to catch NaN earlier 
    #if math.isnan(num): 
    # print("Caught it.") 
    # num = 1 
    return num 

def mean_sim(tlist1, tlist2): 

    summation = sum([numsim(i1, i2) for i1, i2 in zip(tlist1, tlist2)]) 
    num = 1/len(tlist1) * summation 

    if math.isnan(num) or math.isnan(summation): 
     print('Summation: %s' %str(summation)) 
     print('Num: %s' %str(num)) 
     print('tlist1:') 
     print(tlist1) 
     print('tlist2:') 
     print(tlist2) 
     exit() # instead, probably will: num = 0 # instead of NaN 

    return num 

print("Running with numpy built lists...") 
mean_sim(list1, list1) 
print("Running with list of 0.0...") 
mean_sim(list2, list2) 

輸出(成功的崩潰):

$ python3 ./test2.py 
Running with numpy built lists... 
./test2.py:9: RuntimeWarning: invalid value encountered in double_scalars 
    num = 1 - (abs(x - y)/(abs(x) + abs(y))) 
Summation: nan 
Num: nan 
tlist1: 
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] 
tlist2: 
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] 

回答

0

讓我們注意到開始在

np.random.rand(10) * np.random.randint(2) 

因子np.random.randint(2)是0或1與相等的概率年。並且您將整個數組乘以它,因此以50%的概率,數組全部爲零。這是不是你所期望的?

如果你想要有1或2,那將是np.random.randint(1, 3)documentation


您的代碼看起來很奇怪,因爲你正在使用Python列表,並zip等,而不是內置的NumPy的向量運算。這裏是我的版本:

import numpy as np 
a = np.random.rand(10) * np.random.randint(1, 3) 
b = np.random.rand(10) * np.random.randint(1, 3) 
arr_diff = np.abs(a-b)/(np.abs(a) + np.abs(b)) 
num = np.sum(1 - np.nan_to_num(arr_diff)) 
print(num) 

注意nan_to_num被稱爲由nan值來代替,從兩個數字爲0產生,由0(這是有道理的,因爲這些應該得到類似1)。


NumPy部門不同於普通的Python部門。而0/0引發了一個Python例外,執行np.array([0])/np.array([0])回報array([ nan])與僅僅是一個警告:

__main__:1: RuntimeWarning: invalid value encountered in true_divide 

這種行爲可以使用seterr改變:

np.seterr(divide="raise", invalid="raise") 

確保拋出錯誤兩個1/0和0/0種錯誤。

+0

是的,它的寫法完全是爲了快速生成0的數組。我的原始代碼需要一個長度爲7的列表,其中每個列表都是0到6之間的隨機整數,我很少會遇到NaN問題。我轉換我的其他函數類似,我認爲將我的實際數據轉換爲numpy數組,然後執行數學計算將會生效。謝謝。 – Manner

相關問題