私が解決したい実際の問題は、N個の単位ベクトルのセットと別のM個のベクトルのセットが与えられた場合、各単位ベクトルについて、 M個のベクトルのすべてとの内積の絶対値の平均を計算することです。基本的に、これは 2 つの行列の外積を計算し、絶対値を間に挟んで合計および平均化します。
NとMが大きすぎない場合、これは難しくなく、続行するには多くの方法があります (以下を参照)。問題は、NとMが大きい場合、作成される一時ファイルが巨大になり、提供されたアプローチに実際的な制限が生じることです。この計算は、一時的に作成せずに実行できますか? 私が抱えている主な困難は、絶対値の存在によるものです。そのような計算を「スレッド化」するための一般的な手法はありますか?
例として、次のコードを考えてみましょう
N = 7
M = 5
# Create the unit vectors, just so we have some examples,
# this is not meant to be elegant
phi = np.random.rand(N)*2*np.pi
ctheta = np.random.rand(N)*2 - 1
stheta = np.sqrt(1-ctheta**2)
nhat = np.array([stheta*np.cos(phi), stheta*np.sin(phi), ctheta]).T
# Create the other vectors
m = np.random.rand(M,3)
# Calculate the quantity we desire, here using broadcasting.
S = np.average(np.abs(np.sum(nhat*m[:,np.newaxis,:], axis=-1)), axis=0)
これは素晴らしいことです。S は長さNの配列になり、目的の結果が含まれています。残念ながら、その過程で巨大な可能性のあるアレイをいくつか作成してしまいました。結果として
np.sum(nhat*m[:,np.newaxis,:], axis=-1)
はM X N配列です。もちろん、最終結果はサイズNのみです。NとMのサイズを増やし始めると、すぐにメモリ エラーが発生します。
上記のように、絶対値が必要ない場合は、次のように進めることができます。einsum()
T = np.einsum('ik,jk,j', nhat, m, np.ones(M)) / M
これは、非常に大きなNおよびMに対しても機能し、迅速に機能します。特定の問題については、を含める必要がありますabs()
が、より一般的な解決策 (おそらくより一般的な ufunc) も興味深いでしょう。