協(xié)同過濾簡介
協(xié)同過濾是一種基于一組興趣相同的用戶或項目進行的推薦,它根據(jù)鄰居用戶(與目標用戶興趣相似的用戶)的偏好信息產(chǎn)生對目標用戶的推薦列表。
協(xié)同過濾算法主要分為:
- 基于用戶的協(xié)同過濾算法
- 基于物品的協(xié)同過濾算法
基于用戶的協(xié)同過濾算法
基于用戶的協(xié)同過濾算法是根據(jù)鄰居用戶的偏好信息產(chǎn)生對目標用戶的推薦。它基于這樣一個假設(shè):如果一些用戶對某一類項目的打分比較接近,則他們對其它類項目的打分也比較接近。協(xié)同過濾推薦系統(tǒng)采用統(tǒng)計計算方式搜索目標用戶的相似用戶,并根據(jù)相似用戶對項目的打分來預(yù)測目標用戶對指定項目的評分,最后選擇相似度較高的前若干個相似用戶的評分作為推薦結(jié)果,并反饋給用戶。
基于物品的協(xié)同過濾算法
基于物品的協(xié)同過濾是根據(jù)用戶對相似物品的評分數(shù)據(jù)預(yù)測目標項目的評分,它是建立在如下假設(shè)基礎(chǔ)上的:如果大部分用戶對某些物品的打分比較相近,則當前用戶對這些項的打分也會比較接近。ltem一based協(xié)同過濾算法主要對目標用戶所評價的一組項目進行研究,并計算這些項目與目標項目之間的相似性,然后從選擇前K個最相似度最大的項目輸出,這是區(qū)別于User-based協(xié)同過濾。
相似度計算
歐式距離
設(shè)向量,
皮爾遜相關(guān)系數(shù)
皮爾遜相關(guān)系數(shù)是一種度量兩個變量間相關(guān)程度的方法。它是一個介于 1 和 -1 之間的值,其中,1 表示變量完全正相關(guān), 0 表示無關(guān),-1 表示完全負相關(guān)。
<center>

</center>
按照高中數(shù)學水平來理解, 它很簡單, 可以看做將兩組數(shù)據(jù)首先做Z分數(shù)處理之后, 然后兩組數(shù)據(jù)的乘積和除以樣本數(shù)。
Z分數(shù)一般代表正態(tài)分布中, 數(shù)據(jù)偏離中心點的距離.等于變量減掉平均數(shù)再除以標準差.(就是高考的標準分類似的處理)
標準差則等于變量減掉平均數(shù)的平方和,再除以樣本數(shù),最后再開方.
皮爾遜相關(guān)的約束條件
從以上解釋, 也可以理解皮爾遜相關(guān)的約束條件:
- 兩個變量間有線性關(guān)系
- 變量是連續(xù)變量
- 變量均符合正態(tài)分布,且二元分布也符合正態(tài)分布
- 兩變量獨立
余弦相似度
余弦相似度計算的是兩個向量夾角的余弦值。若夾角為90度則相似度為0,若兩個向量的方向相同,則相似度為1。余弦相似度的取值范圍為[-1,1],因此我們也將它們歸一化到[0,1]。
兩種算法的比較
當物品的數(shù)據(jù)相對穩(wěn)定,例如電子商務(wù)類型的網(wǎng)站,計算相似度的計算量相對較小,同時不必頻繁更新,因此可以使用基于物品的協(xié)同過濾算法,但是對于新聞,博客等更新較快的系統(tǒng),物品的數(shù)量是海量的,計算更加復(fù)雜,因此我們需要使用基于用戶的協(xié)同過濾算法。

參考上表,行與行之間的比較是基于用戶的相似度,列與列之間的比較則是基于武平的相似度,到底使用哪一種相似度,這取決與用戶或者物品的數(shù)量。
推薦引擎的評價
使用交叉測試的方法,將某些已知的評分去電,然后對他們進行預(yù)測,然后計算預(yù)測值與真實值之間的差異,通常用于評價的指標為最小均方根誤差,首先計算均方誤差的平均值然后取其平方根。
實例:餐館菜肴推薦引擎
svdRec.py
#-*-coding=utf-8 -*-
from numpy import *
from numpy import linalg as la
def loadExData():
return [[1,1,1,0,0],
[2,2,2,0,0],
[1,1,1,0,0],
[5,5,5,0,0],
[1,1,0,2,2],
[0,0,0,3,3],
[0,0,0,1,1]]
#計算歐幾里得相似度
def eulidSim(inA,inB):
return 1.0/(1.0+la.norm(inA-inB))
#計算皮爾遜相似度
def pearsSim(inA,inB):
if len(inA)<3:
return 1.0
return 0.5+0.5*corrcoef(inA,inB,rowvar=0)[0][1]
#計算余弦相似度
def cosSim(inA,inB):
num= float(inA.T*inB)
denom = la.norm(inA)*la.norm(inB)
return 0.5+0.5*(num/denom)
#計算在給定相似度計算方法下,用戶對物品的估計評分值
def standEst(dataMat,user,simMeas,item):
n = shape(dataMat)[1]
simTotal = 0.0
ratSimTotal =0.0
for j in range(n):
userRating = dataMat[user,j]
if userRating == 0:
continue;
overlap = nonzero(logical_and(dataMat[:,item].A>0,dataMat[:,j].A>0))[0]
if len(overlap) == 0:
similarity=0
else:
similarity = simMeas(dataMat[overlap,item],dataMat[overlap,j])
simTotal += similarity
ratSimTotal += similarity*userRating
if simTotal == 0:
return 0.0
else:
return ratSimTotal/simTotal
def recommend(dataMat,user,N=3,simMeas=cosSim,estMethod=standEst):
unratedItems = nonzero(dataMat[user,:].A==0)[1] #find the item which the user not ranked
if len(unratedItems) == 0:
return "you rated everything"
itemScore = []
for item in unratedItems:
estimatedScore = estMethod(dataMat,user,simMeas,item)
itemScore.append((item,estimatedScore))
return sorted(itemScore,key=lambda jj : jj[1] ,reverse=True)[:N]
Restaurant_recommendation_system.py
#-*-coding=utf-8 -*-
from numpy import *
from matplotlib import *
import svdRec
mymat = mat(svdRec.loadExData())
"""
testing Sim
print svdRec.eulidSim(mymat[:,0],mymat[:,4])
print svdRec.eulidSim(mymat[:,0],mymat[:,0])
print svdRec.cosSim(mymat[:,0],mymat[:,0])
print svdRec.cosSim(mymat[:,0],mymat[:,4])
print svdRec.pearsSim(mymat[:,0],mymat[:,4])
print svdRec.pearsSim(mymat[:,0],mymat[:,0])
"""
"""
testing predict
"""
print mymat
mymat[0,1]=mymat[0,0]=mymat[1,0]=mymat[2,0]=4
mymat[3,3]=2
print mymat
print svdRec.recommend(mymat,2)