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

标签 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在评估阶段的评估方法是一样的吗?

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

对于最终的树,当我运行 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

最佳答案

交叉发布我对此交叉发布问题的交叉验证答案: 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

关于python - XGBoost/lightGBM 如何评估 ndcg 的排名任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46247340/

相关文章:

python - 将二维数组中的每一列与另一个二维数组中的每一列相乘

python - 如何将我自己的字典添加到python中的词段库中?

machine-learning - 成本函数,线性回归,试图避免硬编码 theta。 Octave 。

python - 多条件提前停止

python - 如何从 iOS 调用 python 脚本

python - 如何排除某个 wiki 页面出现在 trac 搜索中?

facebook - 在网站 "Recommend This Site"按钮点击和 "Share This Story"按钮点击上获得不一致的 Facebook 点赞计数器

sequence - 如何训练序列项的 LSTM 模型?

c++ - 从 C++ 调用 Cython 函数

python - 神经网络 : Mysterious ReLu