我正在使用python进行学习排名问题,我正在使用以下DCG和NDCG代码评估我的成功(来自http://nbviewer.ipython.org/github/ogrisel/notebooks/blob/master/Learning%20to%20Rank.ipynb)
def dcg(relevances, rank=20):
relevances = np.asarray(relevances)[:rank]
n_relevances = len(relevances)
if n_relevances == 0:
return 0.
discounts = np.log2(np.arange(n_relevances) + 2)
return np.sum(relevances / discounts)
def ndcg(relevances, rank=20):
best_dcg = dcg(sorted(relevances, reverse=True), rank)
if best_dcg == 0:
return 0.
return dcg(relevances, rank) / best_dcg
以下是3个项目列表中最佳和最差情况的DCG值,没有重复的排名......
>>> ndcg(np.asarray([3,2,1]))
1.0
>>> ndcg(np.asarray([1,2,3]))
0.78999800424603583
我们可以使用此指标来比较两个排名,看看哪个更好。如果我计算4项目列表的最坏情况,但是......
>>> ndcg(np.asarray([1,2,3,4]))
0.74890302967841715
4项目列表似乎不再与3项目列表相比。
我还计算了两种替代NDCG。 NDCG2将实现的dcg与机器人的最佳和最差情况进行比较......
def ndcg2(relevances, rank=20):
best_dcg = dcg(sorted(relevances, reverse=True), rank)
worst_dcg=dcg(sorted(relevances, reverse=False),rank)
if best_dcg == 0:
return 0.
return (dcg(relevances, rank)-worst_dcg) / (best_dcg-worst_dcg)
NDCG将我的实际排名列表随机抽样50次,计算每项排名,并将其与我的实际DCG进行比较。
def ndcg3(relevances, rank=20):
shuffled=np.copy(relevances)
rands=[]
for i in range(50):
np.random.shuffle(shuffled)
rands.append(dcg(shuffled,rank))
avg_rand_dcg=np.mean(np.asarray(rands))
return dcg(relevances, rank) / avg_rand_dcg
在我的各个列表中,我得到以下指标......
老实说,我无法对这些结果做出正面或反面。我的NDCG值似乎很好,但它们在列表中是否真的具有可比性?替代指标是否更有意义?
编辑:在我的第一次随机比较中,我没有使用np.copy()。因此,我的随机分数几乎总是.99。现在已经修复了,结果更有意义。
答案 0 :(得分:3)
有人认为可能误导你的是使NDCG正常化的方法。通常,您有许多文档要排名,但您的NDCG会在较少数量的文档中被截断(例如NCDG @ 3)。在您的代码中,这由参数' rank'决定。
让我们假设您要对5个文档进行排名,其中R = [1,2,3,4,0],并计算NDCG @ 3。如果您的算法认为最佳顺序是[doc1,doc2,doc3,doc4,doc5],那么您将拥有:
NDCG@3 = DCG([1, 2, 3]) / DCG([4, 3, 2])
而不是
NDCG@3 = DGC([1, 2, 3]) / DCG([3, 2, 1]) # Incorrect
所以从某种意义上说,NDCG([1,2,3])和NDCG([1,2,3,4])是无法比较的。分子是完全相同的,但分母是完全不同的。如果您希望NDCG具有直观含义,则必须进行设置 '秩'小于或等于您的文件数量。