如何在Pandas DataFrame中添加列展示Sklearn决策树分类规则路径?
实现每个样本的决策树规则路径追踪
当然有靠谱的实现思路!我之前做过类似的需求,核心就是利用Sklearn决策树的内部结构,手动追踪每个样本从根节点到叶子节点的决策路径,再把路径转换成你想要的规则字符串格式。下面是具体步骤和代码示例,亲测有效:
核心思路拆解
- 扒出决策树的内部结构:Sklearn的
DecisionTreeClassifier有个tree_属性,里面藏着所有节点的特征索引、阈值、子节点关系这些关键信息,这是我们追踪路径的基础。 - 写个循环函数追踪路径:对每个样本,从根节点出发,一步步判断走左子树还是右子树,同时把每一步的决策规则(比如
White=False)记录下来,直到走到叶子节点。 - 把规则批量应用到DataFrame:用Pandas的
apply方法,给每个样本生成对应的规则字符串,新增成一列就行。
代码示例
假设你已经训练好了决策树模型clf,并且有包含所有特征的DataFramedf,直接用下面的代码就能搞定:
import pandas as pd from sklearn.tree import DecisionTreeClassifier # 这里假设你已经完成了模型训练(替换成你自己的训练代码) # X = df[['White', 'Black', 'Weight', 'price']] # y = df['target'] # clf = DecisionTreeClassifier(max_depth=4) # 示例参数 # clf.fit(X, y) # 获取模型训练时用的特征名称 feature_names = clf.feature_names_in_ def get_sample_decision_path(row): current_node = 0 # 从根节点开始遍历 path_rules = [] tree_structure = clf.tree_ while True: # 判断当前节点是不是叶子节点,是就停止 if tree_structure.children_left[current_node] == -1 and tree_structure.children_right[current_node] == -1: break # 取出当前节点的特征和阈值 feature_idx = tree_structure.feature[current_node] feature_name = feature_names[feature_idx] threshold = tree_structure.threshold[current_node] sample_value = row[feature_name] # 根据特征类型生成规则,同时切换到子节点 if pd.api.types.is_bool_dtype(df[feature_name]): # 布尔型特征:Sklearn用-0.5做阈值,<= -0.5对应False,否则是True if sample_value <= threshold: path_rules.append(f"{feature_name}=False") current_node = tree_structure.children_left[current_node] else: path_rules.append(f"{feature_name}=True") current_node = tree_structure.children_right[current_node] else: # 数值型特征:直接用阈值比较 if sample_value <= threshold: path_rules.append(f"{feature_name}<={threshold:.1f}") current_node = tree_structure.children_left[current_node] else: path_rules.append(f"{feature_name}>{threshold:.1f}") current_node = tree_structure.children_right[current_node] # 把规则拼接成你要的格式 return '- ' + ', '.join(path_rules) # 给DataFrame新增决策路径列 df['decision_path'] = df.apply(get_sample_decision_path, axis=1)
注意事项
- 特征类型适配:代码里自动判断了布尔型和数值型特征,如果你有其他类型的特征(比如多分类),可以再扩展判断逻辑,比如检查特征是否是
category类型,然后对应生成特征=类别值的规则。 - 阈值格式调整:数值型特征的阈值我保留了1位小数,你可以根据自己的需求修改
:.1f的格式。 - 性能优化:如果你的DataFrame特别大,
apply可能有点慢,这时候可以考虑把函数改成向量化的形式,或者用swifter库加速apply操作。
内容的提问来源于stack exchange,提问作者Corentin Moreau
相关产品推荐
相关产品推荐

