XGBoost / lightGBM如何评估ndcg的排名任务?

时间:2017-09-15 20:55:01

标签: python machine-learning recommendation-engine xgboost lightgbm

我目前正在XGBoost / lightGBM之间运行测试,因为他们能够对项目进行排名。我正在复制这里提出的基准:https://github.com/guolinke/boosting_tree_benchmarks

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

我的问题是:

  1. 使用ndcg创建测试集的验证时 - 有一个test.group文件,表示前X行是0组,等等。为了获得组的推荐,我得到了预测值和已知的相关性得分和排序按每组降序预测值列出?

  2. 为了从上面创建的列表中获得最终的ndcg分数 - 我是否获得ndcg分数并取得所有分数的均值?这与评估阶段XGBoost / lightGBM的评估方法相同吗?

  3. 以下是我在模型完成培训后评估测试集的方法。

    对于运行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)
    

    注意

    Group-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

2 个答案:

答案 0 :(得分:1)

交叉发布我对这个交叉发布问题的交叉验证答案: https://stats.stackexchange.com/questions/303385/how-does-xgboost-lightgbm-evaluate-ndcg-metric-for-ranking/487487#487487


我自己也遇到过这个问题,最后深入代码找出了答案。

不同之处在于对丢失的 IDCG 的处理。您的代码返回 0,而 LightGBM is treating that case as a 1

以下代码为我生成了匹配结果:

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 1.  # CHANGE THIS
    return dcg_at_k(r, k) / idcg

答案 1 :(得分:0)

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