28 AdaBoost::AdaBoost(
const WeakClassifier &weakClassifier,
bool useScaling,
bool useNullRejection,Float nullRejectionCoeff,UINT numBoostingIterations,UINT predictionMethod)
31 this->useScaling = useScaling;
32 this->useNullRejection = useNullRejection;
33 this->nullRejectionCoeff = nullRejectionCoeff;
34 this->numBoostingIterations = numBoostingIterations;
35 this->predictionMethod = predictionMethod;
36 classType =
"AdaBoost";
37 classifierType = classType;
38 classifierMode = STANDARD_CLASSIFIER_MODE;
39 debugLog.setProceedingText(
"[DEBUG AdaBoost]");
40 errorLog.setProceedingText(
"[ERROR AdaBoost]");
41 trainingLog.setProceedingText(
"[TRAINING AdaBoost]");
42 warningLog.setProceedingText(
"[WARNING AdaBoost]");
46 classifierType =
"AdaBoost";
47 classifierMode = STANDARD_CLASSIFIER_MODE;
48 debugLog.setProceedingText(
"[DEBUG AdaBoost]");
49 errorLog.setProceedingText(
"[ERROR AdaBoost]");
50 trainingLog.setProceedingText(
"[TRAINING AdaBoost]");
51 warningLog.setProceedingText(
"[WARNING AdaBoost]");
66 this->numBoostingIterations = rhs.numBoostingIterations;
67 this->predictionMethod = rhs.predictionMethod;
68 this->models = rhs.models;
70 if( rhs.weakClassifiers.size() > 0 ){
71 for(UINT i=0; i<rhs.weakClassifiers.size(); i++){
72 WeakClassifier *weakClassiferPtr = rhs.weakClassifiers[i]->createNewInstance();
73 weakClassifiers.push_back( weakClassiferPtr );
85 if( classifier == NULL ){
86 errorLog <<
"deepCopyFrom(const Classifier *classifier) - The classifier pointer is NULL!" << std::endl;
97 this->numBoostingIterations = ptr->numBoostingIterations;
98 this->predictionMethod = ptr->predictionMethod;
99 this->models = ptr->models;
101 if( ptr->weakClassifiers.size() > 0 ){
102 for(UINT i=0; i<ptr->weakClassifiers.size(); i++){
103 WeakClassifier *weakClassiferPtr = ptr->weakClassifiers[i]->createNewInstance();
104 weakClassifiers.push_back( weakClassiferPtr );
120 errorLog <<
"train_(ClassificationData &trainingData) - There are not enough training samples to train a model! Number of samples: " << trainingData.
getNumSamples() << std::endl;
128 const UINT NEGATIVE_LABEL = WEAK_CLASSIFIER_NEGATIVE_CLASS_LABEL;
130 const Float beta = 0.001;
132 TrainingResult trainingResult;
134 const UINT K = (UINT)weakClassifiers.size();
136 errorLog <<
"train_(ClassificationData &trainingData) - No weakClassifiers have been set. You need to set at least one weak classifier first." << std::endl;
140 classLabels.
resize(numClasses);
141 models.
resize(numClasses);
146 trainingData.
scale(ranges,0,1);
155 for(UINT classIter=0; classIter<numClasses; classIter++){
158 classLabels[classIter] = trainingData.
getClassLabels()[classIter];
161 models[ classIter ].setClassLabel( classLabels[classIter] );
166 for(UINT i=0; i<M; i++){
167 UINT label = trainingData[i].getClassLabel()==classLabels[classIter] ? POSITIVE_LABEL : NEGATIVE_LABEL;
168 VectorFloat trainingSample = trainingData[i].getSample();
169 classData.
addSample(label,trainingSample);
173 std::fill(weights.begin(),weights.end(),1.0/M);
176 bool keepBoosting =
true;
179 while( keepBoosting ){
182 UINT bestClassifierIndex = 0;
184 for(UINT k=0; k<K; k++){
189 if( !weakLearner->
train(classData,weights) ){
190 errorLog <<
"Failed to train weakLearner!" << std::endl;
197 Float numCorrect = 0;
198 Float numIncorrect = 0;
199 for(UINT i=0; i<M; i++){
201 Float prediction = weakLearner->
predict( classData[i].getSample() );
203 if( (prediction == positiveLabel && classData[i].getClassLabel() != POSITIVE_LABEL) ||
204 (prediction != positiveLabel && classData[i].getClassLabel() == POSITIVE_LABEL) ){
206 errorMatrix[k][i] = 1;
209 errorMatrix[k][i] = 0;
214 trainingLog <<
"PositiveClass: " << classLabels[classIter] <<
" Boosting Iter: " << t <<
" Classifier: " << k <<
" WeightedError: " << e <<
" NumCorrect: " << numCorrect/M <<
" NumIncorrect: " <<numIncorrect/M << std::endl;
218 bestClassifierIndex = k;
226 alpha = 0.5 * log( (1.0-epsilon)/epsilon );
228 trainingLog <<
"PositiveClass: " << classLabels[classIter] <<
" Boosting Iter: " << t <<
" Best Classifier Index: " << bestClassifierIndex <<
" MinError: " << minError <<
" Alpha: " << alpha << std::endl;
230 if( grt_isinf(alpha) ){ keepBoosting =
false; trainingLog <<
"Alpha is INF. Stopping boosting for current class" << std::endl; }
231 if( 0.5 - epsilon <= beta ){ keepBoosting =
false; trainingLog <<
"Epsilon <= Beta. Stopping boosting for current class" << std::endl; }
232 if( ++t >= numBoostingIterations ) keepBoosting =
false;
234 trainingResult.setClassificationResult(t, minError,
this);
235 trainingResults.push_back(trainingResult);
236 trainingResultsObserverManager.notifyObservers( trainingResult );
241 models[ classIter ].addClassifierToCommitee( weakClassifiers[bestClassifierIndex], alpha );
244 Float reWeight = (1.0 - epsilon) / epsilon;
247 for(UINT i=0; i<M; i++){
248 oldSum += weights[i];
250 if( errorMatrix[bestClassifierIndex][i] == 1 ) weights[i] *= reWeight;
251 newSum += weights[i];
257 reWeight = oldSum/newSum;
258 for(UINT i=0; i<M; i++){
259 weights[i] *= reWeight;
263 trainingLog <<
"Stopping boosting training at iteration : " << t-1 <<
" with an error of " << epsilon << std::endl;
266 if( grt_isinf(alpha) ){ alpha = 1; }
267 models[ classIter ].addClassifierToCommitee( weakClassifiers[bestClassifierIndex], alpha );
275 for(UINT k=0; k<numClasses; k++){
276 models[k].normalizeWeights();
283 predictedClassLabel = 0;
285 classLikelihoods.
resize(numClasses);
286 classDistances.
resize(numClasses);
293 predictedClassLabel = 0;
294 maxLikelihood = -10000;
297 errorLog <<
"predict_(VectorFloat &inputVector) - AdaBoost Model Not Trained!" << std::endl;
301 if( inputVector.size() != numInputDimensions ){
302 errorLog <<
"predict_(VectorFloat &inputVector) - The size of the input vector (" << inputVector.size() <<
") does not match the num features in the model (" << numInputDimensions << std::endl;
307 for(UINT n=0; n<numInputDimensions; n++){
308 inputVector[n] =
scale(inputVector[n], ranges[n].minValue, ranges[n].maxValue, 0, 1);
312 if( classLikelihoods.size() != numClasses ) classLikelihoods.
resize(numClasses,0);
313 if( classDistances.size() != numClasses ) classDistances.
resize(numClasses,0);
315 UINT bestClassIndex = 0;
316 UINT numPositivePredictions = 0;
320 for(UINT k=0; k<numClasses; k++){
321 Float result = models[k].predict( inputVector );
323 switch ( predictionMethod ) {
324 case MAX_POSITIVE_VALUE:
326 if( result > bestDistance ){
327 bestDistance = result;
330 numPositivePredictions++;
331 classLikelihoods[k] = result;
332 }
else classLikelihoods[k] = 0;
334 classDistances[k] = result;
335 sum += classLikelihoods[k];
339 if( result > bestDistance ){
340 bestDistance = result;
343 if( result < worstDistance ){
344 worstDistance = result;
346 numPositivePredictions++;
347 classLikelihoods[k] = result;
348 classDistances[k] = result;
352 errorLog <<
"predict_(VectorFloat &inputVector) - Unknown prediction method!" << std::endl;
357 if( predictionMethod == MAX_VALUE ){
359 worstDistance = fabs( worstDistance );
360 for(UINT k=0; k<numClasses; k++){
361 classLikelihoods[k] += worstDistance;
362 sum += classLikelihoods[k];
368 for(UINT k=0; k<numClasses; k++)
369 classLikelihoods[k] /= sum;
371 maxLikelihood = classLikelihoods[ bestClassIndex ];
373 if( numPositivePredictions == 0 ){
374 predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
375 }
else predictedClassLabel = classLabels[ bestClassIndex ];
391 if( nullRejectionCoeff > 0 ){
392 this->nullRejectionCoeff = nullRejectionCoeff;
403 errorLog <<
"saveModelToFile(fstream &file) - The file is not open!" << std::endl;
408 file<<
"GRT_ADABOOST_MODEL_FILE_V2.0\n";
412 errorLog <<
"saveModelToFile(fstream &file) - Failed to save classifier base settings to file!" << std::endl;
417 file <<
"PredictionMethod: " << predictionMethod << std::endl;
421 file <<
"Models: " << std::endl;
422 for(UINT i=0; i<models.size(); i++){
424 errorLog <<
"saveModelToFile(fstream &file) - Failed to write model " << i <<
" to file!" << std::endl;
440 errorLog <<
"loadModelFromFile(string filename) - Could not open file to load model!" << std::endl;
448 if( word ==
"GRT_ADABOOST_MODEL_FILE_V1.0" ){
449 return loadLegacyModelFromFile( file );
452 if( word !=
"GRT_ADABOOST_MODEL_FILE_V2.0" ){
453 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read file header!" << std::endl;
454 errorLog << word << std::endl;
460 errorLog <<
"loadModelFromFile(string filename) - Failed to load base settings from file!" << std::endl;
465 if( word !=
"PredictionMethod:" ){
466 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read PredictionMethod header!" << std::endl;
469 file >> predictionMethod;
473 if( word !=
"Models:" ){
474 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read Models header!" << std::endl;
479 models.
resize( numClasses );
480 for(UINT i=0; i<models.size(); i++){
482 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load model " << i <<
" from file!" << std::endl;
493 bestDistance = DEFAULT_NULL_DISTANCE_VALUE;
495 classDistances.
resize(numClasses,DEFAULT_NULL_DISTANCE_VALUE);
519 weakClassifiers.push_back( weakClassiferPtr );
527 weakClassifiers.push_back( weakClassiferPtr );
534 for(UINT i=0; i<weakClassifiers.size(); i++){
535 if( weakClassifiers[i] != NULL ){
536 delete weakClassifiers[i];
537 weakClassifiers[i] = NULL;
540 weakClassifiers.clear();
545 if( numBoostingIterations > 0 ){
546 this->numBoostingIterations = numBoostingIterations;
553 if( predictionMethod != MAX_POSITIVE_VALUE && predictionMethod != MAX_VALUE ){
556 this->predictionMethod = predictionMethod;
562 std::cout <<
"AdaBoostModel: \n";
563 std::cout<<
"NumFeatures: " << numInputDimensions << std::endl;
564 std::cout<<
"NumClasses: " << numClasses << std::endl;
565 std::cout <<
"UseScaling: " << useScaling << std::endl;
566 std::cout<<
"UseNullRejection: " << useNullRejection << std::endl;
568 for(UINT k=0; k<numClasses; k++){
569 std::cout <<
"Class: " << k+1 <<
" ClassLabel: " << classLabels[k] << std::endl;
575 bool AdaBoost::loadLegacyModelFromFile( std::fstream &file ){
580 if( word !=
"NumFeatures:" ){
581 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumFeatures header!" << std::endl;
584 file >> numInputDimensions;
587 if( word !=
"NumClasses:" ){
588 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumClasses header!" << std::endl;
594 if( word !=
"UseScaling:" ){
595 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read UseScaling header!" << std::endl;
601 if( word !=
"UseNullRejection:" ){
602 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read UseNullRejection header!" << std::endl;
605 file >> useNullRejection;
609 if( word !=
"Ranges:" ){
610 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read Ranges header!" << std::endl;
613 ranges.
resize( numInputDimensions );
615 for(UINT n=0; n<ranges.size(); n++){
616 file >> ranges[n].minValue;
617 file >> ranges[n].maxValue;
622 if( word !=
"Trained:" ){
623 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read Trained header!" << std::endl;
629 if( word !=
"PredictionMethod:" ){
630 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read PredictionMethod header!" << std::endl;
633 file >> predictionMethod;
637 if( word !=
"Models:" ){
638 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read Models header!" << std::endl;
643 models.
resize( numClasses );
644 classLabels.
resize( numClasses );
645 for(UINT i=0; i<models.size(); i++){
647 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load model " << i <<
" from file!" << std::endl;
653 classLabels[i] = models[i].getClassLabel();
662 bestDistance = DEFAULT_NULL_DISTANCE_VALUE;
664 classDistances.
resize(numClasses,DEFAULT_NULL_DISTANCE_VALUE);
bool saveBaseSettingsToFile(std::fstream &file) const
bool setPredictionMethod(UINT predictionMethod)
#define DEFAULT_NULL_LIKELIHOOD_VALUE
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
virtual Float predict(const VectorFloat &x)
bool addSample(UINT classLabel, const VectorFloat &sample)
AdaBoost(const WeakClassifier &weakClassifier=DecisionStump(), bool useScaling=false, bool useNullRejection=false, Float nullRejectionCoeff=10.0, UINT numBoostingIterations=20, UINT predictionMethod=MAX_VALUE)
std::string getClassifierType() const
virtual bool resize(const unsigned int size)
bool setNumDimensions(UINT numDimensions)
This class contains the AdaBoost classifier. AdaBoost (Adaptive Boosting) is a powerful classifier th...
Vector< UINT > getClassLabels() const
virtual bool train_(ClassificationData &trainingData)
virtual bool train(ClassificationData &trainingData, VectorFloat &weights)
virtual bool loadModelFromFile(std::fstream &file)
bool setNumBoostingIterations(UINT numBoostingIterations)
virtual bool saveModelToFile(std::fstream &file) const
virtual Float getPositiveClassLabel() const
WeakClassifier * createNewInstance() const
UINT getNumSamples() const
#define WEAK_CLASSIFIER_POSITIVE_CLASS_LABEL
bool addWeakClassifier(const WeakClassifier &weakClassifer)
virtual bool recomputeNullRejectionThresholds()
virtual bool deepCopyFrom(const Classifier *classifier)
virtual bool predict_(VectorFloat &inputVector)
bool clearWeakClassifiers()
bool copyBaseVariables(const Classifier *classifier)
bool loadBaseSettingsFromFile(std::fstream &file)
UINT getNumDimensions() const
UINT getNumClasses() const
bool setWeakClassifier(const WeakClassifier &weakClassifer)
Vector< MinMax > getRanges() const
AdaBoost & operator=(const AdaBoost &rhs)
bool setNullRejectionCoeff(Float nullRejectionCoeff)
bool scale(const Float minTarget, const Float maxTarget)