如何从python3中的xgboost模型中提取决策规则(特征拆分)?

时间:2018-05-04 13:15:27

标签: python xgboost

我需要从python中的拟合xgboost模型中提取决策规则。我使用0.6a2版本的xgboost库,我的python版本是3.5.2。

我的最终目标是使用这些拆分来区分变量(根据拆分)。

我没有遇到这个版本的模型的任何属性,它可以给我分裂。

plot_tree给了我类似的东西。然而,它是树的可视化。

对于xgboost模型我需要https://stackoverflow.com/a/39772170/4559070之类的东西

3 个答案:

答案 0 :(得分:7)

这是可能的,但并不容易。我建议您使用GradientBoostingClassifier中的scikit-learn,它与xgboost类似,但可以对构建的树进行本机访问。

然而,使用xgboost,可以获得模型的文本表示,然后解析它:

from sklearn.datasets import load_iris
from xgboost import XGBClassifier
# build a very simple model
X, y = load_iris(return_X_y=True)
model = XGBClassifier(max_depth=2, n_estimators=2)
model.fit(X, y);
# dump it to a text file
model.get_booster().dump_model('xgb_model.txt', with_stats=True)
# read the contents of the file
with open('xgb_model.txt', 'r') as f:
    txt_model = f.read()
print(txt_model)

它将打印出6棵树的文本描述(2个估算器,每个由3棵树组成,每个类别一个),从这样开始:

booster[0]:
0:[f2<2.45] yes=1,no=2,missing=1,gain=72.2968,cover=66.6667
    1:leaf=0.143541,cover=22.2222
    2:leaf=-0.0733496,cover=44.4444
booster[1]:
0:[f2<2.45] yes=1,no=2,missing=1,gain=18.0742,cover=66.6667
    1:leaf=-0.0717703,cover=22.2222
    2:[f3<1.75] yes=3,no=4,missing=3,gain=41.9078,cover=44.4444
        3:leaf=0.124,cover=24
        4:leaf=-0.0668394,cover=20.4444
...

现在,您可以从此说明中提取所有拆分:

import re
# trying to extract all patterns like "[f2<2.45]"
splits = re.findall('\[f([0-9]+)<([0-9]+.[0-9]+)\]', txt_model)
splits

它将打印元组列表(feature_id,split_value),如

[('2', '2.45'),
 ('2', '2.45'),
 ('3', '1.75'),
 ('3', '1.65'),
 ('2', '4.95'),
 ('2', '2.45'),
 ('2', '2.45'),
 ('3', '1.75'),
 ('3', '1.65'),
 ('2', '4.95')]

您可以根据需要进一步处理此列表。

答案 1 :(得分:0)

您可以通过函数model._Booster.trees_to_dataframe()在数据框中找到决策规则。 Yes列包含yes分支的ID和no分支的No列。这样,您就可以重构树,因为对于数据帧的每一行,节点ID的边都指向YesNo。您可以这样使用networkx来做到这一点:

import networkx as nx

df = model._Booster.trees_to_dataframe()

# Create graph
G = nx.Graph()
# Add all the nodes
G.add_nodes_from(df.ID.tolist())
# Add the edges. This should be simpler in Pandas, but there seems to be a bug with df.apply(tuple, axis=1) at the moment.
yes_pairs = df[['ID', 'Yes']].dropna()
no_pairs = df[['ID', 'No']].dropna()
yes_edges = [tuple([i[0], i[1]]) for i in yes_pairs.values]
no_edges = [tuple([i[0], i[1]]) for i in no_pairs.values]
G.add_edges_from(yes_edges + no_edges)

答案 2 :(得分:-4)

您需要知道树的名称,之后,您可以将其插入代码中。