1
2
3
4
5 """ functionality for generating an image showing the results of a composite model voting on a data set
6
7 Uses *Numeric* and *PIL*
8
9 """
10
11 from Numeric import *
12 from PIL import Image, ImageDraw
13
15 """ collects the votes from _composite_ for the examples in _data_
16
17 **Arguments**
18
19 - composite: a composite model
20
21 - data: a list of examples to run through _composite_
22
23 - badOnly: if set only bad (misclassified) examples will be kept
24
25 **Returns**
26
27 a 4-tuple containing:
28
29 1) the expanded list of vote details (see below)
30
31 2) the list of predicted results
32
33 3) the list of true results
34
35 4) the number of miscounted examples
36
37
38 **Notes**
39
40 pp - the expanded list of vote details consists of:
41
42 '[ vote1, vote2, ... voteN, 0, res, trueRes]'
43
44 where _res_ is the predicted results and _trueRes_ is the actual result.
45 The extra zero is included to allow a line to be drawn between the votes
46 and the results.
47
48 """
49 res = []
50 values = []
51 trueValues = []
52 misCount = 0
53 for pt in data:
54 val,err = composite.ClassifyExample(pt)
55 predict = pt[-1]
56 if not badOnly or val != predict:
57 values.append(val)
58 trueValues.append(predict)
59 if val != predict:
60 misCount = misCount + 1
61 res.append(composite.GetVoteDetails()+[0,val,pt[-1]])
62 return res,values,trueValues,misCount
63
64 -def BuildVoteImage(nModels,data,values,trueValues=[],
65 sortTrueVals=0,xScale=10,yScale=2,
66 addLine=1):
67 """ constructs the actual image
68
69 **Arguments**
70
71 - nModels: the number of models in the composite
72
73 - data: the results of voting
74
75 - values: predicted values for each example
76
77 - trueValues: true values for each example
78
79 - sortTrueVals: if nonzero the votes will be sorted so
80 that the _trueValues_ are in order, otherwise the sort
81 is by _values_
82
83 - xScale: number of pixels per vote in the x direction
84
85 - yScale: number of pixels per example in the y direction
86
87 - addLine: if nonzero, a purple line is drawn separating
88 the votes from the examples
89
90 **Returns**
91
92 a PIL image
93
94 """
95 nData = len(data)
96 data = array(data,Int)
97 if sortTrueVals and trueValues != []:
98 order = argsort(trueValues)
99 else:
100 order = argsort(values)
101 data = take(data,order)
102 maxVal = max(ravel(data))
103 data = data * 255 / maxVal
104 img = Image.fromstring('L',(nModels,nData),data.astype('b').tostring())
105
106 if addLine:
107 img = img.convert('RGB')
108 canvas = ImageDraw.Draw(img)
109 if trueValues != []:
110 canvas.line([(nModels-3,0),(nModels-3,nData)],fill=(128,0,128))
111 else:
112 canvas.line([(nModels-2,0),(nModels-2,nData)],fill=(128,0,128))
113 img = img.resize((nModels*xScale,nData*yScale))
114 return img
115
116
117 -def VoteAndBuildImage(composite,data,badOnly=0,sortTrueVals=0,
118 xScale=10,yScale=2,addLine=1):
119 """ collects votes on the examples and constructs an image
120
121 **Arguments**
122
123 - composte: a composite model
124
125 - data: the examples to be voted upon
126
127 - badOnly: if nonzero only the incorrect votes will be shown
128
129 - sortTrueVals: if nonzero the votes will be sorted so
130 that the _trueValues_ are in order, otherwise the sort
131 is by _values_
132
133 - xScale: number of pixels per vote in the x direction
134
135 - yScale: number of pixels per example in the y direction
136
137 - addLine: if nonzero, a purple line is drawn separating
138 the votes from the examples
139
140 **Returns**
141
142 a PIL image
143
144
145 """
146 nModels = len(composite)+3
147 print 'nModels:',nModels-3
148
149 res,values,trueValues,misCount = CollectVotes(composite,data,badOnly)
150 print '%d examples were misclassified'%misCount
151 img = BuildVoteImage(nModels,res,values,trueValues,sortTrueVals,
152 xScale,yScale,addLine)
153 return img
154
156 """ provides a list of arguments for when this is used from the command line
157
158 """
159 import sys
160
161 print 'Usage: VoteImg.py [optional arguments] <modelfile.pkl> <datafile.qdat>'
162 print 'Optional Arguments:'
163 print '\t-o outfilename: the name of the output image file.'
164 print '\t The extension determines the type of image saved.'
165 print '\t-b: only include bad (misclassified) examples'
166 print '\t-t: sort the results by the true (input) classification'
167 print '\t-x scale: scale the image along the x axis (default: 10)'
168 print '\t-y scale: scale the image along the y axis (default: 2)'
169 print '\t-d databasename: instead of using a qdat file, pull the data from'
170 print '\t a database. In this case the filename argument'
171 print '\t is used to indicate the name of the table in the database.'
172
173 sys.exit(-1)
174
175 if __name__ == '__main__':
176 import sys,getopt
177 import cPickle
178 from ML.Data import DataUtils
179
180 args,extra = getopt.getopt(sys.argv[1:],'o:bthx:y:d:')
181 if len(extra) < 2:
182 Usage()
183 badOnly = 0
184 sortTrueVals = 0
185 xScale=10
186 yScale=2
187 dbName = ''
188 outFileName='foo.png'
189 for arg,val in args:
190 if arg == '-b':
191 badOnly = 1
192 elif arg == '-t':
193 sortTrueVals = 1
194 elif arg == '-o':
195 outFileName = val
196 elif arg == '-x':
197 xScale = int(val)
198 elif arg == '-y':
199 yScale = int(val)
200 elif arg == '-d':
201 dbName = val
202 elif arg == '-h':
203 Usage()
204 else:
205 Usage()
206 modelFile=open(extra[0],'rb')
207 model = cPickle.load(modelFile)
208
209 fName= extra[1]
210 if dbName == '':
211 data = DataUtils.BuildQuantDataSet(fName)
212 else:
213 data = DataUtils.DBToQuantData(dbName,fName)
214
215 dataSet = data.GetNamedData()
216
217 img = VoteAndBuildImage(model,dataSet,badOnly=badOnly,sortTrueVals=sortTrueVals,
218 xScale=xScale,yScale=yScale)
219 img.save(outFileName)
220