训练好的“决策树”VS“决策路径”

Posted

技术标签:

【中文标题】训练好的“决策树”VS“决策路径”【英文标题】:Trained "Decision Tree" VS “Decision Path” 【发布时间】:2019-06-01 04:06:33 【问题描述】:

我正在使用 scikit“决策树”分类器来预测迁移项目的“工作量”。我的另一部分要求是找到影响预测的特征。

我训练了模型,得到了一个分层树,其中包含不同节点的所有特征。

我认为当我提供测试记录时,将使用同一棵树来预测大小。但令我惊讶的是,事实并非如此!!

预测后,我打印了 decision_path 以查看 “该预测中考虑的特征”

这个决策路径与模型构建的树完全不同。

如果树不用于预测,那么树有什么用。

我如何使用决策路径来获得该预测中的重要特征?

如果我导出这些规则集并使用它来查找决策路径,那会给我错误的特征或与决策路径的输出不匹配。

编辑 1

添加了通用代码。它给出了类似的输出。

from __future__ import print_function
import pandas as pd
import numpy as np

from sklearn import preprocessing
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn import tree
# Create tree object 
import graphviz
import pydotplus
import collections

file_path = "sample_data_generic.csv"
data = pd.read_csv( file_path )
data.head()

df = data.copy()
cols = df.columns
col_len = len(cols)
features_category = []

for col_index in range( col_len ):
    if df[ cols[col_index] ].dtype == 'object' or df[ cols[col_index] ].dtype == 'float64':
        df[ cols[col_index] ] = df[ cols[col_index] ].astype('category')
        features_category.append( cols[col_index] )

#redefining the variable value as it is throwing some error in the below lines due to the presence of next line char?!
features_category = ['Cloud Provider', 'OS Upgrade Path', 'Target_OS_NAME', 'Target_OS_VERSION', 'os_version']

# create dataframe for target variable
df_target = df['Size']
df.drop('Size', axis=1, inplace=True)

df = pd.get_dummies(df, columns=features_category, dtype='int')

df.head()

df_x_data = df.copy()
df_x_data.head()
y_data = df_target
target_classes = y_data.unique()
target_classes = target_classes.astype('category')
test_size_val = 0.3

x_train, x_test, y_train, y_test = train_test_split(df_x_data, y_data, test_size=test_size_val, random_state=1)


print("number of test samples :", x_test.shape[0])
print("number of training samples:",x_train.shape[0])

x_train.sort_values(['Comps'], ascending=[True]) #, 'Estimation'
model = tree.DecisionTreeClassifier()
model = model.fit(x_train, y_train)
model.score(x_test, y_test)
dot_data = tree.export_graphviz(model, out_file=None, 
                     feature_names=x_train.columns,  
                     class_names=target_classes,  
                     filled=True, rounded=True,  
                     special_characters=True)  
graph = pydotplus.graph_from_dot_data(dot_data)
print('graph: ', graph)
colors = ('white','red', 'green')

edges = collections.defaultdict(list)

for edge in graph.get_edge_list():
    edges[edge.get_source()].append(int(edge.get_destination()))
print( edges )
for edge in edges:
    edges[edge].sort()
    for i in range(2):
        dest = graph.get_node(str(edges[edge][i]))[0]
        dest.set_fillcolor(colors[i])
        
graph.write_png('decision_tree_2019_generic.png')

from IPython.display import Image
Image(filename = 'decision_tree_2019_generic.png')

to_predict = x_test[3:4]
model.predict( to_predict )

to_predict.values

applied = model.apply( to_predict )
applied

to_predict

decision_path = model.decision_path( to_predict )
print( decision_path.indices, '\n' )
print( decision_path[:1][:1])

predict_cols = decision_path.indices

predicted_row = to_predict
cols = predicted_row.columns
#print("len of cols: ", len(cols) )
for col in predict_cols:
    print( cols[col], predicted_row[ cols[col] ].values )

样本数据:是目前生成的数据。

Cloud Provider,Comps,env,hosts,OS Upgrade Path,Target_OS_NAME,Target_OS_VERSION,Size,os_version AWS,11,2,3833,不直接,Linux,4,M,2 谷歌云,16,6,4779,Direct,Mac,3,S,1 AWS,18,6,6677,Not Direct,Linux,7,S,8 谷歌云,34,2,1650,Direct,Windows,5,B,1 AWS,35,6,9569,Direct,Windows,6,M,3 AWS,36,6,7421,非直接,Windows,3,B,5 谷歌云,49,4,3469,Direct,Mac,6,B,1 AWS,54,5,5677,Direct,Mac,4,M,8

但是预测的测试数据的决策路径是: 比较 [206] --> 环境 [3] --> 主机 [637]

提前致谢

【问题讨论】:

请分享代码。 @Lukasz,有什么建议吗?谢谢 我做错了什么吗? 顺便说一句,你应该给测试数据打分吧?类似model.score(x_test, y_test). 好收获。你是对的,那是一个错误。我在我的代码中改变了它,在这里也一样。 【参考方案1】:

我认为您误解了decision_path 的返回值:它使用树内部表示的节点索引返回一个稀疏矩阵,指示预测通过树的哪些节点。这些并不意味着(实际上也不是)与数据集的列对齐。相反,如果您想访问与预测经过的节点相关的特征,请尝试:

predict_nodes = decision_path.indices
predicted_row = to_predict
cols = predicted_row.columns
for node in predict_nodes:
    col = model.tree_.feature[node]
    print( cols[col], predicted_row[ cols[col] ].values )

请注意,叶节点显然没有测试特征,并且(根据我的经验)返回特征索引的负值,所以也要注意这一点。

要了解有关树的内部结构的更多信息,请参阅 this 示例,并且(根据文档的建议)使用 help(sklearn.tree._tree.Tree)

【讨论】:

太棒了。是的,叶子节点名称不精确(重复) 一个问题:当我们有决策路径时,为什么我们需要导出树规则并使用它来找到相同的路径?在这种情况下,我们需要依赖它吗?你能澄清一下吗? 很高兴它有帮助!我不确定我是否理解您的问题,您指的是export_graphviz 方法吗?没有必要检查决策路径中涉及的特征(尽管它可以帮助直观地检查路径)。还是你指的是别的东西?

以上是关于训练好的“决策树”VS“决策路径”的主要内容,如果未能解决你的问题,请参考以下文章

如何从 scikit-learn 决策树中提取决策规则?

如何从 scikit-learn 决策树中提取决策规则?

如何从 scikit-learn 决策树中提取决策规则?

我如何从决策树中预测 x_train 的位置获取叶子的节点号?

使用sklearn python通过决策树提取数据点的规则路径

R语言使用party包中的ctree函数构建条件推理决策树(Conditional inference trees)使用plot函数可视化训练好的条件推理决策树条件推理决策树的叶子节点的阴影区域表