協(xié)同過濾簡介
協(xié)同過濾是一種基于一組興趣相同的用戶或項(xiàng)目進(jìn)行的推薦,它根據(jù)鄰居用戶(與目標(biāo)用戶興趣相似的用戶)的偏好信息產(chǎn)生對目標(biāo)用戶的推薦列表玄渗。
協(xié)同過濾算法主要分為:
- 基于用戶的協(xié)同過濾算法
- 基于物品的協(xié)同過濾算法
基于用戶的協(xié)同過濾算法
基于用戶的協(xié)同過濾算法是根據(jù)鄰居用戶的偏好信息產(chǎn)生對目標(biāo)用戶的推薦座菠。它基于這樣一個假設(shè):如果一些用戶對某一類項(xiàng)目的打分比較接近,則他們對其它類項(xiàng)目的打分也比較接近藤树。協(xié)同過濾推薦系統(tǒng)采用統(tǒng)計(jì)計(jì)算方式搜索目標(biāo)用戶的相似用戶浴滴,并根據(jù)相似用戶對項(xiàng)目的打分來預(yù)測目標(biāo)用戶對指定項(xiàng)目的評分,最后選擇相似度較高的前若干個相似用戶的評分作為推薦結(jié)果岁钓,并反饋給用戶巡莹。
基于物品的協(xié)同過濾算法
基于物品的協(xié)同過濾是根據(jù)用戶對相似物品的評分?jǐn)?shù)據(jù)預(yù)測目標(biāo)項(xiàng)目的評分,它是建立在如下假設(shè)基礎(chǔ)上的:如果大部分用戶對某些物品的打分比較相近甜紫,則當(dāng)前用戶對這些項(xiàng)的打分也會比較接近。ltem一based協(xié)同過濾算法主要對目標(biāo)用戶所評價的一組項(xiàng)目進(jìn)行研究骂远,并計(jì)算這些項(xiàng)目與目標(biāo)項(xiàng)目之間的相似性囚霸,然后從選擇前K個最相似度最大的項(xiàng)目輸出,這是區(qū)別于User-based協(xié)同過濾激才。
相似度計(jì)算
歐式距離
設(shè)向量,
皮爾遜相關(guān)系數(shù)
皮爾遜相關(guān)系數(shù)是一種度量兩個變量間相關(guān)程度的方法拓型。它是一個介于 1 和 -1 之間的值,其中瘸恼,1 表示變量完全正相關(guān)劣挫, 0 表示無關(guān),-1 表示完全負(fù)相關(guān)东帅。
<center>
</center>
按照高中數(shù)學(xué)水平來理解, 它很簡單, 可以看做將兩組數(shù)據(jù)首先做Z分?jǐn)?shù)處理之后, 然后兩組數(shù)據(jù)的乘積和除以樣本數(shù)压固。
Z分?jǐn)?shù)一般代表正態(tài)分布中, 數(shù)據(jù)偏離中心點(diǎn)的距離.等于變量減掉平均數(shù)再除以標(biāo)準(zhǔn)差.(就是高考的標(biāo)準(zhǔn)分類似的處理)
標(biāo)準(zhǔn)差則等于變量減掉平均數(shù)的平方和,再除以樣本數(shù),最后再開方.
皮爾遜相關(guān)的約束條件
從以上解釋, 也可以理解皮爾遜相關(guān)的約束條件:
- 兩個變量間有線性關(guān)系
- 變量是連續(xù)變量
- 變量均符合正態(tài)分布,且二元分布也符合正態(tài)分布
- 兩變量獨(dú)立
余弦相似度
余弦相似度計(jì)算的是兩個向量夾角的余弦值。若夾角為90度則相似度為0靠闭,若兩個向量的方向相同帐我,則相似度為1。余弦相似度的取值范圍為[-1,1],因此我們也將它們歸一化到[0,1]愧膀。
兩種算法的比較
當(dāng)物品的數(shù)據(jù)相對穩(wěn)定拦键,例如電子商務(wù)類型的網(wǎng)站,計(jì)算相似度的計(jì)算量相對較小檩淋,同時不必頻繁更新,因此可以使用基于物品的協(xié)同過濾算法,但是對于新聞忘嫉,博客等更新較快的系統(tǒng),物品的數(shù)量是海量的,計(jì)算更加復(fù)雜氧敢,因此我們需要使用基于用戶的協(xié)同過濾算法。
參考上表莲镣,行與行之間的比較是基于用戶的相似度福稳,列與列之間的比較則是基于武平的相似度,到底使用哪一種相似度瑞侮,這取決與用戶或者物品的數(shù)量的圆。
推薦引擎的評價
使用交叉測試的方法,將某些已知的評分去電半火,然后對他們進(jìn)行預(yù)測越妈,然后計(jì)算預(yù)測值與真實(shí)值之間的差異,通常用于評價的指標(biāo)為最小均方根誤差钮糖,首先計(jì)算均方誤差的平均值然后取其平方根梅掠。
實(shí)例:餐館菜肴推薦引擎
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]]
#計(jì)算歐幾里得相似度
def eulidSim(inA,inB):
return 1.0/(1.0+la.norm(inA-inB))
#計(jì)算皮爾遜相似度
def pearsSim(inA,inB):
if len(inA)<3:
return 1.0
return 0.5+0.5*corrcoef(inA,inB,rowvar=0)[0][1]
#計(jì)算余弦相似度
def cosSim(inA,inB):
num= float(inA.T*inB)
denom = la.norm(inA)*la.norm(inB)
return 0.5+0.5*(num/denom)
#計(jì)算在給定相似度計(jì)算方法下,用戶對物品的估計(jì)評分值
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)