原始问题
我将大小为 n 的行 P 与大小为 n×m 的矩阵 O 的每一列相关联。我制作了以下代码:
import numpy as np
def ColumnWiseCorrcoef(O, P):
n = P.size
DO = O - (np.sum(O, 0) / np.double(n))
DP = P - (np.sum(P) / np.double(n))
return np.dot(DP, DO) / np.sqrt(np.sum(DO ** 2, 0) * np.sum(DP ** 2))
它比天真的方法更有效:
def ColumnWiseCorrcoefNaive(O, P):
return np.corrcoef(P,O.T)[0,1:O[0].size+1]
以下是我在英特尔内核上使用 numpy-1.7.1-MKL 获得的时间:
O = np.reshape(np.random.rand(100000), (1000,100))
P = np.random.rand(1000)
%timeit -n 1000 A = ColumnWiseCorrcoef(O, P)
1000 loops, best of 3: 787 us per loop
%timeit -n 1000 B = ColumnWiseCorrcoefNaive(O, P)
1000 loops, best of 3: 2.96 ms per loop
现在的问题是:你能为这个问题推荐一个更快的代码版本吗?挤出额外的 20% 会很棒。
2017 年 5 月更新
很长一段时间后,我回到了这个问题,重新运行并扩展了任务和测试。
使用 einsum,我将代码扩展到 P 不是行而是矩阵的情况。因此,任务是将 O 的所有列与 P 的所有列相关联。
对如何用科学计算常用的不同语言解决相同的问题感到好奇,我在 MATLAB、Julia 和 R 中实现了它(在其他人的帮助下)。MATLAB 和 Julia 是最快的,它们有专门的例程计算列相关性。R 也有专门的例程,但速度最慢。
在当前版本的 numpy(来自 Anaconda 的 1.12.1)中,einsum 仍然胜过我使用的专用函数。
所有脚本和时间都可以在https://github.com/ikizhvatov/efficient-columnwise-correlation获得。