我目前正在XGBoost / lightGBM之间运行测试,以对它们进行排名。我正在复制此处提供的基准:https://github.com/guolinke/boosting_tree_benchmarks

我已经能够成功复制他们工作中提到的基准。我想确保自己正确实现了自己的ndcg指标版本,并且正确理解了排名问题。

我的问题是:


使用ndcg为测试集创建验证时-有一个test.group文件,其中说前X行是第0组,以此类推。为了获得该组的建议,我得到了预测值和已知的相关性分数,并对它们进行了排序通过递减每个组的预测值列出?
为了从上面创建的列表中获得最终的ndcg分数-我是否获得ndcg分数并取所有分数的平均值?这与XGBoost / lightGBM处于评估阶段的评估方法是否相同?


这是我在模型完成训练后评估测试集的方法。

对于运行lightGBM的最后一棵树,我在验证集上获得了这些值:

[500]   valid_0's ndcg@1: 0.513221  valid_0's ndcg@3: 0.499337  valid_0's ndcg@5: 0.505188  valid_0's ndcg@10: 0.523407


我的最后一步是获取测试集的预测输出并计算预测的ndcg值。

这是我计算ndcg的python代码:

import numpy as np

def dcg_at_k(r, k):
    r = np.asfarray(r)[:k]
    if r.size:
        return np.sum(np.subtract(np.power(2, r), 1) / np.log2(np.arange(2, r.size + 2)))
    return 0.


def ndcg_at_k(r, k):
    idcg = dcg_at_k(sorted(r, reverse=True), k)
    if not idcg:
        return 0.
    return dcg_at_k(r, k) / idcg


在获得针对特定组(GROUP-0)的测试集的预测后,我得到以下预测:

query_id    predict
0   0   (2.0, -0.221681199441)
1   0   (1.0, 0.109895548348)
2   0   (1.0, 0.0262799346312)
3   0   (0.0, -0.595343431322)
4   0   (0.0, -0.52689043426)
5   0   (0.0, -0.542221350664)
6   0   (1.0, -0.448015576024)
7   0   (1.0, -0.357090949646)
8   0   (0.0, -0.279677741045)
9   0   (0.0, 0.2182200869)


注意

组0实际上有大约112行。

然后,我按降序对元组列表进行排序,从而提供相关性得分列表:

def get_recommendations(x):

    sorted_list = sorted(list(x), key=lambda i: i[1], reverse=True)
    return [k for k, _ in sorted_list]

relavance = evaluation.groupby('query_id').predict.apply(get_recommendations)

query_id
0    [4.0, 2.0, 2.0, 3.0, 2.0, 2.0, 2.0, 2.0, 2.0, ...
1    [4.0, 2.0, 2.0, 2.0, 1.0, 1.0, 3.0, 2.0, 1.0, ...
2    [2.0, 3.0, 2.0, 2.0, 1.0, 0.0, 2.0, 2.0, 1.0, ...
3    [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, ...
4    [1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, ...


最后,对于每个查询ID,我都会在相关性列表中计算ndcg分数,然后取为每个查询ID计算的所有ndcg分数的平均值:

relavance.apply(lambda x: ndcg_at_k(x, 10)).mean()


我获得的值是~0.497193

最佳答案

我认为问题是由相同查询中具有相同标签的数据引起的。
在这种情况下,XGBoost和LightGBM都将为该查询生成ndcg 1。

09-04 23:24