2017-11-10 17 views
3

配列aの形状(M1, M2, N)と別の配列bの形状(N,)の間の共分散を得る必要があります。異なる形状の配列のための速い僅かな共分散

私が現在やっていることはforブロック使用である:

import numpy as np 

M1, M2, N = 23, 50, 117 
a = np.random.uniform(-2., 2., (M1, M2, N)) 
b = np.random.uniform(-1., 1., N) 

c = [] 
for i in range(M1): 
    for j in range(M2): 
     c.append(np.cov(a[i][j], b)[0, 1]) 

を、それは大きな(M1, M2)のために少し遅くなります。これをスピードアップする方法はありますか?

答えて

2

いつもcovは手で計算できます。ここにはdoteinsumをそれぞれ使用する2つの提案があります。

import numpy as np 

M1, M2, N = 23, 50, 117 
a = np.random.uniform(-2., 2., (M1, M2, N)) 
b = np.random.uniform(-1., 1., N) 

c = [] 
for i in range(M1): 
    for j in range(M2): 
     c.append(np.cov(a[i][j], b)[0, 1]) 

c1 = np.reshape(c, (M1, M2)) 

ac = a - a.mean(axis=-1, keepdims=True) 
bc = (b - b.mean())/(N-1) 

c2 = np.dot(ac, bc) 
c3 = np.einsum('ijk,k->ij', ac, bc) 
print(np.allclose(c1, c2)) 
print(np.allclose(c1, c3)) 

プリント

True 
True 
+1

あなたに戻って見て良いです!これらと一緒にしばらくの間、つまらないでしたが、通過することはできませんでした。 'テンソル'はテンソルの 'ドット 'よりも優れています:' np.tensordot(ac、bc、axes =((-1、-1))) '。 – Divakar

+0

3つのオプション( 'np.einsum'、' np.dot'、 'np.tensordot')は' for'ブロックよりもずっと高速です。明らかにそれらはすべて同じように高速ですので、私は解釈するのが簡単です(私にとっては) 'np.dot'と一緒に行きます。あなたがた両方に感謝します! – Gabriel

+0

@Divakarありがとうございました。私はあなたが今までと同じくらい多分であることを見ることができます。 –

関連する問題