2016-06-01 89 views
2

ベクトルと配列の各行(Pythonのnumpyとscipyを想定しています)との相関係数を計算したいと思います。実際のデータ配列とメモリの制約のため、標準的な相関行列計算関数の使用は不可能です。私の素朴な実装は次のとおりです。Pythonの1対多の相関計算の高速化

import numpy as np 
import scipy.stats as sps 

np.random.seed(0) 

def correlateOneWithMany(one, many): 
    """Return Pearson's correlation coef of 'one' with each row of 'many'.""" 
    pr_arr = np.zeros((many.shape[0], 2), dtype=np.float64) 
    pr_arr[:] = np.nan 
    for row_num in np.arange(many.shape[0]): 
     pr_arr[row_num, :] = sps.pearsonr(one, many[row_num, :]) 
    return pr_arr 

obs, varz = 10 ** 3, 500 
X = np.random.uniform(size=(obs, varz)) 

pr = correlateOneWithMany(X[0, :], X) 

%timeit correlateOneWithMany(X[0, :], X) 
# 10 loops, best of 3: 38.9 ms per loop 

これを加速することについてのご意見は大いにありがたく思っています。

+0

*「...により、実際のデータ配列およびメモリの制約の大きさに」*配列と実際のメモリ制約の典型的なサイズを教えてください。 –

答えて

1

モジュールscipy.spatial.distanceは、「相関距離」を実装しています。これは、単純に相関係数をマイナスしたものです。 cdistを使用して1対多の距離を計算し、1から結果を減算して相関係数を得ることができます。

cdistを使用して相関係数の計算を含むスクリプトを修正しました。

import numpy as np 
import scipy.stats as sps 
from scipy.spatial.distance import cdist 

np.random.seed(0) 

def correlateOneWithMany(one, many): 
    """Return Pearson's correlation coef of 'one' with each row of 'many'.""" 
    pr_arr = np.zeros((many.shape[0], 2), dtype=np.float64) 
    pr_arr[:] = np.nan 
    for row_num in np.arange(many.shape[0]): 
     pr_arr[row_num, :] = sps.pearsonr(one, many[row_num, :]) 
    return pr_arr 

obs, varz = 10 ** 3, 500 
X = np.random.uniform(size=(obs, varz)) 

pr = correlateOneWithMany(X[0, :], X) 

c = 1 - cdist(X[0:1, :], X, metric='correlation')[0] 

print(np.allclose(c, pr[:, 0])) 

はタイミング:

In [133]: %timeit correlateOneWithMany(X[0, :], X) 
10 loops, best of 3: 37.7 ms per loop 

In [134]: %timeit 1 - cdist(X[0:1, :], X, metric='correlation')[0] 
1000 loops, best of 3: 1.11 ms per loop 
+0

うん、それはうまくいく - 素敵な10倍の改善! – dewarrn1

関連する問題