推荐系统评测方法和指标
目录
前提
假设研究的是是TopN推荐问题,即推荐的任务是预测用户会不会对物品进行评分(或其他行为),程序上表现为是否会产生一条‘用户-物品’记录。
离线评测方法(交叉验证)
将用户行为数据集均等分成M份,挑选一份作为测试集,剩下的M-1份作为训练集。为了防止过拟合的测试结果,需要进行M次试验,使得每份数据集都有一次作为测试集的机会,然后以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
离线评测指标
召回率
召回率描述有多少比例的用户-物品记录包含在最终的推荐结果列表里。即推荐正确的数量与实际记录数之比。
xxxxxxxxxx
# 计算召回率
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)
新颖度
可以用推荐列表中物品的平均流行度度量推荐结果的新颖度,如果推荐出的物品都很热门,说明推荐的新颖度较低。
#新颖度计算
def Popluarity(train,test,N):
item_popularity=dict()
for user,item in train.items():
for item in items.keys():
if item not in item_popularity:
item_popularity[item]=0
item_popularity[item]+=1
ret=0
n=0
for user in train.keys():
rank=GetRecommendation(user,N)
for item,pui in rank:
#取对数,让流行度的平均值更加稳定平滑
ret+=math.log(1+item_popularity[item])
n+=1
ret/=n*1.0
return ret