在這樣的情況下,masking
幫助 -
def mask_vectorized_app(x):
out = np.empty_like(x)
mask = x>=0
mask_rev = ~mask
out[mask] = np.log(x[mask]+1)
out[mask_rev] = -np.log(-x[mask_rev]+1)
return out
介紹numexpr
module有助於我們進一步。
import numexpr as ne
def mask_vectorized_numexpr_app(x):
out = np.empty_like(x)
mask = x>=0
mask_rev = ~mask
x_masked = x[mask]
x_rev_masked = x[mask_rev]
out[mask] = ne.evaluate('log(x_masked+1)')
out[mask_rev] = ne.evaluate('-log(-x_rev_masked+1)')
return out
通過@user2685079's post
啓發,然後使用logarithmetic屬性:log(A**B) = B*log(A)
,我們可以在簽入日誌計算推,這讓我們做更多的工作numexpr
的計算表達式,像這樣 -
s = (-2*(x<0))+1 # np.sign(x)
out = ne.evaluate('log((abs(x)+1)**s)')
計算sign
使用比較給了我們s
以另一種方式 -
s = (-2*(x<0))+1
最後,我們可以把這個到numexpr
評估表達 -
def mask_vectorized_numexpr_app2(x):
return ne.evaluate('log((abs(x)+1)**((-2*(x<0))+1))')
運行測試
糊塗的做法進行比較 -
def loopy_app(x):
out = np.empty_like(x)
for i in range(len(out)):
out[i] = f(x[i])
return out
時序和驗證 -
In [141]: x = np.random.randn(100000)
...: print np.allclose(loopy_app(x), mask_vectorized_app(x))
...: print np.allclose(loopy_app(x), mask_vectorized_numexpr_app(x))
...: print np.allclose(loopy_app(x), mask_vectorized_numexpr_app2(x))
...:
True
True
True
In [142]: %timeit loopy_app(x)
...: %timeit mask_vectorized_numexpr_app(x)
...: %timeit mask_vectorized_numexpr_app2(x)
...:
10 loops, best of 3: 108 ms per loop
100 loops, best of 3: 3.6 ms per loop
1000 loops, best of 3: 942 µs per loop
使用@user2685079's solution
使用np.sign
以取代第一部分,然後與不numexpr
評價 -
In [143]: %timeit np.sign(x) * np.log(1+abs(x))
100 loops, best of 3: 3.26 ms per loop
In [144]: %timeit np.sign(x) * ne.evaluate('log(1+abs(x))')
1000 loops, best of 3: 1.66 ms per loop
發佈的解決方案是否適用於您? – Divakar
@Divakar對不起,我還沒有可能檢查,如果還沒有。我會在最近的時間嘗試並給出答案 – ichernob