2017-10-06 31 views
2

numpyの2次元配列で各行をとり、特定の計算のスカラー結果を返す関数を実装しようとしています。私の現在のコードは次のようになります。numpy apply_along_axisベクトル化

img = np.array([ 
    [0, 5, 70, 0, 0, 0 ], 
    [10, 50, 4, 4, 2, 0 ], 
    [50, 10, 1, 42, 40, 1 ], 
    [10, 0, 0, 6, 85, 64], 
    [0, 0, 0, 1, 2, 90]] 
) 

def get_y(stride): 
    stride_vals = stride[stride > 0] 
    pix_thresh = stride_vals.max() - 1.5*stride_vals.std() 
    return np.argwhere(stride>pix_thresh).mean() 

np.apply_along_axis(get_y, 0, img) 
>> array([ 2. , 1. , 0. , 2. , 2.5, 3.5]) 

期待どおりに動作します実際のデータセットに〜2kの行や〜、フレームごとに20〜50列があるとして、しかし、パフォーマンスは60回来て、素晴らしいではありません秒。

おそらくnp.apply_along_axis機能を使用しないことによってプロセスをスピードアップする方法はありますか?

+0

私はapply_along_axisが単純な行の反復よりも遅いと予想します。 – hpaulj

+0

@hpaulj私はそれをテストしましたが、実際には速度を上げるには反復処理を少し遅くしています。何か特別な理由はありますか?軸に沿って適用すると一般に行の反復よりも遅い場合、そのような機能を持つ点は何ですか? – ymoiseev

+1

便宜。それはあなたが読むことができるPythonコードです。ループや関数の評価はコンパイルされません。ループを一般化するだけで、複数の次元(4次元配列の他の3つ)での評価を簡単に表現できます。ループインデックスを生成するために 'np.ndindex'を使います。 – hpaulj

答えて

2

ここNaNとしてzerosを設定する1つのベクトル化のアプローチだとそれは私たちがそうのように、zerosを避けたものmaxstd値を計算するnp.nanmaxnp.nanstdを使用してみましょう -

imgn = np.where(img==0, np.nan, img) 
mx = np.nanmax(imgn,0) # np.max(img,0) if all are positive numbers 
st = np.nanstd(imgn,0) 
mask = img > mx - 1.5*st 
out = np.arange(mask.shape[0]).dot(mask)/mask.sum(0) 

ランタイムテスト -

In [94]: img = np.random.randint(-100,100,(2000,50)) 

In [95]: %timeit np.apply_along_axis(get_y, 0, img) 
100 loops, best of 3: 4.36 ms per loop 

In [96]: %%timeit 
    ...: imgn = np.where(img==0, np.nan, img) 
    ...: mx = np.nanmax(imgn,0) 
    ...: st = np.nanstd(imgn,0) 
    ...: mask = img > mx - 1.5*st 
    ...: out = np.arange(mask.shape[0]).dot(mask)/mask.sum(0) 
1000 loops, best of 3: 1.33 ms per loop 

このように、私たちは高速化を見ています。3x+

+1

ありがとう、これは素晴らしい作品です。大きな画像の場合、100倍以上の高速化が可能です! – ymoiseev

関連する問題