首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XGBoost/lightGBM如何评估ndcg对任务的排序?

XGBoost/lightGBM如何评估ndcg对任务的排序?
EN

Stack Overflow用户
提问于 2017-09-15 20:55:00
回答 2查看 3.5K关注 0票数 3

目前,我正在XGBoost/lightGBM之间运行测试,以了解它们对项进行排序的能力。我正在复制这里提供的基准:基准

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

我的问题是:

  1. 当使用ndcg为测试集创建验证时--有一个test.group文件,其中显示前X行为组0,等等。为了获得组的建议,我得到了预测值和已知的相关分数,并通过降低每个组的预测值对列表进行排序?
  2. 为了从上面创建的列表中得到最终的ndcg分数,我得到ndcg的分数并取所有分数的平均值吗?这是与评估阶段的XGBoost/lightGBM相同的评估方法吗?

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

对于最后一棵树,当我运行lightGBM时,我在验证集上获得以下值:

代码语言:javascript
复制
[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代码:

代码语言:javascript
复制
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

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

代码语言:javascript
复制
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行。

然后,我将元组的列表按降序排序,其中提供了一个关联分数列表:

代码语言:javascript
复制
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分数的平均值:

代码语言:javascript
复制
relavance.apply(lambda x: ndcg_at_k(x, 10)).mean()

我得到的值是~0.497193

EN

回答 2

Stack Overflow用户

发布于 2021-02-11 19:52:36

交叉张贴“我的十字”验证了这个跨帖问题的答案:https://stats.stackexchange.com/questions/303385/how-does-xgboost-lightgbm-evaluate-ndcg-metric-for-ranking/487487#487487

我自己偶然发现了这件事,并最终钻研了代码来解决这个问题。

不同之处在于如何处理缺少的IDCG。代码返回0,而LightGBM把那个案子当作一个1返回。

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

代码语言:javascript
复制
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
票数 2
EN

Stack Overflow用户

发布于 2017-09-26 13:21:58

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46247340

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档