NDCG(标准化折扣增益)是否有缺陷?我已经计算了一些替代的排名质量测量,我无法做出正面或反面

时间:2014-10-01 18:33:42

标签: python machine-learning information-retrieval supervised-learning ranking-functions

我正在使用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:平均值是.87(听起来不错)
  • 斯皮尔曼等级:大约.25(不惊人,但有一些东西)
  • NDCG2:.58(平均而言,稍微接近最佳dcg而不是最差)
  • NDCG3:1.04(略好于随机排序的列表)

老实说,我无法对这些结果做出正面或反面。我的NDCG值似乎很好,但它们在列表中是否真的具有可比性?替代指标是否更有意义?

编辑:在我的第一次随机比较中,我没有使用np.copy()。因此,我的随机分数几乎总是.99。现在已经修复了,结果更有意义。

1 个答案:

答案 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具有直观含义,则必须进行设置 '秩'小于或等于您的文件数量。