【推荐系统排序指标】CG、DCG、NDCG、Hit Rate

举报
野猪佩奇996 发表于 2022/05/17 00:06:17 2022/05/17
【摘要】 文章目录 一、CG,累计增益 Cumulative Gain二、DCG,折损累计增益 Discounted cumulative gain三、NDCG,归一化折损累计增益 Normalized D...

一、CG,累计增益 Cumulative Gain

CG表示对K个item的Gain进行累加,其中Gain表示列表中每一个item的相关性分数 r ( i ) r(i) r(i),CG即: C G @ K = ∑ i K r ( i ) C G @ K=\sum_{i}^{K} r(i) CG@K=iKr(i)

二、DCG,折损累计增益 Discounted cumulative gain

DCG提出:如果有效结果在列表中排的较低的话,应该对列表的评分惩罚,惩罚和有效结果的排位有关。所以就加了衰减因子:
D C G p = ∑ i = 1 p r e l i log ⁡ 2 ( i + 1 ) = r e l 1 + ∑ i = 2 p r e l i log ⁡ 2 ( i + 1 ) D C G_{p}=\sum_{i=1}^{p} \frac{r e l_{i}}{\log _{2}(i+1)}=r e l_{1}+\sum_{i=2}^{p} \frac{r e l_{i}}{\log _{2}(i+1)} DCGp=i=1plog2(i+1)reli=rel1+i=2plog2(i+1)reli
还有一个公式广泛在工业界和kaggle比赛中,对应的公式和代码如下:
D C G p = ∑ i = 1 p 2 r e l i − 1 log ⁡ 2 ( i + 1 ) D C G_{p}=\sum_{i=1}^{p} \frac{2^{r e l_{i}}-1}{\log _{2}(i+1)} DCGp=i=1plog2(i+1)2reli1

# 第二种公式的实现
import numpy as np
def dcg_at_n(rel, n):
    rel = np.asfarray(rel)[:n]
    dcg = np.sum(np.divide(np.power(2, rel) - 1, log2_table[:rel.shape[0]]))
    return dcg

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意:当相关性得分是 0 / 1 0 / 1 0/1 ,即 r e l i ∈ { 0 , 1 } r e l_{i} \in\{0,1\} reli{0,1} 时,上面两个公式是等价的。

三、NDCG,归一化折损累计增益 Normalized Discounted Cumulative Gain

3.1 NDCG简介

常用作排序模型的指标评估。DCG没有考虑到推荐列表和每个检索中真正有效结果(test items list) 的个数,所以最后引入NDCG,就是标准化后的DCG。
N D C G k = D C G k I D C G k N D C G_{k}=\frac{D C G_{k}}{I D C G_{k}} NDCGk=IDCGkDCGk
其中 I D C G I D C G IDCG 是指ideal DCG,即理想结果下的DCG,对应的公式为: I D C G p = ∑ i = 1 ∣ R E L p ∣ 2 j e l i − 1 log ⁡ 2 ( i + 1 ) I D C G_{p}=\sum_{i=1}^{\left|R E L_{p}\right|} \frac{2^{j e l_{i}}-1}{\log _{2}(i+1)} IDCGp=i=1RELplog2(i+1)2jeli1

简单说:NDCG是由各DCG除以当前DCG中最大的值得到的。
n:Normalization,不同指标大小不同,需要做normalization
D:Position discount,位置越靠前影响越大
C:Cumulating,
G:Gain,可以使相关性、点击率等指标
在这里插入图片描述

3.2 电影推荐的一个栗子

基于打分的个性推荐系统可以用CG(cumulative gain), 累计増益。假设我们推荐 k k k 个物品,这个推荐列表的 C G k C G_{k} CGk 计算 公式如下:
C G k = ∑ i = 1 k r e l i . C G_{k}=\sum_{i=1}^{k} \mathrm{rel}_{i} . CGk=i=1kreli.
r e l i \mathrm{rel}_{i} reli 表示第 k k k 个物品的相关性。假设我们共推孝 k k k 个电影, r e l i r e l_{i} reli 可以是用户对第 i i i 部电影的评分。
比如豆篗给用户推荐了五部电影,
M 1 , M 2 , M 3 , M 4 , M 5 .  M_{1}, M_{2}, M_{3}, M_{4}, M_{5} \text {. } M1,M2,M3,M4,M5
该用户对这五部电影的评分分别是 5 , 3 , 2 , 1 , 2 5,3,2,1,2 5,3,2,1,2
那么这个推荐列表的CG等于
C G 5 = 5 + 3 + 2 + 1 + 2 = 13 C G_{5}=5+3+2+1+2=13 CG5=5+3+2+1+2=13
CG没有考虎推荐的次序,在此基础之后我们引入对物品顺序的考虑,就有了DCG(discounted CG), 折扣累积增益。 公式如下:
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^{\mathrm{rel}_{i}}-1}{\log _{2}(i+1)} . DCGk=i=1klog2(i+1)2reli1.
比如豆蛌给用户推荐了五部电影,
M 1 , M 2 , M 3 , M 4 , M 5 ,  M_{1}, M_{2}, M_{3}, M_{4}, M_{5} \text {, } M1,M2,M3,M4,M5
该用户对这五部电影的评分分别是 5 , 3 , 2 , 1 , 2 5,3,2,1,2 5,3,2,1,2
那么这个推荐列表的DCG等于
D C G 5 = 2 5 − 1 log ⁡ 2 2 + 2 3 − 1 log ⁡ 2 3 + 2 2 − 1 log ⁡ 2 4 + 2 1 − 1 log ⁡ 2 5 + 2 2 − 1 log ⁡ 2 6 = 31 + 4.4 + 1.5 + 0.4 + 1.2 = 38.5 D C G_{5}=\frac{2^{5}-1}{\log _{2} 2}+\frac{2^{3}-1}{\log _{2} 3}+\frac{2^{2}-1}{\log _{2} 4}+\frac{2^{1}-1}{\log _{2} 5}+\frac{2^{2}-1}{\log _{2} 6}=31+4.4+1.5+0.4+1.2=38.5 DCG5=log22251+log23231+log24221+log25211+log26221=31+4.4+1.5+0.4+1.2=38.5

3.3 代码实践栗子

这里也贴一个代码的实践例子:

import numpy as np

def ndcg(rel_true, rel_pred, p=None, form="linear"):
    """ Returns normalized Discounted Cumulative Gain
    Args:
        rel_true (1-D Array): relevance lists for particular user, (n_songs,)
        rel_pred (1-D Array): predicted relevance lists, (n_pred,)
        p (int): particular rank position
        form (string): two types of nDCG formula, 'linear' or 'exponential'
    Returns:
        ndcg (float): normalized discounted cumulative gain score [0, 1]
    """
    rel_true = np.sort(rel_true)[::-1]
    p = min(len(rel_true), min(len(rel_pred), p))
    # 因为索引是从0开始的,正常应该加1,但是从0开始,log(0+1)则等于无穷大,所以这里面加的是2,如果索引是从1开始,则加的是1,所以感觉跟上面的公式不一致,其实是一样的。
    discount = 1 / (np.log2(np.arange(p) + 2))

    if form == "linear":
        idcg = np.sum(rel_true[:p] * discount)
        dcg = np.sum(rel_pred[:p] * discount)
    elif form == "exponential" or form == "exp":
        idcg = np.sum([2 ** x - 1 for x in rel_true[:p]] * discount)
        dcg = np.sum([2 ** x - 1 for x in rel_pred[:p]] * discount)
    else:
        raise ValueError("Only supported for two formula, 'linear' or 'exp'")

    return dcg / idcg


if __name__ == "__main__":
    song_index = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8}
    user_lists = ["USER1", "USER2", "USER3"]

    relevance_true = {
        # 每首歌曲i在每个用户下的评分,并且按降序排序,这个顺序对于相应的用户是最完美的。
        "USER1": [3, 3, 2, 2, 1, 1, 0, 0, 0],
        "USER2": [3, 2, 1, 1, 2, 0, 1, 1, 1],
        "USER3": [0, 1, 0, 1, 2, 3, 3, 1, 0]
    }

    s1_prediction = {
        # 模型预测,用户可能点击的顺序
        "USER1": ['A', 'E', 'C', 'D', 'F'],
        "USER2": ['G', 'E', 'A', 'B', 'D'],
        "USER3": ['C', 'G', 'F', 'B', 'E']
    }

    s2_prediction = {
        "USER1": ['A', 'B', 'C', 'G', 'E'],
        "USER2": ['B', 'A', 'G', 'E', 'F'],
        "USER3": ['E', 'G', 'F', 'B', 'I']
    }


    for user in user_lists:
        print(f'===={user}===')
        r_true = relevance_true[user]

        for song in s1_prediction[user]:
            test = song_index[song]
            test2 = r_true[test]
        s1_pred = [r_true[song_index[song]] for song in s1_prediction[user]]
        s2_pred = [r_true[song_index[song]] for song in s2_prediction[user]]

        print(f'S1 nDCG@5 (linear): {ndcg(r_true, s1_pred, 5, "linear")}')
        print(f'S2 nDCG@5 (linear): {ndcg(r_true, s2_pred, 5, "linear")}')

        # 一般我们使用下面指数的形式
        print(f'S1 nDCG@5 (exponential): {ndcg(r_true, s1_pred, 5, "exp")}')
        print(f'S2 nDCG@5 (exponential): {ndcg(r_true, s2_pred, 5, "exp")}')

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

结果如下,三个用户对应的NDCG指标:

====USER1===
S1 nDCG@5 (linear): 0.8232936061974518
S2 nDCG@5 (linear): 0.8793791209851007
S1 nDCG@5 (exponential): 0.7406319169800546
S2 nDCG@5 (exponential): 0.911476869939315
====USER2===
S1 nDCG@5 (linear): 0.8241067540896558
S2 nDCG@5 (linear): 0.864255024163802
S1 nDCG@5 (exponential): 0.7200216168193889
S2 nDCG@5 (exponential): 0.821434096248145
====USER3===
S1 nDCG@5 (linear): 0.6850898875992608
S2 nDCG@5 (linear): 0.867837452040598
S1 nDCG@5 (exponential): 0.6922758990315323
S2 nDCG@5 (exponential): 0.826208951093206

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

四、Hit Rate

hr指标在top N推荐中经常使用:
H R =  测试集中的item出现在  T o p − N  推荐列表中的用户数量   用户总数  H R=\frac{\text { 测试集中的item出现在 } T o p-N \text { 推荐列表中的用户数量 }}{\text { 用户总数 }} HR= 用户总数  测试集中的item出现在 TopN 推荐列表中的用户数量 

五、推荐系统评测指标

在这里插入图片描述

Reference

[1] 推荐系统常用评价指标:NDCG、Recall、Precision、Hit Rate
[2] https://en.wikipedia.org/wiki/Discounted_cumulative_gain
[3] 推荐系统有哪些常用的评价标准
[4] 某乎:推荐系统研究中常用的评价指标
[5] 推荐系统5—多目标排序

文章来源: andyguo.blog.csdn.net,作者:山顶夕景,版权归原作者所有,如需转载,请联系作者。

原文链接:andyguo.blog.csdn.net/article/details/124675454

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。