LightGBM中的'Dataset中使用categorical_feature'警告?

20

根据我阅读的LightGBM文档,应该在Dataset方法中定义分类特征。因此,我有以下代码:

cats=['C1', 'C2']
d_train = lgb.Dataset(X, label=y, categorical_feature=cats)

然而,我收到了以下错误消息:

/app/anaconda3/anaconda3/lib/python3.7/site-packages/lightgbm/basic.py:1243: UserWarning: 在数据集中使用categorical_feature。 warnings.warn('在数据集中使用categorical_feature。')

为什么会收到这个警告消息?

3个回答

31
我猜测你在调用`lgb.train`函数时收到了警告。该函数还有一个参数`categorical_feature`,默认值为`'auto'`,这意味着从`pandas.DataFrame`中获取分类列(参见文档)。警告是在此行发出的,它表示尽管`lgb.train`已经请求自动识别分类特征,但LightGBM将使用数据集中指定的特征。
为避免警告,您可以在`lgb.Dataset`和`lgb.train`中都使用相同的参数`categorical_feature`。或者,您可以使用`categorical_feature=None`构建数据集,并只在`lgb.train`中指定分类特征。

如果使用sklearn API中的DataFrame,则无法构建具有categorical_feature=None的数据集。 - memeplex
4
这还能用吗?无论我如何/在哪里指定分类变量,我都会收到“覆盖参考数据集中的参数。参数字典中的分类列被覆盖。”的消息。 - ironv
不幸的是,警告仍然存在。 - CutePoison

4

如用户andrey-popov所述,您可以使用lgb.traincategorical_feature参数来消除此警告。

下面是一个简单的示例,其中包含一些代码,说明您如何实现:

# Define categorical features
cat_feats = ['item_id', 'dept_id', 'store_id', 
             'cat_id', 'state_id', 'event_name_1',
             'event_type_1', 'event_name_2', 'event_type_2']
    ...

# Define the datasets with the categorical_feature parameter
train_data = lgb.Dataset(X.loc[train_idx], 
                         Y.loc[train_idx], 
                         categorical_feature=cat_feats, 
                         free_raw_data=False)

valid_data = lgb.Dataset(X.loc[valid_idx], 
                         Y.loc[valid_idx], 
                         categorical_feature=cat_feats, 
                         free_raw_data=False)

# And train using the categorical_feature parameter
lgb.train(lgb_params, 
          train_data, 
          valid_sets=[valid_data], 
          verbose_eval=20, 
          categorical_feature=cat_feats, 
          num_boost_round=1200)

4
抱歉回复晚了。我仍然收到以下警告信息: /home/dlin/.conda/envs/mybase/lib/python3.7/site-packages/lightgbm/basic.py:1279: 用户警告:覆盖参考数据集的参数。 warnings.warn('Overriding the parameters from Reference Dataset.') /home/dlin/.conda/envs/mybase/lib/python3.7/site-packages/lightgbm/basic.py:1091: 用户警告:param字典中的类别列已被覆盖。 warnings.warn('{} in param dict is overridden.'.format(cat_alias)) - David293836
我也有同感 - 我觉得现在在lightGBM中存在很多关于冗长的bug。 - CutePoison

0

这不是对原始OP的答案,而是针对使用sklearn API并遇到此问题的人的答案。 对于那些使用sklearn API的人,特别是使用sklearn中的cross_val方法之一的人,有两个解决方案可供考虑。

Sklearn API解决方案 对我有效的解决方案是将分类字段转换为pandas中的category数据类型。

如果您正在使用pandas df,则LightGBM应自动将其视为分类。从文档中可以看出:

在Python包中,将从pandas分类中提取整数代码

这应该相当于在Dataset对象中设置分类变量的sklearn API中的等效项。 但请记住,LightGBM并不正式支持sklearn API的任何非核心参数,他们明确地表示了这一点:

在sklearn中不支持**kwargs,可能会导致意外问题。

自适应解决方案 另一种更可靠的解决方法是创建自己的包装类,在底层实现核心数据集/训练,但暴露出适合cv方法的fit/predict接口。这样,您只需要编写少量代码就可以获得lightGBM的全部功能。

以下是此解决方案的示例。

class LGBMSKLWrapper:

    def __init__(self, categorical_variables, params):
        self.categorical_variables = categorical_variables
        self.params = params
        self.model = None

    def fit(self, X, y):
        my_dataset = ltb.Dataset(X, y, categorical_feature=self.categorical_variables)
        self.model = ltb.train(params=self.params, train_set=my_dataset)
    
    def predict(self, X):
        return self.model.predict(X)

上述代码允许您在创建对象时加载参数,然后在客户端调用“fit”时将其传递给训练。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接