一啸臀、基本原理
協(xié)同過濾中另一種經(jīng)典的方法就是基于用戶的協(xié)同過濾方法贰拿,其思想是先計算用戶u與其它用戶的相似度规哪,然后選取和u最相似的幾個用戶求豫,把他們買過的產(chǎn)品推薦給u。主要也可分為兩步:(1)建立物品-用戶倒排表诉稍,如圖2的上半部分所示蝠嘉;(2)建立用戶相似度矩陣,如圖2的下半部分所示杯巨。
基于用戶的協(xié)同過濾算法的相似度的計算方法與基于物品的計算方式相同蚤告。對于與用戶u相似度接近的K個用戶,遍歷他們有過正反饋的物品服爷,計算出用戶u對每一個物品的感興趣程度:
其中杜恰,包含和用戶u興趣最接近的K個用戶,是對物品i有過行為的用戶集合仍源,是用戶u和用戶v的相似度心褐,表示用戶v對i的興趣,然后根據(jù)感興趣程度由高到低確定N個推薦給用戶u的物品笼踩。
基于用戶協(xié)同和基于物品協(xié)同的區(qū)別
(1)從推薦場景的角度考慮
ItemCF適用于購物網(wǎng)站逗爹,其中用戶的數(shù)量遠(yuǎn)多于物品的數(shù)量,物品數(shù)據(jù)相對穩(wěn)定嚎于,相似度計算量較小掘而,且不必頻繁更新挟冠;UserCF更適用于新聞、博客等社交網(wǎng)絡(luò)袍睡,其內(nèi)容更新非常頻繁知染,即UserCF更注重社會化,而ItemCF更注重個性化斑胜。
(2)從多樣性的角度考慮
即覆蓋率持舆,指推薦系統(tǒng)能否給用于提供多種選擇。由于UserCF更傾向推薦熱門物品伪窖,ItemCF的多樣性遠(yuǎn)好于UserCF,容易發(fā)現(xiàn)并推薦長尾里的物品居兆。
(3)從冷啟動的角度考慮
UserCF中在新用戶對很少物品產(chǎn)生行為后覆山,不能立即對他進(jìn)行個性化推薦,即暫時無法找到興趣相投的用戶泥栖。ItemCF中新用戶只要對一個物品產(chǎn)生行為簇宽,就可以給他推薦和該物品相關(guān)的其它物品。
二吧享,算法實踐
采用GroupLens提供的MovieLens數(shù)據(jù)集魏割,http://www.grouplens.org/node/73。本章使用中等大小的數(shù)據(jù)集钢颂,包含6000多用戶對4000多部電影的100萬條評分钞它。該數(shù)據(jù)集是一個評分?jǐn)?shù)據(jù)集,用戶可以給電影評1-5分5個不同的等級殊鞭。本文著重研究隱反饋數(shù)據(jù)集中TopN推薦問題遭垛,因此忽略了數(shù)據(jù)集中的評分記錄。
1操灿、包的加載與變量定義
該部分定義了所需要的主要變量锯仪,集合采用字典形式的數(shù)據(jù)結(jié)構(gòu)。
import random
import math
from operator import itemgetter
class UserBasedCF():
def __init__(self):
self.n_sim_user = 20
self.n_rec_user = 10
self.train = {}
self.test = {}
self.user_sim_matrix = {}
self.movie_count = 0
2趾盐、數(shù)據(jù)加載
讀取原始CSV文件庶喜,并劃分訓(xùn)練集和測試集,訓(xùn)練集占比87.5%救鲤,同時建立訓(xùn)練集和測試集的用戶字典久窟,記錄每個用戶對電影評分的字典。
def get_dataset(self,filename,pivot=0.875):
train_len,test_len = 0,0
random.seed()
for line in self.load_file(filename):
user,movie,rating,timestamp = line.split(',')
if random.random()<pivot:
self.train.setdefault(user,{})
self.train[user][movie] = rating
train_len += 1
else:
self.test.setdefault(user,{})
self.test[user][movie] = rating
test_len += 1
print('Load dataset success!')
print('train set:%s, test set:%s'% (train_len,test_len))
def load_file(self,filename):
with open(filename,'r') as f:
for i,line in enumerate(f):
if i==0:
continue
yield line.strip('\r\n')
3蜒简、計算相似度矩陣
第一步建立電影-用戶倒排表瘸羡;第二步計算矩陣C,C[i][j]表示同時喜歡電影i和j的用戶數(shù)搓茬,并考慮對活躍用戶的懲罰犹赖;第三步計算用戶間的相似性矩陣队他。
def calc_user_sim(self):
movie_user = {}
for user,movies in self.train.items():
for movie in movies:
if movie not in movie_user:
movie_user[movie] = set()
movie_user[movie].add(user)
print('Build movie-user table success!')
self.movie_count = len(movie_user)
for movies,users in movie_user.items():
for u in users:
for v in users:
if u == v:
continue
self.user_sim_matrix.setdefault(u,{})
self.user_sim_matrix[u].setdefault(v,0)
self.user_sim_matrix[u][v] += 1/math.log(1+len(users))
print('Build user co-rated movies matrix success!')
for u,related_users in self.user_sim_matrix.items():
for v,count in related_users.items():
self.user_sim_matrix[u][v] = count / math.sqrt(len(self.train[u])*len(self.train[v]))
print('Calculate user similarity matrix success!')
4、對用戶進(jìn)行推薦
針對目標(biāo)用戶U峻村,找到K部相似的電影麸折,并推薦其N部電影,如果用戶已經(jīng)看過該電影則不推薦粘昨。
def recommend(self,user):
K = self.n_sim_user
N = self.n_rec_user
rank = {}
watched_movies = self.train[user]
for v,wuv in sorted(self.user_sim_matrix[user].items(),key=itemgetter(1),reverse=True)[:K]:
for movie,rvi in self.train[v].items():
if movie in watched_movies:
continue
rank.setdefault(movie,0)
rank[movie] += float(wuv)*float(rvi)
return sorted(rank.items(),key=itemgetter(1),reverse=True)[0:N]
5垢啼、評估指標(biāo)的計算
產(chǎn)生推薦并通過準(zhǔn)確率、召回率和覆蓋率進(jìn)行評估张肾。
def evaluate(self):
print('Evaluateing starting ...')
N = self.n_rec_movie
hit,rec_count,test_count = 0,0,0
all_rec_movies = set()
for i,user in enumerate(self.train):
test_movies = self.test.get(user,{})
rec_movies = self.recommend(user)
for movie,w in rec_movies:
if movie in test_movies:
hit += 1
all_rec_movies.add(movie)
rec_count += N
test_count += len(test_movies)
precision = hit/(1.0*rec_count)
recall = hit/(1.0*test_count)
coverage = len(all_rec_movies)/(1.0*self.movie_count)
print('precision=%.4f, recall=%.4f, coverage=%.4f'%(precision,recall,coverage))
結(jié)果如下所示芭析,由于數(shù)據(jù)量較大,計算速度較慢吞瞪,耐心等待即可馁启。
Load dataset success!
train set:875020, test set:125188
Build movie-user table success!
Build user co-rated movies matrix success!
Calculate user similarity matrix success!
Evaluateing starting ...
precision=0.2322, recall=0.1120, coverage=0.2931
參考資料
[1]. https://blog.csdn.net/m0_37917271/article/details/82498308
[2]. 推薦系統(tǒng)與深度學(xué)習(xí). 黃昕等. 清華大學(xué)出版社. 2019.
[3]. 推薦系統(tǒng)算法實踐. 黃美靈. 電子工業(yè)出版社. 2019.
[4]. 推薦系統(tǒng)算法. 項亮. 人民郵電出版社. 2012.
[5]. 美團機器學(xué)習(xí)實踐. 美團算法團隊. 人民郵電出版社. 2018.
新家孟城口,古木余衰柳芍秆。來者復(fù)為誰惯疙,空悲昔人有⊙叮——王維《輞川集·孟城坳》