3

对于课堂上的推荐系统项目,我目前正在尝试为包含大约 7000 个用户(行)和 4000 个电影(列)的数据集构建和存储基于项目的相似度矩阵。所以我有一个数据透视表,其中 UserID 作为索引,MovieID 作为列,评级作为值。可以想象,有很多 0 评级。

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

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 方法,但无处可去。

知道如何改进这一点(可能很多)?

4

2 回答 2

3

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

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 万个条目的密集矩阵,因此计算速度不会很快。您可能会考虑是否真的需要存储所有这些值,或者是否可以使用(例如)仅计算最近邻居相关性的算法。

于 2015-11-14T00:25:16.063 回答
1

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

如果没有,您应该能够通过仅计算对称结果矩阵的一半并且在等于pearsonr()时根本不调用来将性能大致提高一倍。ij

于 2015-11-13T23:54:58.120 回答