推荐系统常用评价指标


最近在做一些推荐系统方面的研究工作,对于推荐系统的评价指标总是搞得很乱,现在正好用博客整理下,免得每次都要上网查

目录

1.Rating Prediction

对于rating prediction任务,一般都是根据原有的评分数据,利用矩阵分解等方法去拟合原评分,使得优化后的模型可以去预测新的评分,这里就要衡量你预测的评分和实际评分的差异了,指标也很简单,分为RMSEMAE

(1)RMSE

RMSE ⁡ = 1 ∣ T ∣ ∑ ( u , i ) ∈ T ( r ^ u i − r u i ) 2 \operatorname{RMSE}=\sqrt{\frac{1}{|\mathcal{T}|} \sum_{(u, i) \in \mathcal{T}}\left(\hat{r}_{u i}-r_{u i}\right)^{2}} RMSE=T1(u,i)T(r^uirui)2
其中 T \mathcal{T} T是测试集, r ^ u i \hat{r}_{u i} r^ui是模型预测出来的评分, r u i {r}_{u i} rui是测试集的实际评分。

(2)MAE

$$\mathrm{MAE}=\frac{1}{|\mathcal{T}|} \sum_{(u, i) \in \mathcal{T}}\left|\hat{r}_{u i}-r_{u i}\right|$$

RMSE ⁡ = 1 ∣ T ∣ ∑ ( u , i ) ∈ T ( r ^ u i − r u i ) 2 \operatorname{RMSE}=\sqrt{\frac{1}{|\mathcal{T}|} \sum_{(u, i) \in \mathcal{T}}\left(\hat{r}_{u i}-r_{u i}\right)^{2}} RMSE=T1(u,i)T(r^uirui)2
其中 T \mathcal{T} T是测试集, r ^ u i \hat{r}_{u i} r^ui是模型预测出来的评分, r u i {r}_{u i} rui是测试集的实际评分。

RMSE和MAE实际上差别不大的指标,在Rating任务中比较常用

2.Ranking Prediction

对于Ranking prediction任务,一般是将其化为二分类任务:有评分为1,无评分为0(这是比较粗糙的做法),然后对每个用户取其偏好最高的K个商品(TOP-K)推荐。指标看起来也“复杂”很多,分别有Rrecision@K,Recall@K,MAP,MRR,NDCG

(1)Precision@K

p r e c i s i o n @ K = ∣ R e l u ∩ R e c u ∣ ∣ R e c u ∣ precision@K = \frac{\left|R e l_{u} \cap R e c_{u}\right|}{\left|R e c_{u}\right|} precision@K=RecuReluRecu
其中 R e l u R e l_{u} Relu表示与用户 u u u 相关的商品集(测试集), R e c u R e c_{u} Recu表示推荐给用户的前K个列表,二者的交集除以 R e c u R e c_{u} Recu的集合元素个数(其实就是K),得到Precision@K。一般是算出每个用户的Precision@K,然后取平均值。

#计算每个用户的Precision@K值,最后还要取平均值
    def cal_precision_at_k(k, rankedlist, test_matrix):
	    test_set = set(test_matrix)
	    rank_set = set(rankedlist)
	    hit = len(test_set & rank_set)
	    return float(hit / k)

(2)Recall@K

R e c a l @ K = ∣ R e l u ∩ R e c u ∣ ∣ R e l u ∣ Recal@K = \frac{\left|R e l_{u} \cap R e c_{u}\right|}{\left|R e l_{u}\right|} Recal@K=ReluReluRecu
其中 R e l u R e l_{u} Relu表示与用户u相关的商品集(测试集), R e c u R e c_{u} Recu表示推荐给用户的前K个列表,二者的交集除以 R e l u R e l_{u} Relu中元素的个数(也就是测试集中用户u评过分的商品数),得到Recall@K。一般是算出每个用户的Recall@K,然后取平均值。

#计算每个用户的Recall@K值,最后还要取平均值
def cal_Recall_at_k_for_each_user(k, rankedlist, testlist):
    test_set = set(test_matrix)
    rank_set = set(rankedlist)
    hit = len(test_set & rank_set)
    return float(hit / len(test_set))

(3)MAP(Mean Average Precision,平均准确率)

M A P = ∑ u ∈ U ∗ e A P u ∣ U t e ∣ M A P=\frac{\sum_{u \in U^{* e}} A P_{u}}{\left|\mathcal{U}^{t e}\right|} MAP=UteuUeAPu
首先需要计算每个用户AP(Average Precision)
A P u = 1 ∣ I u t e ∣ ∑ i ∈ I u t e ∑ j ∈ I u t u δ ( r a n k u j &lt; r a n k u i ) + 1 r a n k u i A P_{u}=\frac{1}{\left|\mathcal{I}_{u}^{t e}\right|} \sum_{i \in \mathcal{I}_{u}^{t_{e}}} \frac{\sum_{j \in \mathcal{I}_{u}^{t_{u}}} \delta\left(rank_{u j}&lt;rank_{u i}\right)+1}{rank_{u i}} APu=Iute1iIuterankuijIutuδ(rankuj<rankui)+1
公式看起来有点吓人,其中 r a n k u i rank_{u i} rankui表示推荐列表中物品 i 的排序位置, r a n k u j &lt; r a n k u i rank_{u j}&lt;rank_{u i} rankuj<rankui 表示在对用户 u u u 的排序列表中物品 j j j 的排序位置在物品 i i i 的前面。假设你推荐的TOP-K商品中,有N个命中了(与测试集的交集为N),其实就是 A P u = ∑ i ∈ I ∗ u i 在 推 荐 列 表 中 的 排 名 i 在 测 试 集 中 的 排 名 A P_{u} = \frac{\sum_{i \in I^{* u}} i在推荐列表中的排名}{\mathcal i在测试集中的排名} APu=iiIui其中 I ∗ u I^{* u} Iu是用户u的推荐列表中命中的元素集合。MAP就是所有用户AP的平均值。 M A P = 1 ∣ U ∣ ∑ u = 1 ∣ U ∣ A P u \mathrm{MAP}=\frac{1}{|U|} \sum_{u=1}^{|U|} {AP_u} MAP=U1u=1UAPu还是不理解?上代码:

#这个只是计算每个用户MAP的代码,最后还要对整个取平均值
def cal_map_for_each_user(rankedlist, testlist):
    ap = 0
    s = set(testlist)
    #命中的元素在testlist中的排名
    hits = [ idx for idx, val in enumerate(rankedlist) if val in s ] 
    count = len(hits)
    for i in range(count):
        ap += (i+1) / (hits[i] + 1)
        
    if count != 0:
        map = ap / count
    else:
    	map = 0

    return map

(4)MRR(Mean Reciprocal Rank, 平均倒数排名)

M R R = 1 ∣ Q ∣ ∑ i = 1 ∣ U ∣ 1 rank ⁡ i \mathrm{MRR}=\frac{1}{|Q|} \sum_{i=1}^{|U|} \frac{1}{\operatorname{rank}_{i}} MRR=Q1i=1Uranki1
其中 ∣ U ∣ |U| U是用户的个数, r a n k i rank_i ranki是对于第 i i i个用户,推荐列表中第一个在测试集结果中的商品所在的排列位置,计算起来也十分简单:

#这个也是只是计算每个用户的MRR,最后还要取均值
    if count != 0:
        mrr = 1 / (hits[0] + 1)
    else:
    	mrr = 0

(5) NDCG@K(Normalized Discounted Cummulative Gain@K)

NDCG应该是Ranking指标里面最复杂的了,讲NDCG应该先从CG,DCG讲起

CG@K(Cummulative Gain,累计增益)

C G k = ∑ i = 1 k r e l i C G_{k}=\sum_{i=1}^{k} r e l_{i} CGk=i=1kreli
其中, r e l i rel_i reli 表示处于位置 i i i 的推荐结果的相关性,在推荐系统中是命中 r e l i rel_i reli 为1,不命中 r e l i rel_i reli 为0。 k k k是TOP-K中的K。

DCG@K(Discounted Cummulative Gain)

D C G k = ∑ i = 1 k 2 r e l i − 1 log ⁡ 2 ( i + 1 ) D C G_{k}=\sum_{i=1}^{k} \frac{2^{r e l_{i}}-1}{\log _{2}(i+1)} DCGk=i=1klog2(i+1)2reli1,推荐系统中,命中则 2 r e l i − 1 2^{r e l_{i}}-1 2reli1为1,不命中则 2 r e l i − 1 2^{r e l_{i}}-1 2reli1为0。 D C G DCG DCG引入了位置因素,比 C G CG CG更有价值。

IDCG@K(Ideal DCG)

I D C G k = ∑ i = 1 k 1 log ⁡ 2 ( i + 1 ) I D C G_{k}=\sum_{i=1}^{k} \frac{1}{\log _{2}(i+1)} IDCGk=i=1klog2(i+1)1
k k k是TOP-K中的K。 I D C G IDCG IDCG是理想化的 D C G DCG DCG,因此 D C G DCG DCG的值介于[0, I D C G IDCG IDCG]之间。

    for i in range(k):
        idcg_k += 1 / math.log(i + 2, 2)
NDCG@K (Normalized Discounted Cummulative Gain@K)

N D C G u @ k = D C G u @ k I D C G u N D C G_{u} @ k=\frac{D C G_{u} @ k}{I D C G_{u}} NDCGu@k=IDCGuDCGu@k
终于轮到 N D C G @ K NDCG@K NDCG@K了,它的值就是 D C G DCG DCG I D C G IDCG IDCG之间的比值,介于[0,1]之间。
因此所有用户的平均 N D C G @ K NDCG@K NDCG@K为: N D C G @ k = ∑ u ∈ U t e N D C G u @ k ∣ U t e ∣ N D C G @ k=\frac{\sum_{u \in \mathcal{U}^{te} N D C G_{u} @ k}}{\left|\mathcal{U}^{te}\right|} NDCG@k=UteuUteNDCGu@k
其中, U t e U^{te} Ute为测试集中的所有用户。

#计算每个用户的NDCG@K值,最后还要取平均值
def cal_ndcg_at_k_for_each_user(k, rankedlist, testlist):
    idcg_k = 0
    dcg_k = 0
    if len(testlist) < k: k = len(testlist)
    for i in range(k):
        idcg_k += 1 / math.log(i + 2, 2)
        
    s = set(testlist)
    hits = [ idx for idx, val in enumerate(rankedlist) if val in s]
    count = len(hits)

    for i in range(count):
        dcg_k += 1 / math.log(hits[i] + 2, 2)

    return  float(dcg_k / idcg_k)

(6)NDCG(Normalized Discounted Cummulative Gain)

既然已经介绍了 N D C G @ K NDCG@K NDCG@K,为啥还要单独介绍一个 N D C G NDCG NDCG呢,二者除了一个 @ K @K @K有啥区别?
主要是看有的论文是用 N D C G @ K NDCG@K NDCG@K,有的是用 N D C G NDCG NDCG,因此两个都记下来好了,二者的区别主要是计算 I D C G IDCG IDCG的不同( D C G DCG DCG计算是一样的)

IDCG(Ideal DCG)

I D C G n = ∑ i = 1 n 1 log ⁡ 2 ( i + 1 ) I D C G_{n}=\sum_{i=1}^{n} \frac{1}{\log _{2}(i+1)} IDCGn=i=1nlog2(i+1)1
其中n是用户 u u u的测试集长度,这样一算 I D C G IDCG IDCG变大了。然后 N D C G NDCG NDCG计算是公式一样的:
N D C G = ∑ u ∈ U t e N D C G u @ k ∣ U t e ∣ N D C G =\frac{\sum_{u \in \mathcal{U}^{te} N D C G_{u} @ k}}{\left|\mathcal{U}^{te}\right|} NDCG=UteuUteNDCGu@k
其中, U t e U^{te} Ute为测试集中的所有用户。

好了总结完毕~

最后不得不感谢Mathpix Snipping Tool这个工具太好用了,全文的LaTeX公式都是用它做的,想了解的自己去百度搜索,你会发现新天地的。

  • 14
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
<项目介绍> 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到94.5分,放心下载使用! 该资源适合计算机相关专业(如人工智能、通信工程、自动化、软件工程等)的在校学生、老师或者企业员工下载,适合小白学习或者实际项目借鉴参考! 当然也可作为毕业设计、课程设计、课程作业、项目初期立项演示等。如果基础还行,可以在此代码基础之上做改动以实现更多功能。 本项目主要实现了疾病自诊和医生推荐两个功能并构建了医生服务指标评价体系。疾病自诊主要通过利用BERT+CRF+BiLSTM的医疗实体识别, 建立医学知识图谱, 从而实现基于患者问诊文本的疾病初诊。这个功能帮助患者初步了解自身的疾病情况并为下一步与医生的交流提供支持。 第二个功能是医生推荐。本平台采用基于Jacard距离的Minhash和minhashLSHForest算法来进行推荐, 匹配患者的咨询文本和医生的历史问诊信息,从而为患者推荐最适合的医生。最后我们使用django框架进行项目发布。 数据采集 本项目除了使用公开的医疗数据集外,还采集了中国领先医疗平台的数据集。 `spiders`模块提供了数据采集的信息。 39crawler用于获取39健康网的数据,hdf用于获取好大夫网的数据(scrapy)。 我们还提供了编译后的代码程序,感兴趣的同学可以通过百度网盘获取。 链接:https://pan.baidu.com/s/149ttC2KJJLA9HJl8YYKkLg 提取码:见资源 运行程序在dist文件夹中,双击spider_run.exe即可运行爬虫程序。 爬取指定的疾病信息,在disease.txt加入科室名称(拼音)或者疾病名称(拼音),每一个科室或者科室占据单独一行。 无论你在disease.txt文件中添加多少行,爬虫只会爬取第一行对应的科室或疾病,结果将在程序运行完成后,输出为doctor.csv,disease.csv。 如需爬取第二个疾病,请将第一行科室或者疾病删去,重新运行程序。 ## 3.疾病自诊 在疾病自诊模块,平台会读取用户疾病描述的语义信息,首先进行文本预处理,然后通过实体识别模型抽取出其中的关键成分,即:疾病症状、并发症、身体部位等医学实体。然后,这些医学实体会输入到平台后端的知识图谱(基于大规模数据集构建)中。最终,通过知识图谱的快速查询和计算,平台将返回基于患者疾病描述的疾病推断以及相应的概率值。同时,疾病相关的介绍、需要去就诊的科室和疾病多发人群的相关信息也会推送给用户。 ### 3.1. 医学实体识别 医疗实体识别是指从给定句子中识别出医疗实体。在本项目中,需要从患者咨询的病情描述中识别出疾病、症状、科室等多种类型的医疗实体,找到与疾病特征相关的关键词。 `entity_extract`模块提供了有关医学实体识别的有关信息。 支持识别的实体类型 ~~~~ body:患病部位,如:胃,皮肤 drug :药品,如:产妇康清洗液 feature:患病程度,如:严重 disease:疾病,如:前列腺炎 symptom:疾病症状,如:胃壁增厚 department:科室,如:五官科 test:疾病相关的检查,如:血常规 模型选择 我们在训练集上检验了BERT、BERT+CRF、BERT+BiLSTM和BERT+BiLSTM+CRF各模型的准确率、召回率和micro_f1值后,我们发现BERT+BiLSTM+CRF模型具有更好的医疗实体识别能力,因此,在本项目中,我们选用`**BERT+BiLSTM +CRF**`模型完成后续医疗实体识别的任务。 知识图谱构建 为了进行准确的疾病诊断,我们依托于大规模数据集构建知识图谱。 `build_kg`模块提供了有关知识图谱构建的信息。 我们将应用于疾病自诊这一模块的所需实体标记为诊断检查项目、科室、疾病、药品、患病的部位、疾病症状、患病程度,在用户输入一段文本后,我们首先通过实体识别将以上这些关键实体识别出来。 通过事先考察,我们发现在进行疾病诊断的过程中,不仅仅是以身体的症状为依据,也有许多其他的所属关系可供我们参考。因此在进行关系抽取中,我们将各个实体间的关系分为8类,分别为属于、疾病常用药品、疾病对应科室、疾病别名、疾病所需检查、疾病部位、疾病症状、疾病并发疾病。我们通过以上8类关系判断在知识图谱中实体间两两之间的关系,从而计算出患该种疾病的概率。定义知识图谱实体间关系的描述性统计特征如下表所示。 医生推荐 在医生推荐模块,平台期望寻找到历史数据中与用户最相似的患者,并找到与之对应到相应的医生,来完成个性化的推荐。具体而言,平台首先通过用户的描述文本获

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值