参考
https://zhuanlan.zhihu.com/p/136199536
http://zhaoxi-sight.com/artificial-intelligence/%E6%90%9C%E7%B4%A2%E7%B3%BB%E7%BB%9F%E4%B9%8B%E8%AF%84%E4%BB%B7%E6%8C%87%E6%A0%87ndcg/
含义
- 高相关性的文档在搜索引擎结果列表越早出现越好。即高相关性的文档出现的位置越靠前,指标会越高。
- NDCG 同样可以用来计算推荐系统中,召回、排序的平均点击位置,来评估效果
累积增益(Cumulative Gain, CG)
CG 是搜索结果列表中所有文档的分级相关性得分的总和。CG 只考虑了搜索结果列表中文档的相关性,而没有考虑这些文档在结果列表中的位置因素。给定一个结果列表的排序位置 p ,CG可定义为:
其中 i 表示当前文档所处位置,rel_i 表示该文档的相关性
折损累计增益(Discounted cumulative gain,DCG)
DCG 提出在搜索结果列表的较低位置上出现相关性较高的文档时,应该对评测得分施加惩罚。惩罚比例与文档的所在位置的对数值相关。给定一个结果列表的排序位置 p ,DCG 可定义为:
理想累积折现增益(ideal Discounted Cumulative Gain,IDCG)
IDCG 就是当前结果在最理想情况下的 DCG。
比如排序结果: A = [3,2,3,1,2],理想结果应该是: I_A = [3,3,2,2,1]
计算 I_A 的 DCG 即为 IDCG
归一化折损累计增益(Normalized Discounted Cumulative Gain, NDCG)
NDCG 就是当前结果的 DCG 用 IDCG 进行归一化,用于表示当前结果接近最理想的结果的程度。
import pandas as pd
import numpy as np
df = pd.DataFrame(data={'rank': [1, 2, 3, 4, 5],
'rel_a': [3, 2, 3, 1, 2],
'rel_b': [0, 1, 0, 0, 1]})
def get_dcg(rank, rel):
return (np.power(2, rel) - 1) / np.log2(rank + 1)
df['dcg_a'] = df.apply(lambda row: get_dcg(row['rank'], row['rel_a']), axis=1)
df['dcg_b'] = df.apply(lambda row: get_dcg(row['rank'], row['rel_b']), axis=1)
df['i_rel_a'] = sorted(df['rel_a'], reverse=True)
df['i_rel_b'] = sorted(df['rel_b'], reverse=True)
df['idcg_a'] = df.apply(lambda row: get_dcg(row['rank'], row['i_rel_a']), axis=1)
df['idcg_b'] = df.apply(lambda row: get_dcg(row['rank'], row['i_rel_b']), axis=1)
df
ndcg_a = df['dcg_a'].sum() / df['idcg_a'].sum()
ndcg_b = df['dcg_b'].sum() / df['idcg_b'].sum()
ndcg_a
ndcg_b