在Python中加速一对多的相关计算

6
我希望您能在Python中(假定使用numpy和/或scipy)计算一个向量与数组的每一行之间的Pearson相关系数。由于真实数据数组的大小和内存限制,无法使用标准相关矩阵计算函数。以下是我的天真实现:
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

任何加速此过程的想法都将不胜感激!

由于真实数据数组的大小和内存限制,可能会出现问题。请提供一个典型的数组大小和实际内存限制。 - Warren Weckesser
1个回答

8
模块 scipy.spatial.distance 实现了“相关距离”,它仅是相关系数的一减。您可以使用函数 cdist 计算一对多的距离,并通过从 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接