什麼是協同過濾:
協同過濾(Collaborative Filtering recommendation)簡單來說是利用某興趣相投、擁有共同經驗之群體的喜好來推薦使用者感興趣的資訊,個人通過合作的機制給予資訊相當程度的回應(如評分)并記錄下來以達到過濾的目的進而幫助别人篩選資訊,回應不一定局限于特别感興趣的,特别不感興趣資訊的紀錄也相當重要。
協同過濾是應用較廣的智能推薦算法,電子商務系統中可以通過使用者的曆史使用資料向使用者推薦使用者潛在喜愛的商品。
協同過濾分為基于使用者的協同過濾(User-Based)和基于物品的協同過濾(Item-Based)。
1.基于使用者的協同過濾(UBCF):
基于使用者的協同過濾的基本思想相當簡單,基于使用者對物品的偏好找到相鄰鄰居使用者,然後将鄰居使用者喜歡的推薦給目前使用者,為具有相同或相似的價值觀、思想觀、知識水準和興趣偏好的使用者,其對資訊的需求也是相似的。
計算上,就是将一個使用者對所有物品的偏好作為一個向量來計算使用者之間的相似度,找到 K 鄰居後,根據鄰居的相似度權重以及他們對物品的偏好,預測目前使用者沒有偏好的未涉及物品,計算得到一個排序的物品清單作為推薦。
舉例:
對于使用者 A,根據使用者的曆史偏好,這裡隻計算得到一個鄰居 - 使用者 C,然後将使用者 C 喜歡的物品 D 推薦給使用者 A。
2.基于物品的協同過濾(IBCF):
基于物品的協同過濾的原理和基于使用者的協同過濾類似,隻是在計算鄰居時采用物品本身,而且是從使用者的角度,即基于使用者對物品的偏好找到相似的物品,然後根據使用者的曆史偏好,推薦相似的物品給他。
從計算的角度看,就是将所有使用者對某個物品的偏好作為一個向量來計算物品之間的相似度,得到物品的相似物品後,根據使用者曆史的偏好預測目前使用者還沒有表示偏好的物品,計算得到一個排序的物品清單作為推薦。
例子:
對于物品 A,根據所有使用者的曆史偏好,喜歡物品 A 的使用者都喜歡物品 C,得出物品 A 和物品 C 比較相似,而使用者 C 喜歡物品 A,那麼可以推斷出使用者 C 可能也喜歡物品 C。
計算相似度
在建構協同過濾推薦模型時,一個重要的環節就是如何選擇合适的相似度計算方法。建立相似度矩陣,計算相似度普遍有這幾種方法:皮爾遜相關系數(Pearson Correlation Coefficient)、基于歐幾裡德距離的相似度、餘弦相似度(Cosine-based Similarity)、傑卡德系數(Jaccard similarity coefficient) 。
a 皮爾遜相關系數
皮爾遜相關系數一般用于計算兩個定距變量間聯系的緊密程度,它的取值在 [-1,+1] 之間。用數學公式表示,皮爾森相關系數等亍兩個變量的協方差除于兩個變量的标準差。計算公式如下所示:
由于皮爾遜相關系數描述的是兩組資料變化移動的趨勢,是以在基于使用者的協同過濾系統中,經常使用。描述使用者購買或評分變化的趨勢,若趨勢相近則皮爾遜系數趨近于1,也就是我們認為相似的使用者。
設(X1,Y1),…,(Xn,Yn)為從樣本總體F(x,y)中抽取的樣本,則
相關系數和協方差的關系:
皮爾遜相關系數
其中,X,Y不是互相獨立,即它們之間存在着一定的關系。
協方差和方差的關系:
b 基于歐幾裡德距離的相似度
歐幾裡德距離計算相似度是所有相似度計算裡面最簡單、最易了解的方法。計算出來的歐幾裡德距離是一個大于0的數,為了使其更能展現使用者之間的相似度,可以把它規約到(0, 1]之間,最終得到如下計算公式:
隻要至少有一個共同評分項,就能用歐幾裡德距離計算相似度;如果沒有共同評分項,那麼歐幾裡德距離也就失去了作用。
c 餘弦相似度
餘弦相似度用向量空間中兩個向量夾角的餘弦值作為衡量兩個個體間差異的大小。餘弦相似度更加注重兩個向量在方向上的差異,而非距離戒長度上。計算公式如下所示:餘弦相似度用向量空間中兩個向量夾角的餘弦值作為衡量兩個個體間差異的大小。餘弦相似度更加注重兩個向量在方向上的差異,而非距離戒長度上。計算公式如下所示:
從圖上可以看出距離度量衡量的是空間各點間的絕對距離,跟各個點所在的位置坐标(即個體特征次元的數值)直接相關。如果保持X點的位置不變,Y點朝原方向進離坐标軸原點,那麼這個時候餘弦相似度是保持不變的,因為夾角不變,而X、Y兩點的距離顯然在發生改變,這就是歐氏距離和餘弦相似度的不同之處。
d 傑卡德系數
Jaccard相似系數用于比較有限樣本集之間的相似性于差異性。Jaccard系數越大,樣本相似度越大。
主要用于比較文本相似度。
案例:電影推薦
讀取資料,部分電影的評分如下:
import json
content = None
with open(‘movie_score.txt’, ‘r’, encoding=‘utf-8’) as file:
content = file.read()
content = content.replace("’", ‘"’)
data = json.loads(content)
#轉換為資料框
data = pd.DataFrame(data)
#将資料中的空值nan變為0
data = data.fillna(0)
求不同電影的相似度:
mcors = np.corrcoef(mdata, rowvar=0)
mcors = 0.5+mcors*0.5
mcors = pd.DataFrame(mcors, columns=mdata.columns, index=mdata.columns)
計算每個使用者每個電影的評分(沒有使用者評分的電影用相似度估算評分):
def cal_score(matrix,mcors,item,user):
totscore = 0
totsims = 0
score = 0
if pd.isnull(matrix[item][user]) or matrix[item][user]==0:
for mitem in matrix.columns:
if matrix[mitem][user]==0:
continue
else:
totscore += matrix[mitem][user]*mcors[item][mitem]
totsims += mcors[item][mitem]
score = totscore/totsims
else:
score = matrix[item][user]
return score
編寫一個函數輸入使用者名檢視推薦的電影與推薦系數:
score_matrix = cal_matscore(mdata,mcors)
for i in range(10):
user = input(str(i)+’.’+‘please input the name of user:’)
print(recommend(mdata,score_matrix,user,2))
user = ‘Toby’ # 檢驗
while True:
user = input(‘please input the name of user:’)
if user == ‘Stop’:
print(‘Stop recommend!’)
break
else:
print(recommend(mdata,score_matrix,user,2))
運作結果:
輸入使用者名傳回推薦的電影,我們檢視Toby的推薦
可以看到首先推薦電影 Lady in the water 推薦系數3.22