lightgbm 的查询信息概念是什么(用于地图度量)?



我正在尝试使用"map"度量激活lightgbm(我将在本文的最后解释我为什么要这样做(,并使用以下参数dict(使用sklearn API(:

param = {
'objective': 'binary',
'num_threads': 40,
'metric': 'map',
'eval_at': 300,
'feature_fraction': 1.0,
'bagging_fraction': 1.0,
'min_data_in_leaf': 50,
'max_depth': -1,
'subsample_for_bin': 200000,
'subsample': 1.0,
'subsample_freq': 0,
'min_split_gain': 0.0,
'min_child_weight': 0.001,
'min_child_samples': 20,
'n_estimators': 9999
}

但我得到以下错误:

> [LightGBM] [Fatal] For MAP metric, there should be query information
> Traceback (most recent call last):   File
> "/home/danri/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py",
> line 2910, in run_code
>     exec(code_obj, self.user_global_ns, self.user_ns)   File "<ipython-input-76-81403c753a65>", line 44, in <module>
>     eval_metric=param_1['metric'])   File "/home/danri/anaconda3/lib/python3.6/site-packages/lightgbm/sklearn.py",
> line 539, in fit
>     callbacks=callbacks)   File "/home/danri/anaconda3/lib/python3.6/site-packages/lightgbm/sklearn.py",
> line 391, in fit
>     callbacks=callbacks)   File "/home/danri/anaconda3/lib/python3.6/site-packages/lightgbm/engine.py",
> line 168, in train
>     booster = Booster(params=params, train_set=train_set)   File "/home/danri/anaconda3/lib/python3.6/site-packages/lightgbm/basic.py",
> line 1215, in __init__
>     ctypes.byref(self.handle)))   File "/home/danri/anaconda3/lib/python3.6/site-packages/lightgbm/basic.py",
> line 47, in _safe_call
>     raise LightGBMError(_LIB.LGBM_GetLastError()) lightgbm.basic.LightGBMError: b'For MAP metric, there should be query
> information'

我对查询信息概念的唯一解释是在lightgbm参数文档中

这就是解释:

查询数据

对于LambdaRank学习,它需要训练数据的查询信息。LightGBM使用一个附加文件来存储查询数据。以下是示例:

27 18 67。。。

这意味着前27行样本属于一个查询,接下来是18行属于另一个,依此类推。(注意:数据应按查询排序(如果数据文件的名称为"train.txt",查询文件的名称应为"train.txt.query"和训练数据的同一文件夹中。LightGBM将如果查询文件存在,则自动加载该文件。

您现在可以在数据文件中指定查询/组id。请参阅上面的参数组。

我还研究了lightgbm代码以了解它的用法,但仍然不理解查询信息的概念。有人能解释一下吗?

我尝试使用"映射"度量的原因是,我的分类模型的目的是达到前10%风险的最高PPV。当我通过"auc"进行优化时,排名的任何改进(在最高风险十分位数或样本数据集的其他部分(都会提高auc。我希望该模型只在提高前10%的PPV方面进行优化,因为这将是它在现实世界中的用途(即将前10%的风险人群送往特定的医疗机构(。

很乐意得到任何帮助。

谢谢!

有以下几点:

  • 度量仅用于评估,不用于优化(除了拟合后选择最佳超参数或提前停止(
  • "查询"(或"组"(基本上是告诉模型如何对样本进行分组的方法。对于评估(如果仅使用映射度量而不使用排名损失函数(,可以通过fit方法的eval_group参数提供组,请参见此处。这是一个数组列表。该列表的长度与eval_set相同,各个数组包含每组中的元素数。因此,数组中的整数之和应该计算相应评估集中的样本数。请注意,为了使这种分组高亮显示工作,代码假设组是按顺序来的。例如,eval_group=[(2,3)]将意味着度量评估将期望具有长度为5(=2+3(的评估样本,并且前2个元素被期望属于一个组,而后2个元素则属于另一组

您想过使用另一个度量吗?根据我对你问题的理解,第一个十分位数的提升可能是一个很好的评估指标。它将你的模型发现"有风险的人"的能力与随机猜测进行了比较,在n%的最高概率中。

简言之,你取按概率排序的前十分之一样本(正如你的模型预测的那样,这些人是"最危险的人"(,计算其中实际"1"的数量,然后除以随机预测给出的实际"1(的数量。

以下是如何在lightgbm中实现它。您需要将其作为"f_eval"参数。它不会用于优化,仅用于评估(以及提前停止(。此代码不处理相等预测的情况。

def f_eval_lift(pred, train_data, centile=10):
df = pd.DataFrame({'true': train_data.get_label(), 'pred': pred})
centile_num = int(np.ceil(centile / 100 * df.shape[0]))
num_1 = int(df['true'].sum())
df = df.nlargest(centile_num, columns='pred', keep='last')
# TODO : handle the case of equal predictions
lift_value = df['true'].sum() / (centile / 100 * num_1)
return 'lift_' + str(centile), lift_value, True

相关内容

  • 没有找到相关文章

最新更新