2015-11-13 42 views
2

對於類中的推薦系統項目,我目前正在嘗試構建和存儲具有大約7000個用戶(行)和4000個電影(列)的數據集的基於項目的相似度矩陣。所以我有一個數據透視表,其中UserIDs作爲索引,MovieIDs作爲列和評級作爲值。你可以想象有很多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方法,但無法獲取任何地方。

任何想法如何改善(可能很多)?

回答

2

你肯定會想要使用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 

而且,你的結果將是一個密集矩陣與約16萬個條目,所以它不會是一個快速計算。您可能會考慮是否真的需要存儲所有這些值,或者您是否可以使用算法(例如)只計算最近鄰居的相關性。

+0

你說得對,我現在覺得很愚蠢。這花了大約5秒鐘,從我能看到的結果幾乎相同。感謝您的幫助! – kbk

1

會不會np.corrcoef(data)給你相同的相關矩陣?

如果不是,那麼只需計算對稱結果矩陣的一半,並且當i等於j時根本不打電話pearsonr(),您應該能夠大致加倍性能。

+0

是的你是對的,謝謝。但是,對於基於電影的相似性,我需要'np.corrcoef(data.T)'。在閱讀你的secomd評論之後,我還發現,我可以將第二個循環的範圍設置爲從i開始。有時候確實不那麼難。謝謝您的回覆! – kbk