2016-03-27 15 views
1

私は何千回も呼ばれるネストされたforループを持つpython関数を持っていて、遅すぎます。私がオンラインで読んだことから、numpyのベクトル化で最適化して、反復がPythonよりはるかに高速なCコードで行われるようにする方法があるはずです。しかし、私は前にnumpyで働いたことがなく、私はそれを理解できません。NumPyを使ってDouble For Loopを最適化

機能は以下のとおりです。最初のパラメータは2次元配列(リストのリスト)です。 2番目のパラメータは、チェックする2次元配列の行のリストです。 3番目のパラメータは、チェックする2D配列の列のリストです(行の数は​​列の数と等しくないことに注意してください)。第4のパラメータは、2D配列の要素を比較するための値です。私はリストを含む各列のリストを返そうとしていますが、valに等しい要素に対応するすべての行インデックスがリストに含まれています。

def filter_indices(my_2d_arr, rows, cols, val): 
    result_indices = [] 

    for c in cols: 
     col_indices = [] 

     for idx in rows: 
      if my_2d_arr[idx][c] == val: 
       col_indices.append(idx) 
     result_indices.append(col_indices) 

    return result_indices 

私が言ったように、これはあまりにも遅く、どのようにベクトル化できるか混乱しています。どんなポインタ/ガイダンスも素晴らしいでしょう。

EDIT

@ B.M。ご回答有難うございます。私はあなたのソリューションを自分のコードの残りの部分とは別に走らせ、numpyを使わずに以前の関数と比較しました。あなたが言ったように、それは私の元の機能がしたように、はるかに速く働きました。しかし、コードの一部として実行すると、私の解決策は何らかの理由で実際には遅くなります。あなたの関数に少し追加して既存のコードを修正して互換性を持たせる必要がありましたが、その時にnumpyのバージョンが高速で、cProfileがオリジナルのfilter_indices関数が高速であることを示していると言っています新しいかすかなものよりも。私は、コードの残りの部分とは別に実行したほうが速いことを考慮して、どうやらnumpyのfilter_indicesがそれほど長くかかるとは考えていません。ここで

は私のオリジナルfilter_indicesはnumpyのなしだ:

def filter_indices_orig(a, data_indices, feature_set, val): 
    result_indices = [] 

    for feature_no in feature_set: 
     feature_indices = [] 

     for idx in data_indices: 
      if a[idx][feature_no] == val: 
       feature_indices.append(idx) 
     result_indices.append(feature_indices) 

    return result_indices 

はここでnumpyのと私の少し変更しfilter_indicesです:

def filter_indices(a, data_indices, feature_set, val): 
    result_indices = {} 
    sub = a[np.meshgrid(data_indices, feature_set, indexing='ij')] 
    r, c = (sub == val).nonzero() 
    rs = np.take(data_indices, r) 
    cs = np.take(feature_set, c) 
    coords = zip(rs, cs) 

    for r, c in coords: 
     feat_indices = result_indices.get(c, []) 
     feat_indices.append(r) 
     result_indices[c] = feat_indices 

    return result_indices 

EDIT 2

は、私はときに私numpyのソリューションが遅いことを考え出しましたいくつかの列のみを検索していますが、多数の列を探していると高速です。残念ながら、検索対象の列が多数あるときにnumpyソリューションを使用しているときに、いくつかの列が検索されているときにも、元の非numpyソリューションを使用していても、わかりません。

ここ

答えて

0

値が選択されたサブアレイでvalある画素の2列、行インデックスとcolsインデックスを返す関数:

def filter_indices_numpy(a,rows,cols,val): 
     sub=a[meshgrid(rows,cols,indexing='ij')] 
     r,c = (sub==val).nonzero() 
     return take(rows,r),take(cols,c) 

例:

a=randint(0,3,(5,5)) 

#array([[0, 1, 0, 2, 2], 
#  [0, 0, 2, 0, 0], 
#  [2, 1, 1, 0, 0], 
#  [1, 0, 0, 1, 2], 
#  [2, 1, 0, 0, 0]]) 

filter_indices_numpy(a,[1,2,3],[1,2,3],0) 
#(array([1, 1, 2, 3, 3]), array([1, 3, 3, 1, 2])) 

いくつかの説明:

meshgrid(rows,cols,indexing='ij')は、選択した行と列のインデックスです。 subはサブアレイです。 r,c = (sub==val).nonzero()は、サブアレイ内の値がvalであるインデックスです。 take(rows,r),take(cols,c)は、配列aのインデックスを変換します。それはおよそ25X高速ですa=randint(0,200,(1000,1000));rows=cols=arange(100)

In [4]: %timeit filter_indices(a,rows,cols,0) 
10 loops, best of 3: 23.1 ms per loop 

In [5]: %timeit filter_indices_numpy(a,rows,cols,0) 
1000 loops, best of 3: 933 µs per loop 

:用

テスト。

関連する問題