Package pycv :: Package cs :: Package ml :: Package cla :: Module score
[hide private]
[frames] | no frames]

Source Code for Module pycv.cs.ml.cla.score

  1  # PyCV - A Computer Vision Package for Python Incorporating Fast Training of Face Detection 
  2   
  3  # Copyright 2007 Nanyang Technological University, Singapore. 
  4  # Authors: Minh-Tri Pham, Viet-Dung D. Hoang, and Tat-Jen Cham. 
  5   
  6  # This file is part of PyCV. 
  7   
  8  # PyCV is free software: you can redistribute it and/or modify 
  9  # it under the terms of the GNU General Public  
 10  # License as published by the Free Software Foundation, either version  
 11  # 3 of the License, or (at your option) any later version. 
 12   
 13  # PyCV is distributed in the hope that it will be useful, 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  # GNU General Public License for more details. 
 17   
 18  # You should have received a copy of the GNU General Public License 
 19  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 20   
 21  # --------------------------------------------------------------------- 
 22  #!/usr/bin/env python 
 23   
 24   
 25  #------------------------------------------------------------------------------- 
 26  # Scoring Binary Classifiers 
 27  # 
 28  # Binary Classifiers that classify based on scoring the current  
 29  # input point. If the score is >= 0, the point is classified as class 1. 
 30  # Otherwise, it is classified as class 0. 
 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  # Scoring Dataset 
 44  #------------------------------------------------------------------------------- 
45 -class ScoringCDataset(CDataset):
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
57 - def new(self):
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
62 - def set_scores(self,value=0):
63 """Set all weight values to 'value', initialize if necessary 64 """ 65 self.scores = [value*ones(x) for x in self.nspc]
66
67 - def dofilter(self, j, filterarray):
68 self.scores[j] = self.scores[j][filterarray] 69 return CDataset.dofilter(self, j, filterarray)
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 # Scoring Classifier 93 #-------------------------------------------------------------------------------
94 -class ScoringClassifier(BinaryClassifier):
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 """
101 - def __init__(self):
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 # Linear Binary Classifiers 137 #------------------------------------------------------------------------------- 138
139 -class TLinearClassifier(ScoringClassifier):
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 """
145 - def __init__(self, w, b):
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 # Additive Classifier 170 #-------------------------------------------------------------------------------
171 -class AdditiveClassifier(ScoringClassifier):
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 """
178 - def __init__(self, sc=None):
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
189 - def preceeding_score(self, input_point, *args, **kwds):
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): # no change of score
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 # Rejector 219 #-------------------------------------------------------------------------------
220 -class Rejector(AdditiveClassifier):
221 """Rejector 222 223 An AdditiveClassifier does nothing but raises an EarlyPrediction exception 224 if the current score falls below 0. 225 """
226 - def __init__(self, sc=None):
228 __init__.__doc__ = AdditiveClassifier.__init__.__doc__ 229
230 - def score(self, input_point, *args, **kwds):
231 sc = self.preceeding_score(input_point, *args, **kwds) 232 if sc < 0: # raise EarlyPrediction if score falls below 0 233 raise self.EarlyPrediction(0, score=sc) 234 return sc # or return the current score
235 score.__doc__ = AdditiveClassifier.score.__doc__
236 237 238 #------------------------------------------------------------------------------- 239 # Shifter 240 #-------------------------------------------------------------------------------
241 -class Shifter(AdditiveClassifier):
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 """
247 - def __init__(self, sc=None, thresh=0):
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):
261 return self.preceeding_score(input_point, *args, **kwds) - self.thresh
262 score.__doc__ = AdditiveClassifier.score.__doc__
263
264 -def train_Shifter(scd, sc, criterion, param1):
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 # create shifter 295 shifter = Shifter(sc, float(z[0])) 296 shifter.err = float(z[1]) 297 298 # shift scores 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 # Resetter 307 #-------------------------------------------------------------------------------
308 -class Resetter(AdditiveClassifier):
309 """An AdditiveClassifier that resets the score to a predefined value."""
310 - def __init__(self, sc=None, value=0):
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):
324 # call preceeding_score() to make sure EarlyPrediction exceptions can be raised 325 self.preceeding_score(input_point, *args, **kwds) 326 return self.value
327 score.__doc__ = AdditiveClassifier.score.__doc__
328