高效计算和存储相似度矩阵

Efficiently calculate and store similarity matrix

对于 class 中的推荐系统项目,我目前正在尝试为具有大约 7000 个用户(行)和 4000 部电影(列)的数据集构建和存储基于项目的相似性矩阵。所以我有一个枢轴 table,其中 UserID 作为索引,MovieID 作为列,评级作为值。正如你想象的那样,有很多 0 评分。

目前我正在使用 scipy 包中的 pearsonr 函数。我想,为了存储所有距离,我必须计算所有列之间的皮尔逊系数,并将它们存储在对称的电影-电影矩阵中。到目前为止我的代码(如你所见,我是 Python/coding 的新手):

import pandas as pd
import numpy as np
from scipy.stats import pearsonr

pd.read_csv('data.csv')
data = data.pivot(index = 'UserID', columns = 'MovieID', values = "Rating")

similarity_data = pd.DataFrame(index=data.columns, columns=data.columns)

for i in range(0,len(data.columns)):
    for j in range(0,len(data.columns)):
        similarity_data.iloc[i,j] =  pearsonr(data.iloc[:,i],data.iloc[:,j])[0]

好吧,正如您想象的那样,这需要很长时间,我很想知道如何更有效地完成这项工作。我的第一个想法是利用矩阵的对称性。但我无法弄清楚如何。

我的想法是这样的:

for i in range(0,len(data.columns)):
    for j in range(0,len(data.columns)):
        similarity_data.iloc[i,j] =  pearsonr(data.iloc[:,i],data.iloc[:,j+i])[0]
        similarity_data[j,i] = similarity_data.iloc[i,j]

然而,即使我能让它工作,我担心这里的问题是两个 for 循环。我试图以某种方式使用地图或 lambda 方法,但无处可去。

知道如何改进这个(可能有很多)吗?

不会np.corrcoef(data)给你相同的相关矩阵吗?

如果不是,当 i 等于 [=13= 时,您应该能够通过仅计算对称结果矩阵的一半而不调用 pearsonr() 来大致将性能提高一倍].

您肯定会想要使用 np.corrcoef,这比 scipy.stats.pearsonr 上的简单循环快大约 1000 倍。例如:

from scipy.stats import pearsonr
import numpy as np
import pandas as pd

# make some small data
df = pd.DataFrame(np.random.rand(100, 40))

C1 = np.array([[pearsonr(df[i], df[j])[0] for i in df] for j in df])
C2 = np.corrcoef(df.values.T)
np.allclose(C1, C2)
# True

时间如下:

%timeit np.array([[pearsonr(df[i], df[j])[0] for i in df] for j in df])
10 loops, best of 3: 154 ms per loop

%timeit np.corrcoef(df.values.T)
10000 loops, best of 3: 116 µs per loop

不过,您的结果将是一个包含大约 1600 万个条目的密集矩阵,因此计算速度不会很快。您可能会考虑是否真的需要存储所有这些值,或者是否可以使用一种算法(例如)只计算最近邻的相关性。