在我的代碼中,我必須考慮與不同的閾值有關的不同貢獻。特別是我有一個函式my_index,其輸出必須與閾值Z_1, Z_2, Z_3進行比較,以確定變數my_value的增量。在下面的MWE中,為了簡單起見,函式my_index只是一個統一的隨機生成器:
import numpy as np
my_len = 100000 as np
Z_1 = 0.2
Z_2 = 0.4
Z_3=0.7
第一 = 1
第二=2
第三個=-0.0003
my_value =0
for i in range(my_len)。
my_index = np.random.uniform()
my_value = first*np.highiside(my_index - Z_1,0)*np.highiside(Z_2 - my_index,0) second*np. heaviside(my_index - Z_3,0) third*np.highiside(Z_3 - my_index,0)
#if Z_1 < my_index < Z_2 add first.
#if my_index > Z_3添加第二個。
#if my_index < Z_3添加第三。
我已經替換了if/else的內容,這些內容本可以用Heaviside函式查看的閾值。
我的問題是:這種做法是否使代碼更快?或者說,就速度而言,heavyiside函式(np.heavyiside)的呼叫更好于if/else控制元件?
uj5u.com熱心網友回復:
假設你使用標準的CPython 解釋器,那么執行Numpy 函式呼叫,如np.heaviside,可能比做基本條件反射更昂貴。然而,兩者都是非常低效的。事實上,條件反射一般都很慢,在這里可以用無分支實作來代替(加/乘轉換為整數的布林值)。最重要的優化是使用矢量化,因為Numpy的設計是對相對較大的陣列而不是標量值進行高效處理(主要是因為額外的內部檢查和函式呼叫)。你可以在一個大陣列中生成所有的隨機值,對其多次應用heavyiside函式。由此產生的代碼肯定會快2到3個數量級!
uj5u.com熱心網友回復:
在 [433]: x=np.range(-10,10)
在[434]: x
輸出[434]。
array([-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2,
3, 4, 5, 6。 7, 8, 9] )
正確使用heaviside--將x作為陣列,而不是單個值:
在[436]: np.heaviside(x,.5)
Out[436]。
array([0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.5, 1. , 1. 。
1. , 1. , 1. , 1。 , 1. , 1. , 1. ])
串列理解的等價物:
在[437]: [. 5 if i==0 else (0 if i< 0 else 1) for i in x] 。
出來[437]。[0, 0, 0, 0, 0, 0, 0, 0, 0, 0。 5, 1, 1, 1, 1, 1, 1, 1, 1]
并從該串列中制作一個陣列:
在[438]: np.array([. 5 if i==0 else (0 if i< 0 else 1) for i in x] )
Out[438]。
array([0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.5, 1. , 1. 。
1. , 1. , 1. , 1。 , 1. , 1. , 1. ])
比較時間:
在 [439]: timeit np.heavyiside(x,.5)
2.5 μs ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loop each)
在[440]: timeit np.array([. 5 if i==0 else (0 if i< 0 else 1) for i in x] )
15.1 μs ± 25.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loop each)
在串列上的迭代比在陣列上的迭代要快:
在[441]: timeit np.array([. 5 if i==0 else (0 if i< 0 else 1) for i in x.tolist() ])
6.66 μs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
而如果我們跳過轉換回串列的程序:
在 [442]: timeit [. 5 if i==0 else (0 if i< 0 else 1) for i in x.tolist() ]
2.28 μs ± 3.01 ns per loop (mean ± std. dev. of 7 runs, 100000 loop each)
對于一個更大的陣列,heaviside的性能甚至更好:
在[445]: x=np.range(-1000,1000)
在[446]: timeit [. 5 if i==0 else (0 if i< 0 else 1) for i in x.tolist() ]
211 μs ± 7 μs per loop (mean ± std. dev. of 7 runs, 1000 loop each)
在[447]中:timeit np.heavyiside(x,.5)
13 μs ± 201 ns per loop (mean ± std. dev. of 7 runs, 100000 loop each)
對于亂數的生成,采取整數的方法也更快:
對于亂數的生成,采取整數的方法也更快。
在 [448]: timeit [np.random. uniform() for _ in range(1000)]
4.62 ms ± 20.3 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
在[449]: timeit np.random.uniform(1000)
4.74 μs ± 171 ns per loop (mean ± std. dev. of 7 runs, 100000 loop each)
我也可以對heaviside的標量使用進行計時--這比[446]中的if/else更糟糕:
在 [450]: timeit [np. heaviside(i,.5) for i in x] 。
8.64 ms ± 44.2 μs per loop (mean ± std. dev. of 7 runs, 100 loop each)
總之:
- 在可能的情況下使用整個陣列的代碼 。
- 當使用Python級別的迭代時,使用串列和標量方法代替 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/323171.html
標籤:
上一篇:ValueError:Toomanyvaluestounpack(expected2),當我試圖從一個regex模式中只提取2個子字串時
