我目前正在 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)
笔记
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
。