00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <ctime>
00025 #include <cmath>
00026 #include <fstream>
00027 #include <limits>
00028
00029 #include "IO/OutputInfo.h"
00030 #include "IO/Serialization.h"
00031 #include "Utils/Utils.h"
00032 #include "Defaults.h"
00033
00034 #include "AdaBoostMHLearner.h"
00035
00036 namespace MultiBoost {
00037
00038
00039
00040 AdaBoostLearner::AdaBoostLearner(nor_utils::Args& args, int verbose)
00041 : _args(args), _maxTime(-1), _theta(0), _verbose(verbose), _outputInfoFile(""),
00042 _smallVal(1E-10)
00043 {
00044
00045 if ( args.hasArgument("-outputinfo") )
00046 args.getValue("-outputinfo", 0, _outputInfoFile);
00047
00049
00050 _basicLearnerName = defaultLearner;
00051
00052 if ( args.hasArgument("-learnertype") )
00053 {
00054 string learnerString;
00055 args.getValue("-learnertype", 0, learnerString);
00056
00057 if ( !BaseLearner::RegisteredLearners().hasLearner(learnerString) )
00058 {
00059
00060 cerr << "ERROR: learner <" << learnerString << "> not found in the registered learners!" << endl;
00061 exit(1);
00062 }
00063 else
00064 _basicLearnerName = learnerString;
00065 }
00066
00067 if (_verbose > 1)
00068 cout << "--> Using learner: " << _basicLearnerName << endl;
00069
00071
00072 if ( args.hasArgument("-shypname") )
00073 args.getValue("-shypname", 0, _shypFileName);
00074 else
00075 _shypFileName = string(SHYP_NAME);
00076
00077 _shypFileName = nor_utils::addAndCheckExtension(_shypFileName, SHYP_EXTENSION);
00078
00080
00081 if ( args.hasArgument("-timelimit") )
00082 {
00083 args.getValue("-timelimit", 0, _maxTime);
00084 if (_verbose > 1)
00085 cout << "--> Overall Time Limit: " << _maxTime << " minutes" << endl;
00086 }
00087
00088
00089 if ( args.hasArgument("-edgeoffset") )
00090 args.getValue("-edgeoffset", 0, _theta);
00091
00092 }
00093
00094
00095
00096 void AdaBoostLearner::run(int numIterations, const string& trainFileName, const string& testFileName)
00097 {
00098 time_t startTime, currentTime;
00099 time(&startTime);
00100
00101
00102 BaseLearner* pWeakHypothesisSource = BaseLearner::RegisteredLearners().getLearner(_basicLearnerName);
00103 Serialization ss(_shypFileName, _basicLearnerName);
00104
00105
00106 InputData* pTrainData = pWeakHypothesisSource->createInputData();
00107 pTrainData->initOptions(_args);
00108 pTrainData->load(trainFileName, IT_TRAIN, _verbose);
00109
00110
00111 InputData* pTestData = NULL;
00112 if ( !testFileName.empty() )
00113 {
00114 pTestData = pWeakHypothesisSource->createInputData();
00115 pTestData->initOptions(_args);
00116 pTestData->load(testFileName, IT_TEST, _verbose);
00117 }
00118
00119
00120 OutputInfo* pOutInfo = NULL;
00121
00122 if ( !_outputInfoFile.empty() )
00123 pOutInfo = new OutputInfo(_outputInfoFile);
00124
00125 if (_verbose == 1)
00126 cout << "Learning in progress..." << endl;
00127
00129 for (int t = 0; t < numIterations; ++t)
00130 {
00131 if (_verbose > 1)
00132 cout << " ------ WORKING ON ITERATION " << t << " ------ " << endl;
00133
00134 BaseLearner* pWeakHypothesis = pWeakHypothesisSource->create();
00135 pWeakHypothesis->initOptions(_args);
00136 pWeakHypothesis->run(pTrainData);
00137
00138
00139 if ( pOutInfo )
00140 {
00141 pOutInfo->outputIteration(t);
00142 pOutInfo->outputError(pTrainData, pWeakHypothesis);
00143 if (pTestData)
00144 pOutInfo->outputError(pTestData, pWeakHypothesis);
00145 pOutInfo->outputMargins(pTrainData, pWeakHypothesis);
00146 pOutInfo->outputEdge(pTrainData, pWeakHypothesis);
00147 pOutInfo->endLine();
00148 }
00149
00150
00151 double gamma = updateWeights(pTrainData, pWeakHypothesis);
00152
00153
00154
00155
00156 if (gamma <= _theta)
00157 {
00158 if (_verbose > 0)
00159 {
00160 cout << "Can't train any further: gamma = " << gamma
00161 << " (with and edge offset (theta)=" << _theta << ")" << endl;
00162 }
00163 break;
00164 }
00165
00166
00167
00168 ss.appendHypothesis(t, pWeakHypothesis);
00169
00170
00171 _foundHypotheses.push_back(pWeakHypothesis);
00172
00173
00174 if (_maxTime > 0)
00175 {
00176 time( ¤tTime );
00177 double diff = difftime(currentTime, startTime);
00178 diff /= 60;
00179
00180 if (diff > _maxTime)
00181 {
00182 if (_verbose > 0)
00183 cout << "Time limit of " << _maxTime
00184 << " minutes has been reached!" << endl;
00185 break;
00186 }
00187 }
00188
00189 }
00191
00192
00193 if (pTrainData)
00194 delete pTrainData;
00195 if (pTestData)
00196 delete pTestData;
00197
00198 if (pOutInfo)
00199 delete pOutInfo;
00200
00201 if (_verbose > 0)
00202 cout << "Learning completed." << endl;
00203 }
00204
00205
00206
00207 double AdaBoostLearner::updateWeights(InputData* pData, BaseLearner* pWeakHypothesis)
00208 {
00209 const int numExamples = pData->getNumExamples();
00210 const int numClasses = ClassMappings::getNumClasses();
00211
00212 double Z = 0;
00213
00214
00215
00216 for (int i = 0; i < numExamples; ++i)
00217 {
00218 for (int l = 0; l < numClasses; ++l)
00219 {
00220 Z += pData->getWeight(i, l) *
00221 exp(
00222 -pWeakHypothesis->getAlpha() *
00223 pWeakHypothesis->classify(pData, i, l) *
00224 pData->getBinaryClass(i, l)
00225 );
00226 }
00227 }
00228
00229
00230
00231 double gamma = 0;
00232
00233
00234
00235 for (int i = 0; i < numExamples; ++i)
00236 {
00237 for (int l = 0; l < numClasses; ++l)
00238 {
00239 double hy = pWeakHypothesis->classify(pData, i, l) *
00240 pData->getBinaryClass(i, l);
00241
00242 double w = pData->getWeight(i, l);
00243
00244 gamma += w * hy;
00245
00246
00247 pData->setWeight( i, l,
00248 w * exp( -pWeakHypothesis->getAlpha() * hy ) / Z );
00249 }
00250 }
00251
00252 return gamma;
00253 }
00254
00255
00256
00257
00258 }