首页 > 编程知识 正文

NDC代码,ndc命令

时间:2023-05-05 11:12:02 阅读:271659 作者:3291

Normalized Discounted Cumulative Gain(归一化折损累计增益)

NDCG用作排序结果的评价指标,评价排序的准确性。

推荐系统通常为某用户返回一个item列表,假设列表长度为K,这时可以用NDCG@K评价该排序列表与用户真实交互列表的差距。

解释:

Gain: 表示列表中每一个item的相关性分数

G a i n = r ( i ) Gain=r(i) Gain=r(i)

Cumulative Gain:表示对K个item的Gain进行累加

C G @ K = ∑ i K r ( i ) CG@K=sum^K_ir(i) CG@K=i∑K​r(i)

Discounted Cumulative Gain:考虑排序顺序的因素,使得排名靠前的item增益更高,对排名靠后的item进行折损。

D C G @ K = ∑ i K r ( i ) l o g 2 ( i + 1 ) DCG@K=sum^K_ifrac{r(i)}{log_2(i+1)} DCG@K=i∑K​log2​(i+1)r(i)​

如果相关性分数r(i)只有(0,1)两种取值时,DCG@K有另一种表达。其实就是如果算法返回的排序列表中的item出现在真实交互列表中时,分子加1,否则跳过。

D C G @ K = ∑ i K = 2 r ( i ) l o g 2 ( i + 1 ) DCG@K=sum_i^K=frac{2^{r(i)}}{log_2(i+1)} DCG@K=i∑K​=log2​(i+1)2r(i)​

Normalized Discounted Cumulative Gain:DCG能够对一个用户的推荐列表进行评价,如果用该指标评价某个推荐算法,需要对所有用户的推荐列表进行评价,由于用户真实列表长度不同,不同用户之间的DCG相比没有意义。所以要对不同用户的指标进行归一化,自然的想法就是计算每个用户真实列表的DCG分数,用IDCG表示,然后用每个用户的DCG与IDCG之比作为每个用户归一化后的分值,最后对每个用户取平均得到最终的分值,即NDCG。

N D C G u @ K = D C G u @ K I D C G u NDCG_u@K=frac{DCG_u@K}{IDCG_u} NDCGu​@K=IDCGu​DCGu​@K​

N D C G @ K = N D C G u @ K ∣ u ∣ NDCG@K=frac{NDCG_u@K}{|u|} NDCG@K=∣u∣NDCGu​@K​

import numpy as npdef 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 / idcgif __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五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。