1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 __all__ = ['ScoringCDataset', 'ScoringClassifier', 'TLinearClassifier',
34 'AdditiveClassifier', 'Rejector', 'Shifter', 'train_Shifter', 'Resetter',
35 ]
36
37 from numpy import array, zeros, ones, concatenate
38 from cla import BinaryClassifier, CDataset
39 from dataset import WeightedCDataset
40 from thresh1d import thresh_1d
41
42
43
44
46 """A binary CDataset with score s[i] associated with sample i.
47 """
48
49 - def __init__(self, separated_input_data, separated_scores = None):
50 CDataset.__init__(self, separated_input_data)
51
52 if separated_scores is None:
53 self.scores = [zeros(x) for x in self.nspc]
54 else:
55 self.scores = separated_scores
56
58 """Make a copy of ScoringCDataset with a copy of scores and a reference to input_data.
59 """
60 return ScoringCDataset(self.input_data, [x.copy() for x in self.scores])
61
63 """Set all weight values to 'value', initialize if necessary
64 """
65 self.scores = [value*ones(x) for x in self.nspc]
66
70 dofilter.__doc__ = CDataset.dofilter.__doc__
71
72 - def concat(self, j, input_data, scores):
73 """Concatenate a few samples to class j.
74
75 :Parameters:
76 j : int
77 class j
78 input_data : an array of samples
79 new samples to be concatenated
80 scores : an array of scores
81 new scores to be concatenated
82 Output:
83 The class is updated.
84 """
85 CDataset.concat(self,j,input_data)
86 self.scores[j] = concatenate([self.scores[j], scores])
87
88
89
90
91
92
93
95 """Scoring Classifier
96
97 A BinaryClassifier that classifies based on scoring the current
98 input point. If the score is >= 0, the point is classified as class 1.
99 Otherwise, it is classified as class 0.
100 """
103
104 - def score(self, input_point, *args, **kwds):
105 """Return the score of an input point.
106
107 :Parameters:
108 input_point : a numpy.array
109 an input point
110
111 :Returns:
112 val : double
113 the input point's score
114 """
115 raise NotImplementedError, "Method score() has not been implemented."
116
117 - def scores(self, input_data, *args, **kwds):
118 """Return an array of scores of an input dataset.
119
120 :Parameters:
121 input_data : numpy.array
122 an array of input data
123
124 :Returns:
125 score_arr : numpy.array
126 an array of scores of the input data
127 """
128 return array([self.score(x, *args, **kwds) for x in input_data])
129
130 - def predict(self, input_point, *args, **kwds):
131 return int(self.score(input_point, *args, **kwds) >= 0)
132 predict.__doc__ = BinaryClassifier.predict.__doc__
133
134
135
136
137
138
140 """Thresholded linear classifier.
141 f(x) = w^T x - b
142 If f(x) >= 0 then return 1. Otherwise return 0.
143 w, b are parameters.
144 """
146 """Initialize the class.
147
148 :Parameters:
149 w : array of doubles
150 direction of projection, same dim with input point
151 b : double
152 thresholding value
153 """
154 ScoringClassifier.__init__(self)
155 self.w = w.ravel()
156 self.b = b
157
158 - def score(self, input_point, *args, **kwds):
159 return dot(self.w,input_point.ravel()) - self.b
160 score.__doc__ = ScoringClassifier.score.__doc__
161
162 - def test(self, input_data, *args, **kwds):
163 idata = input_data.reshape(len(input_data),input_data[0].size)
164 return (dot(idata,self.w).ravel() >= self.b).astype('int')
165 test.__doc__ = ScoringClassifier.test.__doc__
166
167
168
169
170
172 """Additive Classifier
173
174 A ScoringClassifier that adds a value to the score predicted by another
175 ScoringClassifier. The new score is supposed to give a better prediction
176 of the output class.
177 """
179 """Initialize the class.
180
181 :Parameters:
182 sc : ScoringClassifier
183 a ScoringClassifier to preceed this classifier,
184 or None if there's no classifier to preceed
185 """
186 ScoringClassifier.__init__(self)
187 self.sc = sc
188
190 """Return the input point's score from the preceeding classifier.
191
192 :Paramaters:
193 input_point : a numpy.array
194 an input point
195
196 :Returns:
197 score : double
198 the previous score of the input point
199 """
200 if self.sc is None:
201 return 0
202 else:
203 return self.sc.score(input_point, *args, **kwds)
204
205 - def score(self, input_point, *args, **kwds):
206 return self.preceeding_score(input_point, *args, **kwds)
207 score.__doc__ = ScoringClassifier.score.__doc__
208
209 - def predict(self, input_point, *args, **kwds):
210 try:
211 return int(self.score(input_point, *args, **kwds) >= 0)
212 except self.EarlyPrediction, ep:
213 return ep.output
214 predict.__doc__ = ScoringClassifier.predict.__doc__
215
216
217
218
219
236
237
238
239
240
242 """Shifter
243
244 An AdditiveClassifier that shifts (subtracts) the current score by a
245 threshold to adapt the new score towards a different goal.
246 """
248 """Initialize an Shifter.
249
250 :Parameters:
251 sc : ScoringClassifier
252 a ScoringClassifier to preceed this classifier,
253 or None if there's no classifier to preceed
254 thresh : double
255 a threshold value, default is 0
256 """
257 AdditiveClassifier.__init__(self, sc)
258 self.thresh = thresh
259
260 - def score(self, input_point, *args, **kwds):
262 score.__doc__ = AdditiveClassifier.score.__doc__
263
265 """Train a Shifter to succeed a ScoringClassifier with a different goal.
266
267 :Parameters:
268 scd : ScoringCDataset
269 a dataset of points and their current scores, obtained from
270 sc : ScoringClassifier
271 the current ScoringClassifier
272 criterion : integer from 0 to 3
273 0: minimize classification error with prior probabilities
274 1: minimize classification error without prior probabilities
275 2: minimize FAR while constraining FRR
276 3: minimize FRR while constraining FAR
277 param1 : double
278 a parameter representing
279 \lambda if criterion < 2
280 maxFRR if criterion == 2
281 maxFAR if criterion == 3
282
283 :Returns:
284 shifter : Shifter
285 a Shifter succeeding the current ScoringClassifier 'sc'
286 shifter.err : double
287 resulting function value after thresholding
288 scd2 : ScoringCDataset
289 a new ScoringCDataset shifted (subtracted) from scd by
290 shifter.thresh
291 """
292 z = thresh_1d(criterion, param1, WeightedCDataset(scd.scores))
293
294
295 shifter = Shifter(sc, float(z[0]))
296 shifter.err = float(z[1])
297
298
299 new_scores = [x - shifter.thresh for x in scd.scores]
300 scd2 = ScoringCDataset(scd.input_data, new_scores)
301
302 return shifter, shifter.err, scd2
303
304
305
306
307
309 """An AdditiveClassifier that resets the score to a predefined value."""
311 """Initialize a Resetter.
312
313 :Parameters:
314 sc : ScoringClassifier
315 a ScoringClassifier to preceed this classifier,
316 or None if there's no classifier to preceed
317 value : double
318 a resetting value, default is 0
319 """
320 AdditiveClassifier.__init__(self, sc)
321 self.value = value
322
323 - def score(self, input_point, *args, **kwds):
327 score.__doc__ = AdditiveClassifier.score.__doc__
328