使用pydot绘制决策树
我训练了一个决策树
(用Python字典表示),现在我想用pydot来绘制它。在定义树的每个节点(pydot图)时,我给它们指定了一个独特且详细的名称和一个简短的标签。
我的问题是,当我把结果保存为.png文件时,看到的却是详细的节点名称
,而不是节点标签
。
我按照@Martijn Pieters的回答这里的指示操作,但我不知道我漏掉了什么,有没有什么建议?
import pydot
tree= {'salary': {'41k-45k': 'junior', '46k-50k': {'department': {'marketing': 'senior', 'sales': 'senior', 'systems': 'junior'}}, '36k-40k': 'senior', '26k-30k': 'junior', '31k-35k': 'junior', '66k-70k': 'senior'}}
def walk_dictionaryv2(graph, dictionary, parent_node=None):
'''
Recursive plotting function for the decision tree stored as a dictionary
'''
for k in dictionary.keys():
if parent_node is not None:
from_name = parent_node.get_name().replace("\"", "") + '_' + str(k)
from_label = str(k)
node_from = pydot.Node(from_name, label=from_label)
graph.add_edge( pydot.Edge(parent_node, node_from) )
if isinstance(dictionary[k], dict): # if interim node
walk_dictionaryv2(graph, dictionary[k], node_from)
else: # if leaf node
to_name = str(k) + '_' + str(dictionary[k]) # unique name
to_label = str(dictionary[k])
node_to = pydot.Node(to_name, label=to_label, shape='box')
graph.add_edge(pydot.Edge(node_from, node_to))
#node_from.set_name(to_name)
else:
from_name = str(k)
from_label = str(k)
node_from = pydot.Node(from_name, label=from_label)
walk_dictionaryv2(graph, dictionary[k], node_from)
def plot_tree(tree, name):
# first you create a new graph, you do that with pydot.Dot()
graph = pydot.Dot(graph_type='graph')
walk_dictionaryv2(graph, tree)
graph.write_png(name+'.png')
plot_tree(tree,'name')
这是我用上面的代码得到的(不想要的)输出:
2 个回答
3
如果有人想要一个使用边缘标签的版本(这是一种传统的显示决策树的方式)
import pydot
import uuid
def generate_unique_node():
""" Generate a unique node label."""
return str(uuid.uuid1())
def create_node(graph, label, shape='oval'):
node = pydot.Node(generate_unique_node(), label=label, shape=shape)
graph.add_node(node)
return node
def create_edge(graph, node_parent, node_child, label):
link = pydot.Edge(node_parent, node_child, label=label)
graph.add_edge(link)
return link
def walk_tree(graph, dictionary, prev_node=None):
""" Recursive construction of a decision tree stored as a dictionary """
for parent, child in dictionary.items():
# root
if not prev_node:
root = create_node(graph, parent)
walk_tree(graph, child, root)
continue
# node
if isinstance(child, dict):
for p, c in child.items():
n = create_node(graph, p)
create_edge(graph, prev_node, n, str(parent))
walk_tree(graph, c, n)
# leaf
else:
leaf = create_node(graph, str(child), shape='box')
create_edge(graph, prev_node, leaf, str(parent))
def plot_tree(dictionary, filename="DecisionTree.png"):
graph = pydot.Dot(graph_type='graph')
walk_tree(graph, tree)
graph.write_png(filename)
tree = {'salary': {'41k-45k': 'junior', '46k-50k': {'department': {'marketing': 'senior', 'sales': 'senior', 'systems': 'junior'}}, '36k-40k': 'senior', '26k-30k': 'junior', '31k-35k': 'junior', '66k-70k': 'senior'}}
plot_tree(tree)
4
你需要明确地把你创建的节点添加到图中:
node_from = pydot.Node(from_name, label=from_label)
graph.add_node(node_from)
还有
node_to = pydot.Node(to_name, label=to_label, shape='box')
graph.add_node(node_to)
否则渲染器就看不到这些名字。graph.add_node()
会把节点的相关信息包含在生成的 .dot
文件里。
加上这些 graph.add_node()
的代码后,结果就是: