我的 LightGBM 模型中实际上有多少棵树?

问题描述 投票:0回答:1

我的代码看起来像这样

clf = lgb.LGBMClassifier(max_depth=3, verbosity=-1, n_estimators=3)
clf.fit(train_data[features], train_data['y'], sample_weight=train_data['weight'])
print (f"I have {clf.n_estimators_} estimators")
fig, ax = plt.subplots(nrows=4, figsize=(50,36), sharex=True)
lgb.plot_tree(clf, tree_index=7, dpi=600, ax=ax[0]) # why does it have 7th tree?
lgb.plot_tree(clf, tree_index=8, dpi=600, ax=ax[1]) # why does it have 8th tree?
#lgb.plot_tree(clf, tree_index=9, dpi=600, ax=ax[2]) # crashes
#lgb.plot_tree(clf, tree_index=10, dpi=600, ax=ax[3]) # crashes

我很惊讶,尽管

n_estimators=3
,我似乎有9棵树?我实际上如何设置树的数量,与此相关的是,
n_estimators
有什么作用?我读过文档,我以为是树的数量,但似乎是别的东西。

另外,我如何解释单独的树及其顺序 0、1、2 等。我了解随机森林,以及每棵树如何同等重要。在 boosting 中,第一棵树最重要,下一棵树的重要性要低得多,下一棵树的重要性要低得多。那么在我的脑海中,当我查看树形图时,我该如何“模拟”LightGBM 推理过程?

python machine-learning lightgbm boosting
1个回答
0
投票

我实际上如何设置树的数量,与此相关的是,n_estimators 是做什么的?

传递

n_estimators
或其别名之一(LightGBM 文档)。

LightGBM 的

n_estimators

 界面中的 
scikit-learn
(类似
LGBMClassifier
的类)控制增强轮数

对于多类分类以外的所有任务,LightGBM 将在每个 boosting 轮生成 1 棵树。

对于多类分类,LightGBM 将在每个 boosting 轮中训练 1 棵树每个类

因此,例如,如果您的目标有 5 个类别,那么使用

n_estimators=3
进行训练并且不提前停止将产生 15 棵树。

如何解释单独的树及其顺序 0、1、2 等...如何“模拟”LightGBM 推理过程?

每个连续的

{num_classes}
树分组对应于一轮助推轮。它们按目标类别排序。

给定输入

X
,LightGBM 预测
X
属于类
i
将由以下公式给出:

tree_{i}(X) +
tree_{i+num_classes}(X) +
tree_{i+num_classes*2}(X)
... etc/, etc.

例如,考虑使用 LightGBM 的内置多类目标进行 5 类多类分类和 3 轮提升。

属于第一类的样本

x
的LightGBM得分将是第1、6和11棵树的相应叶子值的总和。

这是一个最小的、可重现的示例,使用

lightgbm==4.3.0
和 Python 3.11。

import lightgbm as lgb
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs

# generate multiclass dataset with 5 classes
X, y = make_blobs(n_samples=1_000, centers=5, random_state=773)

# fit a small multiclass classification model
clf = lgb.LGBMClassifier(n_estimators=3, num_leaves=4, seed=708)
clf.fit(X, y)

# underlying model has 15 trees
clf.booster_.num_trees()
# 15

# but just 3 iterations (boosting rounds)
clf.n_iter_
# 3

# just plot the trees for the first class
lgb.plot_tree(clf, tree_index=0)
lgb.plot_tree(clf, tree_index=5)
lgb.plot_tree(clf, tree_index=10)
plt.show()

这将生成如下所示的树形图:

enter image description here

尝试为训练数据的第一行生成原始预测。

clf.predict(X, raw_score=True)[0,]
# array([-1.24209749, -1.90204682, -1.9020346 , -1.89711144, -1.23250193])

您可以手动计算该样本在每棵树中属于哪个叶节点并添加这些叶值。该数字应与上面原始分数中的第一项匹配(在本例中为

-1.24209749
)。

如果您有

pandas
可用,您可能会发现将树结构转储到数据框并在那里使用它会更容易。

model_df = clf.booster_.trees_to_dataframe()

# trees relevant to class 0
relevant_trees = [0, 5, 10]

# figure out which leaf index each sample falls into
leaf_preds = clf.predict(X, pred_leaf=True)[0,]

# subset that to only the trees relevant to class 0
relevant_leaf_ids = [
    f"0-L{leaf_preds[0]}",
    f"5-L{leaf_preds[5]}",
    f"10-L{leaf_preds[10]}"
]

# show the values LightGBM would predict from each tree
model_df[
  model_df["tree_index"].isin(relevant_trees) &
  model_df["node_index"].isin(relevant_leaf_ids)
][["tree_index", "node_index", "value"]]
    tree_index node_index     value
5            0       0-L3 -1.460720
38           5       5-L3  0.119902
73          10      10-L3  0.098720       

这 3 个值相加到

-1.242098
,几乎与
clf.predict(X, raw_score=True)
预测的分数相同(只是打印时丢失的数字精度不同)

© www.soinside.com 2019 - 2024. All rights reserved.