主要学习内容
1 用户行为数据简介
2 用户行为分析
3 实验设计和算法评测
4 基于领域的算法
(1)基于用户的协同过滤算法
(2)基于物品的协同过滤算法
5 隐语义模型
6 基于图的模型
(一)用户行为数据简介
用户行为数据在网站上最简单的存在形式为日志。很多互联网业务会把多种原始日志按照用户行为汇总成会话日志,其中会话表示一次用户行为和对应的服务。如电子商务网站记录的用户行为包括网页浏览、购买、点击、评分和评论等。
用户行为在个性化推荐系统中分为两种:
显性反馈行为和隐性反馈行为
(1)显性反馈行为:
对某些物品的喜欢、不喜欢;对某条事物的评论
(2)隐性反馈行为:
指的是那些不能明确反应用户喜好的行为。代表性的为页面浏览行为。用户浏览一个页面并不代表用户喜欢这个页面展示的物品,可能是因为页面链接显示在首页,用户更容易点击它,隐性反馈虽然不明确,但数据量更大。在很多网站中,可能只有隐性反馈而没有显性反馈。
针对反馈的明确性分,用户行为数据可以分为显性反馈和隐性反馈;但按照反馈的方向分,又可以分为正反馈和负反馈。正反馈:用户的行为倾向于喜欢,负反馈则相反。
下面是一个各代表网站中的一些对比:
用户行为有很多,我们需要统一一下用户行为的表示
- 1 产生行为的用户
- 2 行为的对象
- 3 行为的种类
- 4 产生行为的上下文
- 5 行为的内容
- 6 行为的权重
不同的数据集包含不同的行为,目前比较有代表性的数据集有:
1 无上下文信息的隐性反馈数据集:每条行为记录仅仅包含用户ID和物品ID
2 无上下文信息的显性反馈数据集 :每条记录包含用户ID、物品ID和用户对物品的评分
3 有上下文信息的隐性反馈数据集:每条记录包含用户ID、物品ID和用户对物品产生行为的时间戳
4 有上下文信息的显性反馈数据集:每条记录包含用户ID、物品ID、用户对物品的评分和评分行为发生的时间戳
(二)用户行为分析
(1)用户活跃度和物品流行度的分布
长尾分布:
1 物品流行度的长尾分布
2 用户活跃度的长尾分布
(2)用户活跃度和物品流行度的关系
一般的,不活跃的用户要么是新用户,要么是只来过网站一两次的老用户。
一般的,新用户倾向于浏览热门的物品,因为他们对网站不熟悉,只能点击热门物品
而老用户会逐渐开始浏览冷门的物品
协同过滤算法:仅仅基于用户行为数据设计的推荐算法
经协同过滤算法的深入研究,又提出了很多方法,比如基于邻域的方法(neghborhood-based)、隐语义模型(latent factor model)、基于图的随机游走算法(random walk on graph
广泛应用并最著名的是基于邻域的方法,主要包含下面两种算法:
- 1 基于用户的协同过滤算法:给用户推荐和他兴趣相似的其他用户喜欢的物品
- 2 基于物品的协同过滤算法:给用户推荐和他之前喜欢的物品相似的物品
(三)实验设计和算法评测
评测推荐系统的3 种方法:离线实验、用户调查和在线实验
下面示例用到的是离线实验方法、数据集为无上下文信息的隐性反馈数据集
协同过滤算法的离线实验设计一般如下:
1 将用户行为数据集按照均匀分布随机分成M份,挑选一份作为测试集,将剩下的M-1份作为训练集。
2 在训练集上建立用户兴趣模型,并在测试集上对用户行为进行预测,统计出相应的评测指标。
3 为了保证评测指标并不是过拟合的结果,需要进行M次实验,并且每次都使用不同的测试集。
4 将M次实验测出的评测指标的平均值作为最终的评测指标
将数据集随机分成训练集和测试集的过程:
def SplitData(data,M,k,seed):
test = []
train = []
random.seed(seed)
for user, item in data:
if random.randint(0,M) == k:
test.append([user,item])
else:
train.append([user,item])
return train,test
每次实验选取不同的k(0≤k≤M1)和相同的随机数种子seed,进行M次实验就可 以得到M个不同的训练集和测试集,然后分别进行实验,用M次实验的平均值作为最后的评测指 标。这样做主要是防止某次实验的结果是过拟合的结果(over fitting),但如果数据集够大,模型 够简单,为了快速通过离线实验初步地选择算法,也可以只进行一次实验
评测指标:
对用户u推荐N个物品R,令用户u在测试集上喜欢的物品集合为T,然后通过准确率/召回率评测推荐算法的精度:
召回率描述有多少比例的用户—物品评分记录包含在最终的推荐列表中,而准确率描述最终 的推荐列表中有多少比例是发生过的用户—物品评分记录。下面两段代码给出了召回率和准确率 的计算方法
def Recall(train ,test ,N):
hit = 0
all = 0
for user in train.keys():
tu =test[user]
rank = GetRecommendation(user,N)
for item,pui in rank:
if item in tu:
hit +=1
all +=len(tu)
return hit/(all * 1.0)
def Precision(train, test, N):
hit = 0 all = 0
for user in train.keys():
tu = test[user]
rank = GetRecommendation(user, N)
for item, pui in rank:
if item in tu:
hit += 1
all += N
return hit / (all * 1.0)
除了上面评测推荐算法的精度,还计算了算法的覆盖率,覆盖率反映了推荐算法发掘长尾的 能力,覆盖率越高,说明推荐算法越能够将长尾中的物品推荐给用户
该覆盖率表示最终的推荐列表中包含多大比例的物品。如果所有的物品都被推荐给至少一个 用户,那么覆盖率就是100%。如下代码可以用来计算推荐算法的覆盖率
def Coverage(train, test, N):
recommend_items = set()
all_items = set()
for user in train.keys():
for item in train[user].keys():
all_items.add(item)
rank = GetRecommendation(user, N)
for item, pui in rank:
recommend_items.add(item)
return len(recommend_items) / (len(all_items) * 1.0)
最后,我们还需要评测推荐的新颖度,这里用推荐列表中物品的平均流行度度量推荐结果的 新颖度。如果推荐出的物品都很热门,说明推荐的新颖度较低,否则说明推荐结果比较新。
由于该章的篇幅比较长,暂时到这,下一节从基于邻域的算法开始。
更多文章请访问博客主页:http://blog.youkuaiyun.com/xudailong_blog