微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Lightgbm 在同一数据集上的拆分方式不同一种热编码与一对其他拆分算法

如何解决Lightgbm 在同一数据集上的拆分方式不同一种热编码与一对其他拆分算法

在lightgbm上做小测试的时候,发现了一个我看不懂的案例。

我创建了一个带有分类列的小数据集:

import pandas as pd

X = pd.DataFrame(
    [
        [0,1,1],[2,2,0],[3,3,2],[0,-3,[1,2.5,5,-1.5,],columns=["col1","col2","col3"],)
X["col1"] = X["col1"].astype("category")
X["col3"] = X["col3"].astype("category")
y = pd.Series([0,1])

及其相关的一个热编码版本:

from sklearn.preprocessing import OneHotEncoder

feats_to_encode = ["col1","col3"]
enc = OneHotEncoder()
enc.fit(X[feats_to_encode])
X_one_hot_encoded = pd.DataFrame(
    enc.transform(X[feats_to_encode]).toarray(),columns=[
        feats_to_encode[feat_id] + str(cat)
        for feat_id in range(len(enc.categories_))
        for cat in enc.categories_[feat_id]
    ],)
X_one_hot_encoded["col2"] = X["col2"]

然后我用之前的数据集训练了 2 个 lightgbm 模型。我知道 lightgbm 使用特殊算法管理分类列。 “当一个特征的类别数小于或等于 max_cat_to_onehot 时,将使用一对一分割算法”(见 max_cat_to_onehot)。然后我会天真地期望,因为我的分类列的类别(4 和 3)比参数 max_cat_to_onehot 少,所以我会用两个数据集得到相同的结果,除非“一对一分割算法”不等价到一个热编码分类列。由于参数名称“max_cat_to_onehot”和算法“one-vs-other split algorithm”,我假设了这种行为。

from lightgbm import LGBMRegressor

params = {
    "n_estimators": 1,"max_depth": 2,"min_child_samples": 1,"importance_type": "gain","max_cat_to_onehot": 10,}

model = LGBMRegressor(**params)
model.fit(X,y)
print(model._Booster.dump_model()["tree_info"][0]["tree_structure"]["split_gain"]) # 0.30476200580596924

model = LGBMRegressor(**params)
model.fit(X_one_hot_encoded,y)
print(model._Booster.dump_model()["tree_info"][0]["tree_structure"]["split_gain"]) # 1.0666699409484863

两种型号的第一次拆分是不同的。第二个模型选择了可能的最佳分割,但第一个模型并非如此。

有人知道这是什么原因吗?我认为我对“一对一分割算法”行为的猜测是错误的。

解决方法

我更新了 lightgbm 版本,从 2.3.1 到 3.1.1。使用新版本,我得到了预期的结果。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。