# 推荐算法（8）评测指标

1.用户满意度（在线）

2.预测准确度（离线）

2.1评分预测

RMSE的定义：

MAE采用绝对值计算预测误差，它的定义为：

def RMSE(records):
return math.sqrt(sum([(rui-pui)*(rui-pui) for u,i,rui,pui in records])/float(len(records)))

def MAE(records):
return sum([abs(rui-pui) for u,i,rui,pui in records])/float(len(records))


2.2 TopN推荐

2.2.1.1准确率：

2.2.1.2 Mean Average Precision(MAP) 平均准确率

def AP(ranked_list, ground_truth):
"""Compute the average precision (AP) of a list of ranked items
"""
hits = 0
sum_precs = 0
for n in range(len(ranked_list)):
if ranked_list[n] in ground_truth:
hits += 1
sum_precs += hits / (n + 1.0)
if hits > 0:
return sum_precs / len(ground_truth)
else:
return 0



MAP表示所有用户u uu的AP再取均值，计算公式如下：

2.2.2.1召回率

# 定义精确率指标计算方式
def precision(self):
all, hit = 0, 0
for user in self.test:
test_items = set([x[0] for x in self.test[user]])
rank = self.recs[user]
for item, score in rank:
if item in test_items:
hit += 1
all += len(rank)
return round(hit / all * 100, 2) if all > 0 else 0.0

# 定义召回率指标计算方式
def recall(self):
all, hit = 0, 0
for user in self.test:
test_items = set([x[0] for x in self.test[user]])
rank = self.recs[user]
for item, score in rank:
if item in test_items:
hit += 1
all += len(test_items)
return round(hit / all * 100, 2) if all > 0 else 0.0


2.2.2.2 Hit Ratio(HR) 和召回率等价的

(6+5+4)/(10+12+8) = 0.5。

def hit(gt_items, pred_items):
count = 0
for item in pred_items:
if item in gt_items:
count += 1
return count


3.覆盖率

def Coverage(train,test,N):
recommend_items=set()
all_items=set()
for user in train.keys():
for item in train[user].keys():
rank=GetRecommendation(user,N)
for item,Pui in rank:
return len(recommend_items)/(len(all_items)*1.0)


3.1 第一个是信息熵：

3.2 基尼系数（Gini Index）:

def GiniIndex(p):
j = 1
n = len(p)
G=0
for item,weight in sorted(p.items(),key=itemgetter(1)):
G += (2*j-n-1)*weight
return G/float(n-1)



4.多样性
4.1用户的兴趣是广泛的，一个经常看动漫的用户也可以喜欢其他类型的视频。为了满足用户广泛的兴趣，推荐列表需要能够覆盖用户不同的兴趣领域，即推荐结果需要具有多样性。

4.2 ILS
ILS 衡量推荐列表多样性的指标，计算公式：

5.新颖性

# 定义新颖度指标计算方式
def popularity(self):
# 计算物品的流行度
item_pop = {}
for user in self.train:
for item in self.train[user]:
if item not in item_pop:
item_pop[item] = 0
item_pop[item] += 1

num, pop = 0, 0
for user in self.test:
rank = self.recs[user]
for item, score in rank:
# 取对数，防止因长尾问题带来的被流行物品所主导
pop += math.log(1 + item_pop[item])
num += 1
return round(pop / num, 6)


6.惊喜度

7.信任度

8.实时性

9. 健壮性

1. 设计推荐系统时尽量使用代价比较高的用户行为。如在用户的购买行为和浏览行为中，显然购买行为的代价更高。

2. 在使用数据时，进行攻击检测，从而对数据进行清理。

10 Normalized Discounted Cummulative Gain(NDCG) 衡量排序质量的指标

CG没有考虑每个推荐结果处于不同位置对整个推荐结果的影响，例如，我们总是希望相关性大大的结果排在前面，相关性低的排在前面会影响用户体验。

DCG在CG的基础上引入了位置影响因素，计算公式如下：

DCG针对不同的推荐列表之间很难进行横向评估，而我们评估一个推荐系统不可能仅使用一个用户的推荐列表及相应结果进行评估，而是对整个测试集中的用户及其推荐列表结果进行评估。那么，不同用户的推荐列表的评估分数就需要进行归一化，也就是NDCG。
IDCG表示推荐系统某一用户返回的最好推荐结果列表， 即假设返回结果按照相关性排序， 最相关的结果放在最前面， 此序列的DCG为IDCG。因此DCG的值介于 (0,IDCG] ，故NDCG的值介于(0,1]，那么用户u的NDCG@K定义为：

import numpy as np

def ndcg(pred_rel):
dcg = 0
for (index,rel) in enumerate(pred_rel):
dcg += (rel * np.reciprocal(np.log2(index+2)))
print("dcg " + str(dcg))
idcg = 0
for(index,rel) in enumerate(sorted(pred_rel,reverse=True)):
idcg += (rel * np.reciprocal(np.log2(index+2)))
print("idcg " + str(idcg))

return dcg/idcg

pred_rel = [3,1,2,3,2]
print("ndcg " + str(ndcg(pred_rel)))


11.Mean Reciprocal Rank(MRR) 平均倒数排名

import numpy as np

def mrr(gt_items, pred_items):
for index,item in enumerate(pred_items):
if item in gt_items:
return 1/index


10-16 8611

09-29 3165
01-25 1694
09-23 1万+
04-24 1268
07-30 1万+
09-25 1万+
12-01 5083
08-20 4954
02-07 1万+
12-28 247
12-23 2804