【问题标题】:How to extract decision rules (features splits) from xgboost model in python3?如何从 python3 中的 xgboost 模型中提取决策规则(特征分割)?
【发布时间】:2018-10-14 23:58:23
【问题描述】:

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

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

我没有发现这个版本的模型有任何可以给我拆分的属性。

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

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

【问题讨论】:

    标签: python xgboost


    【解决方案1】:

    你需要知道你的树的名字,然后你可以把它插入到你的代码中。

    【讨论】:

      【解决方案2】:

      这是可能的,但并不容易。我建议您使用scikit-learn 中的GradientBoostingClassifier,它类似于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')]
      

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

      【讨论】:

      • 可能需要使用'\[f([0-9]+)&lt;([0-9]+.[0-9-e]+)\]' 正则表达式来获取科学记数法。我需要提取叶子值,并且需要进行此修改才能全部获取它们。
      • 我怎样才能知道每个特征 id 实际代表什么?就像f2 的实际用途是什么?
      • @JacquelineP.,特征的 id 只是 X 矩阵中相应列的序数。
      • 您也可以使用model.get_booster().get_dump() 而不是写入文件。
      • 还有model.get_booster().trees_to_dataframe(),它会给出更接近预期结果的东西。
      【解决方案3】:

      您可以通过函数model._Booster.trees_to_dataframe() 找到作为数据框的决策规则。 Yes 列包含 yes-branch 的 ID 和 no-branch 的 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)
      

      【讨论】:

        猜你喜欢
        • 2019-06-25
        • 2013-12-12
        • 2016-10-27
        • 2019-06-14
        • 2021-12-16
        相关资源
        最近更新 更多