47

My code is follow the class of machine learning of google.The two code are same.I don't know why it show error.May be the type of variable is error.But google's code is same to me.Who has ever had this problem?

This is error

[0 1 2]
[0 1 2]
Traceback (most recent call last):
  File "/media/joyce/oreo/python/machine_learn/VisualizingADecisionTree.py", line 34, in <module>
    graph.write_pdf("iris.pdf")
AttributeError: 'list' object has no attribute 'write_pdf'
[Finished in 0.4s with exit code 1]
[shell_cmd: python -u "/media/joyce/oreo/python/machine_learn/VisualizingADecisionTree.py"]
[dir: /media/joyce/oreo/python/machine_learn]
[path: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games]

This is code

import numpy as np
from sklearn.datasets import load_iris
from sklearn import tree

iris = load_iris()
test_idx = [0, 50, 100]

# training data
train_target = np.delete(iris.target, test_idx)
train_data = np.delete(iris.data, test_idx, axis=0)

# testing data
test_target = iris.target[test_idx]
test_data = iris.data[test_idx]

clf = tree.DecisionTreeClassifier()
clf.fit(train_data, train_target)

print test_target
print clf.predict(test_data) 

# viz code
from sklearn.externals.six import StringIO
import pydot
dot_data = StringIO()
tree.export_graphviz(clf,
        out_file=dot_data,
        feature_names=iris.feature_names,
        class_names=iris.target_names,
        filled=True, rounded=True,
        impurity=False)

graph = pydot.graph_from_dot_data(dot_data.getvalue())
graph.write_pdf("iris.pdf")
Simd
  • 19,447
  • 42
  • 136
  • 271
乔守卿
  • 583
  • 1
  • 4
  • 8

10 Answers10

70

I think you are using newer version of python. Please try with pydotplus.

import pydotplus
...
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_pdf("iris.pdf")

This should do it.

avellable
  • 1,365
  • 3
  • 13
  • 17
  • 3
    I just had a look.The graph is a list and it contain a pydot.Dot object.I use the pydot.Dot object call the function write_pdf("iris.pdf"),it also solve the question. – 乔守卿 Jul 04 '16 at 05:36
  • @乔守卿 What syntax did you use / how did you use pydot.Dot? – programmer Jul 14 '16 at 15:53
  • 2
    @programmer The length of this list is actually 1. So, just `graph[0].write_pdf`. BTW, I guess the reason it returns a list is that there might be multiple trees in a single dot file. – Weizhou He Jul 31 '16 at 06:36
  • I could only install with `pip install pydotplus`, not with `conda install pydotplus` which caused `InvalidArchiveError('Error with archive C:\\Users\\Admin\\Anaconda3\\pkgs\\openssl-1.1.1d-he774522_2xysboxfd\\pkg-openssl-1.1.1d-he774522_2.tar.zst. You probably need to delete and re-download or re-create this file. Message from libarchive was:\n\nCould not unlink')` – questionto42 May 20 '20 at 09:54
30

pydot.graph_from_dot_data() returns a list, so try:

graph = pydot.graph_from_dot_data(dot_data.getvalue())
graph[0].write_pdf("iris.pdf") 
Iliyan Bobev
  • 3,070
  • 2
  • 20
  • 24
  • 1
    Thanks for the answer. Simple enough solution without having to go through the hassle of pydotplus – maheeka Jun 18 '17 at 15:45
5

I had exactly the same issue. Turned out that I hadn't installed graphviz. Once i did that it started to work.

Deepak Rao
  • 611
  • 8
  • 5
1

@Alex Sokolov, for my case in window, i downloaded and install / unzip the following to a folder then setup the PATH in Windows environment variables. re-run the py code works for me. hope is helpful to you.

Jai
  • 83
  • 7
0

I install scikit-learn via conda and all of about not work. Firstly, I have to install libtool

brew install libtool --universal

Then I follow this sklearn guide Then change the python file to this code

clf = clf.fit(train_data, train_target)
tree.export_graphviz(clf,out_file='tree.dot') 

Finally convert to png in terminal

dot -Tpng tree.dot -o tree.png
LE SANG
  • 10,955
  • 7
  • 59
  • 78
0

I tried the previous answers and still got a error when running the script Therefore, I just used pydotplus

import pydotplus

and install the "graphviz" by using:

sudo apt-get install graphviz

Then it worked for me, and I added

graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_pdf("iris.pdf")

Thanks to the previous contributors.

0

It works as the following on Python3.7 but don't forget to install pydot using Anaconda prompt:

   from sklearn.externals.six import StringIO
   import pydot

   # viz code
   dot_data = StringIO()
   tree.export_graphviz(clf, out_file=dot_data, feature_names=iris.feature_names,
                 class_names=iris.target_names, filled=True, rounded=True,
                 impurity=False)
   graph = pydot.graph_from_dot_data(dot_data.getvalue())
   graph[0].write_pdf('iris.pdf')
0

I use Anaconda. Here's what worked for me: run from terminal:

conda install python-graphviz
conda install pydot     ## don't forget this <-----------------

Then run

clf = clf.fit(train_data, train_target)
tree.export_graphviz(clf,out_file='tree.dot')

Then from the terminal:

dot -Tpng tree.dot -o tree.png
Martin
  • 1
  • 1
0

To add all graphs for the number of your n_estimators you can do:

for i in range(0, n):  #n is your n_estimators number
    dot_data = StringIO()
    tree.export_graphviz(clf.estimators_[i], out_file=dot_data, feature_names=iris.feature_names,
                        class_names=iris.target_names, filled=True, rounded=True,
                        impurity=False)
    graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
    graph.write_pdf("iris%s.pdf"%i)

you could also switch the line

graph = pydotplus.graph_from_dot_data(dot_data.getvalue())

for this one

(graph,) = pydot.graph_from_dot_data(dot_data.getvalue())
graph.write_pdf("iris.pdf")

and it would still work.

Shayki Abramczyk
  • 36,824
  • 16
  • 89
  • 114
-1

I hope this helps, I was having a similar issue. I decided not to use pydot / pydotplus, but rather graphviz. I modified (barely) the code and it works wonders! :)

# 2. Train classifier
# Testing Data
# Examples used to "test" the classifier's accuracy
# Not part of the training data
import numpy as np
from sklearn.datasets import load_iris
from sklearn import tree
iris = load_iris()
test_idx = [0, 50, 100] # Grabs one example of each flower for testing data (in the data set it so happens to be that
                        # each flower begins at 0, 50, and 100

# training data
train_target = np.delete(iris.target, test_idx)     # Delete all but 3 for training target data
train_data = np.delete(iris.data, test_idx, axis=0) # Delete all but 3 for training data

# testing data
test_target = iris.target[test_idx] # Get testing target data
test_data = iris.data[test_idx]     # Get testing data

# create decision tree classifier and train in it on the testing data
clf = tree.DecisionTreeClassifier()
clf.fit(train_data, train_target)

# Predict label for new flower
print(test_target)
print(clf.predict(test_data))

# Visualize the tree
from sklearn.externals.six import StringIO
import graphviz
dot_data = StringIO()
tree.export_graphviz(clf,
        out_file=dot_data,
        feature_names=iris.feature_names,
        class_names=iris.target_names,
        filled=True, rounded=True,
        impurity=False)
graph = graphviz.Source(dot_data.getvalue())
graph.render("iris.pdf", view=True)