2016-10-19 11 views
2

長さn(= 300,000)の系列Xを持っています。 (40 =)Wの窓長を用いて、私は実装する必要があります定数付きPythonベクトル化

ミュー(I)= X(I)-X(IW)

S(i)を= IにIW和{K =ここでループを防ぐ方法があるのだろうかと思っていました。 mu(i)が第2の式で一定であるという事実は、ベクトル化において複雑さを引き起こす。私は今のところ、以下のなかった:

x1=x.shift(1) 
xw=x.shift(w) 
mu= x-xw 
dx=(x-x1-mu)**2 # wrong because mu wouldn't be constant for each i 
s=pd.rolling_sum(dx,w) 

上記のコードは動作します(と働いていた)の設定ループ内ではなく、時間がかかりすぎるので、ベクトル化または他の速度向上方法に関する任意のヘルプは参考になります。私はこれをmathjaxフォーマットでcrossvalidatedに投稿しましたが、ここではうまくいかないようです。

https://stats.stackexchange.com/questions/241050/python-vectorization-with-a-constant

また、単に明確にするために、私はもともと、ただ一つのものをダブルループを使用していませんでした。

 for i in np.arange(w, len(X)): 
      x=X.ix[i-w:i,0] # clip a series of size w 
      x1=x.shift(1) 
      mu.ix[i]= x.ix[-1]-x.ix[0] 
      temp= (x-x1-mu.ix[i])**2 # returns a series of size w but now mu is constant 
      s.ix[i]= temp.sum() 
+1

あなたは、2D ARRで何かができる - np.einsumはそうのように、s[i]を計算するために、ここで使用することができ必要に応じて軸を指定します。パンダの「rolling_sum」がどのように振る舞うかはわかりませんが、2D配列のnumpyだけで方程式のすべての作業を行うことができるようです。 – Evert

+1

まだ半分眠っているので間違っているかもしれません。私はあなたが3つの要因の追加として広場を拡大することができると思います。最初のものは畳み込み(二乗)です.np.convolveを使って非常に素早く行うことができます。もう一つはmu ** 2です。これはすでに持っています.3番目のものは乗算されたbu muの上の畳み込みです。 – Jblasco

+1

いずれにしても、配列の乗算/合計でコストのかかるループを避けるための最初のことは、畳み込みによるものです。 – Jblasco

答えて

1

アプローチ#1:一つのベクトル化のアプローチはbroadcastingを使用されるだろう -

N = X.shape[0] 
a = np.arange(N) 
k2D = a[:,None] - np.arange(w+1)[::-1] 
mu1D = X - X[a-w] 
out = ((X[k2D] - X[k2D-1] - mu1D[:,None])**2).sum(-1) 

最後のステップをさらに最適化すると、01で2乗和を得ることができます-

subs = X[k2D] - X[k2D-1] - mu1D[:,None] 
out = np.einsum('ij,ij->i',subs,subs) 

さらなる改善がX[k2D]X[k2D-1]を取得するNumPy stridesの使用で可能です。


アプローチ#2:非常に大きなアレイを使用する場合、我々はそうように、代わりに元のコードで使用される2つのループの1つのループを使用することができ、メモリを節約する - ここでも

N = X.shape[0] 
s = np.zeros((N)) 
k_idx = np.arange(-w,1) 
for i in range(N): 
    mu = X[i]-X[i-w] 
    s[i] = ((X[k_idx]-X[k_idx-1] - mu)**2).sum() 
    k_idx += 1 

、あなたは以上のループに2つの変数を持っているように見えるので、

subs = X[k_idx]-X[k_idx-1] - mu 
s[i] = np.einsum('i,i->',subs,subs) 
+0

ありがとう、私はアプローチ#2を元々使っていましたが、ループは非常に長くかかります。 2Dアレイを使用したアプローチ#1は有望ですが、私はそれをよりよく理解するために作業する必要があります。私はそれを盲目的に適用し、 'out = ...'行の 'KeyError( '%objarr [mask]にインデックス'%objarr [mask])を入れないでください – dayum

+1

@dayum NumPy配列として' X'を仮定しました。私たちは前向きにその変換を行う必要があると思います。あなたはそれをやっていますか? – Divakar

+0

OKだから、形状も(N、w + 1)の2次元配列です。私の場合、「s」は1Dの形状の配列です(N) – dayum

関連する問題