TestGPHIKOnlineLearnable.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. /**
  2. * @file TestGPHIKOnlineLearnable.cpp
  3. * @brief CppUnit-Testcase to verify that GPHIKClassifier methods herited from Persistent (store and restore) work as desired.
  4. * @author Alexander Freytag
  5. * @date 21-12-2013
  6. */
  7. #ifdef NICE_USELIB_CPPUNIT
  8. // STL includes
  9. #include <iostream>
  10. #include <vector>
  11. // NICE-core includes
  12. #include <core/basics/Config.h>
  13. #include <core/basics/Timer.h>
  14. // gp-hik-core includes
  15. #include "gp-hik-core/GPHIKClassifier.h"
  16. #include "gp-hik-core/GPHIKRawClassifier.h"
  17. #include "TestGPHIKOnlineLearnable.h"
  18. using namespace std; //C basics
  19. using namespace NICE; // nice-core
  20. const bool verboseStartEnd = true;
  21. const bool verbose = false;
  22. const bool writeClassifiersForVerification = false;
  23. CPPUNIT_TEST_SUITE_REGISTRATION( TestGPHIKOnlineLearnable );
  24. void TestGPHIKOnlineLearnable::setUp() {
  25. }
  26. void TestGPHIKOnlineLearnable::tearDown() {
  27. }
  28. void readData ( const std::string filename, NICE::Matrix & data, NICE::Vector & yBin, NICE::Vector & yMulti )
  29. {
  30. std::ifstream ifs ( filename.c_str() , ios::in );
  31. if ( ifs.good() )
  32. {
  33. ifs >> data;
  34. ifs >> yBin;
  35. ifs >> yMulti;
  36. ifs.close();
  37. }
  38. else
  39. {
  40. std::cerr << "Unable to read data from file " << filename << " -- aborting." << std::endl;
  41. CPPUNIT_ASSERT ( ifs.good() );
  42. }
  43. }
  44. void prepareLabelMappings (std::map< uint, uint > & mapClNoToIdxTrain,
  45. const GPHIKClassifier * classifier,
  46. std::map< uint,uint > & mapClNoToIdxTest,
  47. const NICE::Vector & yMultiTest
  48. )
  49. {
  50. // determine classes known during training and corresponding mapping
  51. // thereby allow for non-continous class labels
  52. std::set< uint > classesKnownTraining = classifier->getKnownClassNumbers();
  53. uint noClassesKnownTraining ( classesKnownTraining.size() );
  54. std::set< uint >::const_iterator clTrIt = classesKnownTraining.begin();
  55. for ( uint i=0; i < noClassesKnownTraining; i++, clTrIt++ )
  56. mapClNoToIdxTrain.insert ( std::pair< uint, uint > ( *clTrIt, i ) );
  57. // determine classes known during testing and corresponding mapping
  58. // thereby allow for non-continous class labels
  59. std::set< uint> classesKnownTest;
  60. classesKnownTest.clear();
  61. // determine which classes we have in our label vector
  62. // -> MATLAB: myClasses = unique(y);
  63. for ( NICE::Vector::const_iterator it = yMultiTest.begin(); it != yMultiTest.end(); it++ )
  64. {
  65. if ( classesKnownTest.find ( *it ) == classesKnownTest.end() )
  66. {
  67. classesKnownTest.insert ( *it );
  68. }
  69. }
  70. uint noClassesKnownTest ( classesKnownTest.size() );
  71. std::set< uint >::const_iterator clTestIt = classesKnownTest.begin();
  72. for ( uint i=0; i < noClassesKnownTest; i++, clTestIt++ )
  73. mapClNoToIdxTest.insert ( std::pair< uint,uint > ( *clTestIt, i ) );
  74. }
  75. void evaluateClassifier ( NICE::Matrix & confusionMatrix,
  76. const NICE::GPHIKClassifier * classifier,
  77. const NICE::Matrix & data,
  78. const NICE::Vector & yMulti,
  79. const std::map< uint,uint > & mapClNoToIdxTrain,
  80. const std::map< uint,uint > & mapClNoToIdxTest
  81. )
  82. {
  83. int i_loopEnd ( (int)data.rows() );
  84. for (int i = 0; i < i_loopEnd ; i++)
  85. {
  86. NICE::Vector example ( data.getRow(i) );
  87. NICE::SparseVector scores;
  88. uint result;
  89. // classify with incrementally trained classifier
  90. classifier->classify( &example, result, scores );
  91. confusionMatrix( mapClNoToIdxTrain.find(result)->second, mapClNoToIdxTest.find(yMulti[i])->second ) += 1.0;
  92. }
  93. }
  94. void evaluateClassifierRaw ( NICE::Matrix & confusionMatrix,
  95. const NICE::GPHIKRawClassifier * classifier,
  96. const NICE::Matrix & data,
  97. const NICE::Vector & yMulti,
  98. const std::map< uint,uint > & mapClNoToIdxTrain,
  99. const std::map< uint,uint > & mapClNoToIdxTest
  100. )
  101. {
  102. int i_loopEnd ( (int)data.rows() );
  103. for (int i = 0; i < i_loopEnd ; i++)
  104. {
  105. NICE::Vector example_nonsparse ( data.getRow(i) );
  106. NICE::SparseVector example (example_nonsparse);
  107. NICE::SparseVector scores;
  108. uint result;
  109. // classify with incrementally trained classifier
  110. classifier->classify( &example, result, scores );
  111. uint gtlabel = mapClNoToIdxTest.find(yMulti[i])->second;
  112. uint predlabel = mapClNoToIdxTrain.find(result)->second;
  113. confusionMatrix( gtlabel, predlabel ) += 1.0;
  114. }
  115. }
  116. void compareClassifierOutputs ( const NICE::GPHIKClassifier * classifier,
  117. const NICE::GPHIKClassifier * classifierScratch,
  118. const NICE::Matrix & data
  119. )
  120. {
  121. int i_loopEnd ( (int)data.rows() );
  122. for (int i = 0; i < i_loopEnd ; i++)
  123. {
  124. NICE::Vector example ( data.getRow(i) );
  125. NICE::SparseVector scores;
  126. uint result;
  127. // classify with incrementally trained classifier
  128. classifier->classify( &example, result, scores );
  129. NICE::SparseVector scoresScratch;
  130. uint resultScratch;
  131. classifierScratch->classify( &example, resultScratch, scoresScratch );
  132. bool equal(true);
  133. NICE::SparseVector::const_iterator itScores = scores.begin();
  134. NICE::SparseVector::const_iterator itScoresScratch = scoresScratch.begin();
  135. for ( ; itScores != scores.end(); itScores++, itScoresScratch++)
  136. {
  137. if ( fabs( itScores->second - itScoresScratch->second ) > 10e-3)
  138. {
  139. std::cerr << " itScores->second: " << itScores->second << " itScores->second: " << itScores->second << std::endl;
  140. equal = false;
  141. break;
  142. }
  143. }
  144. CPPUNIT_ASSERT_EQUAL ( equal, true );
  145. }
  146. }
  147. void compareClassifierOutputsRaw ( const NICE::GPHIKClassifier * classifier,
  148. const NICE::GPHIKRawClassifier * classifierRaw,
  149. const NICE::Matrix & data
  150. )
  151. {
  152. int i_loopEnd ( (int)data.rows() );
  153. for (int i = 0; i < i_loopEnd ; i++)
  154. {
  155. NICE::Vector example ( data.getRow(i) );
  156. NICE::SparseVector scores;
  157. uint result;
  158. // classify with incrementally trained classifier
  159. classifier->classify( &example, result, scores );
  160. NICE::SparseVector scoresRaw;
  161. uint resultRaw;
  162. NICE::SparseVector example_sparse(example);
  163. classifierRaw->classify( &example_sparse, resultRaw, scoresRaw );
  164. bool equal(true);
  165. NICE::SparseVector::const_iterator itScores = scores.begin();
  166. NICE::SparseVector::const_iterator itScoresScratch = scoresRaw.begin();
  167. for ( ; itScores != scores.end(); itScores++, itScoresScratch++)
  168. {
  169. if ( fabs( itScores->second - itScoresScratch->second ) > 10e-6)
  170. {
  171. std::cerr << " itScores->second: " << itScores->second << " itScores->second: " << itScores->second << std::endl;
  172. equal = false;
  173. break;
  174. }
  175. }
  176. CPPUNIT_ASSERT_EQUAL ( equal, true );
  177. }
  178. }
  179. void TestGPHIKOnlineLearnable::testOnlineLearningStartEmpty()
  180. {
  181. if (verboseStartEnd)
  182. std::cerr << "================== TestGPHIKOnlineLearnable::testOnlineLearningStartEmpty ===================== " << std::endl;
  183. NICE::Config conf;
  184. conf.sB ( "GPHIKClassifier", "eig_verbose", false);
  185. conf.sS ( "GPHIKClassifier", "optimization_method", "none");
  186. std::string s_trainData = conf.gS( "main", "trainData", "toyExampleSmallScaleTrain.data" );
  187. //------------- read the training data --------------
  188. NICE::Matrix dataTrain;
  189. NICE::Vector yBinTrain;
  190. NICE::Vector yMultiTrain;
  191. readData ( s_trainData, dataTrain, yBinTrain, yMultiTrain );
  192. //----------------- convert data to sparse data structures ---------
  193. std::vector< const NICE::SparseVector *> examplesTrain;
  194. examplesTrain.resize( dataTrain.rows() );
  195. std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin();
  196. for (int i = 0; i < (int)dataTrain.rows(); i++, exTrainIt++)
  197. {
  198. *exTrainIt = new NICE::SparseVector( dataTrain.getRow(i) );
  199. }
  200. //create classifier object
  201. NICE::GPHIKClassifier * classifier;
  202. classifier = new NICE::GPHIKClassifier ( &conf );
  203. bool performOptimizationAfterIncrement ( true );
  204. // add training samples, but without running training method first
  205. classifier->addMultipleExamples ( examplesTrain,yMultiTrain, performOptimizationAfterIncrement );
  206. // create second object trained in the standard way
  207. NICE::GPHIKClassifier * classifierScratch = new NICE::GPHIKClassifier ( &conf );
  208. classifierScratch->train ( examplesTrain, yMultiTrain );
  209. // TEST both classifiers to produce equal results
  210. //------------- read the test data --------------
  211. NICE::Matrix dataTest;
  212. NICE::Vector yBinTest;
  213. NICE::Vector yMultiTest;
  214. std::string s_testData = conf.gS( "main", "testData", "toyExampleTest.data" );
  215. readData ( s_testData, dataTest, yBinTest, yMultiTest );
  216. // ------------------------------------------
  217. // ------------- PREPARATION --------------
  218. // ------------------------------------------
  219. // determine classes known during training/testing and corresponding mapping
  220. // thereby allow for non-continous class labels
  221. std::map< uint,uint > mapClNoToIdxTrain;
  222. std::map< uint,uint > mapClNoToIdxTest;
  223. prepareLabelMappings (mapClNoToIdxTrain, classifier, mapClNoToIdxTest, yMultiTest);
  224. NICE::Matrix confusionMatrix ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  225. NICE::Matrix confusionMatrixScratch ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  226. // ------------------------------------------
  227. // ------------- CLASSIFICATION --------------
  228. // ------------------------------------------
  229. evaluateClassifier ( confusionMatrix, classifier, dataTest, yMultiTest,
  230. mapClNoToIdxTrain,mapClNoToIdxTest );
  231. evaluateClassifier ( confusionMatrixScratch, classifierScratch, dataTest, yMultiTest,
  232. mapClNoToIdxTrain,mapClNoToIdxTest );
  233. // post-process confusion matrices
  234. confusionMatrix.normalizeColumnsL1();
  235. double arr ( confusionMatrix.trace()/confusionMatrix.cols() );
  236. confusionMatrixScratch.normalizeColumnsL1();
  237. double arrScratch ( confusionMatrixScratch.trace()/confusionMatrixScratch.cols() );
  238. if ( verbose )
  239. {
  240. std::cerr << "confusionMatrix: " << confusionMatrix << std::endl;
  241. std::cerr << "confusionMatrixScratch: " << confusionMatrixScratch << std::endl;
  242. }
  243. CPPUNIT_ASSERT_DOUBLES_EQUAL( arr, arrScratch, 1e-8);
  244. // don't waste memory
  245. delete classifier;
  246. delete classifierScratch;
  247. for (std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin(); exTrainIt != examplesTrain.end(); exTrainIt++)
  248. {
  249. delete *exTrainIt;
  250. }
  251. if (verboseStartEnd)
  252. std::cerr << "================== TestGPHIKOnlineLearnable::testOnlineLearningStartEmpty done ===================== " << std::endl;
  253. }
  254. void TestGPHIKOnlineLearnable::testOnlineLearningOCCtoBinary()
  255. {
  256. if (verboseStartEnd)
  257. std::cerr << "================== TestGPHIKOnlineLearnable::testOnlineLearningOCCtoBinary ===================== " << std::endl;
  258. NICE::Config conf;
  259. conf.sB ( "GPHIKClassifier", "eig_verbose", false);
  260. conf.sS ( "GPHIKClassifier", "optimization_method", "none");
  261. conf.sB ( "GPHIKClassifier", "verbose", true);
  262. std::string s_trainData = conf.gS( "main", "trainData", "toyExampleSmallScaleTrain.data" );
  263. //------------- read the training data --------------
  264. NICE::Matrix dataTrain;
  265. NICE::Vector yBinTrain;
  266. NICE::Vector yMultiTrain;
  267. readData ( s_trainData, dataTrain, yBinTrain, yMultiTrain );
  268. //----------------- convert data to sparse data structures ---------
  269. std::vector< const NICE::SparseVector *> examplesTrain;
  270. std::vector< const NICE::SparseVector *> examplesTrainPlus;
  271. std::vector< const NICE::SparseVector *> examplesTrainMinus;
  272. examplesTrain.resize( dataTrain.rows() );
  273. // to check whether non-consecutive and even wrongly odered class numbers work as well
  274. int clNoFirst ( 2 );
  275. int clNoSecond ( 0 );
  276. std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin();
  277. for (int i = 0; i < (int)dataTrain.rows(); i++, exTrainIt++)
  278. {
  279. *exTrainIt = new NICE::SparseVector( dataTrain.getRow(i) );
  280. if ( yBinTrain[i] == 1 )
  281. {
  282. examplesTrainPlus.push_back ( *exTrainIt );
  283. yBinTrain[i] = clNoFirst;
  284. }
  285. else
  286. {
  287. examplesTrainMinus.push_back ( *exTrainIt );
  288. yBinTrain[i] = clNoSecond;
  289. }
  290. }
  291. NICE::Vector yBinPlus ( examplesTrainPlus.size(), clNoFirst ) ;
  292. NICE::Vector yBinMinus ( examplesTrainMinus.size(), clNoSecond );
  293. //create classifier object
  294. NICE::GPHIKClassifier * classifier;
  295. classifier = new NICE::GPHIKClassifier ( &conf );
  296. bool performOptimizationAfterIncrement ( true );
  297. // training with examples for positive class only
  298. classifier->train ( examplesTrainPlus, yBinPlus );
  299. // add samples for negative class, thereby going from OCC to binary setting
  300. classifier->addMultipleExamples ( examplesTrainMinus, yBinMinus, performOptimizationAfterIncrement );
  301. // create second object trained in the standard way
  302. NICE::GPHIKClassifier * classifierScratch = new NICE::GPHIKClassifier ( &conf );
  303. classifierScratch->train ( examplesTrain, yBinTrain );
  304. NICE::GPHIKRawClassifier * classifierScratchRaw = new NICE::GPHIKRawClassifier ( &conf );
  305. classifierScratchRaw->train ( examplesTrain, yBinTrain );
  306. // TEST both classifiers to produce equal results
  307. //------------- read the test data --------------
  308. NICE::Matrix dataTest;
  309. NICE::Vector yBinTest;
  310. NICE::Vector yMultiTest;
  311. std::string s_testData = conf.gS( "main", "testData", "toyExampleTest.data" );
  312. readData ( s_testData, dataTest, yBinTest, yMultiTest );
  313. // ------------------------------------------
  314. // ------------- PREPARATION --------------
  315. // ------------------------------------------
  316. // determine classes known during training/testing and corresponding mapping
  317. // thereby allow for non-continous class labels
  318. std::map< uint,uint > mapClNoToIdxTrain;
  319. std::map< uint,uint > mapClNoToIdxTest;
  320. prepareLabelMappings (mapClNoToIdxTrain, classifier, mapClNoToIdxTest, yMultiTest);
  321. NICE::Matrix confusionMatrix ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  322. NICE::Matrix confusionMatrixScratch ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  323. NICE::Matrix confusionMatrixScratchRaw ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  324. // ------------------------------------------
  325. // ------------- CLASSIFICATION --------------
  326. // ------------------------------------------
  327. evaluateClassifier ( confusionMatrix, classifier, dataTest, yBinTest,
  328. mapClNoToIdxTrain, mapClNoToIdxTest );
  329. evaluateClassifier ( confusionMatrixScratch, classifierScratch, dataTest, yBinTest,
  330. mapClNoToIdxTrain, mapClNoToIdxTest );
  331. evaluateClassifierRaw ( confusionMatrixScratchRaw, classifierScratchRaw, dataTest, yBinTest,
  332. mapClNoToIdxTrain, mapClNoToIdxTest );
  333. // post-process confusion matrices
  334. confusionMatrix.normalizeColumnsL1();
  335. double arr ( confusionMatrix.trace()/confusionMatrix.cols() );
  336. confusionMatrixScratch.normalizeColumnsL1();
  337. double arrScratch ( confusionMatrixScratch.trace()/confusionMatrixScratch.cols() );
  338. confusionMatrixScratchRaw.normalizeColumnsL1();
  339. double arrScratchRaw ( confusionMatrixScratchRaw.trace()/confusionMatrixScratchRaw.cols() );
  340. if ( verbose )
  341. {
  342. std::cerr << "confusionMatrix: " << confusionMatrix << std::endl;
  343. std::cerr << "confusionMatrixScratch: " << confusionMatrixScratch << std::endl;
  344. std::cerr << "confusionMatrixScratchRaw: " << confusionMatrixScratchRaw << std::endl;
  345. }
  346. CPPUNIT_ASSERT_DOUBLES_EQUAL( arr, arrScratch, 1e-8);
  347. CPPUNIT_ASSERT_DOUBLES_EQUAL( arrScratch, arrScratchRaw, 1e-8);
  348. compareClassifierOutputsRaw(classifier, classifierScratchRaw, dataTest);
  349. // don't waste memory
  350. delete classifier;
  351. delete classifierScratch;
  352. delete classifierScratchRaw;
  353. for (std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin(); exTrainIt != examplesTrain.end(); exTrainIt++)
  354. {
  355. delete *exTrainIt;
  356. }
  357. if (verboseStartEnd)
  358. std::cerr << "================== TestGPHIKOnlineLearnable::testOnlineLearningOCCtoBinary done ===================== " << std::endl;
  359. }
  360. void TestGPHIKOnlineLearnable::testOnlineLearningBinarytoMultiClass()
  361. {
  362. if (verboseStartEnd)
  363. std::cerr << "================== TestGPHIKOnlineLearnable::testOnlineLearningBinarytoMultiClass ===================== " << std::endl;
  364. NICE::Config conf;
  365. conf.sB ( "GPHIKClassifier", "eig_verbose", false);
  366. conf.sS ( "GPHIKClassifier", "optimization_method", "downhillsimplex");
  367. // conf.sS ( "GPHIKClassifier", "optimization_method", "none");
  368. std::string s_trainData = conf.gS( "main", "trainData", "toyExampleSmallScaleTrain.data" );
  369. //------------- read the training data --------------
  370. NICE::Matrix dataTrain;
  371. NICE::Vector yBinTrain;
  372. NICE::Vector yMultiTrain;
  373. readData ( s_trainData, dataTrain, yBinTrain, yMultiTrain );
  374. //----------------- convert data to sparse data structures ---------
  375. std::vector< const NICE::SparseVector *> examplesTrain;
  376. std::vector< const NICE::SparseVector *> examplesTrain12;
  377. std::vector< const NICE::SparseVector *> examplesTrain3;
  378. NICE::Vector yMulti12 ( yMultiTrain.size(), 1 ) ;
  379. NICE::Vector yMulti3 ( yMultiTrain.size(), 1 ) ;
  380. int cnt12 ( 0 );
  381. int cnt3 ( 0 );
  382. examplesTrain.resize( dataTrain.rows() );
  383. std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin();
  384. for (int i = 0; i < (int)dataTrain.rows(); i++, exTrainIt++)
  385. {
  386. *exTrainIt = new NICE::SparseVector( dataTrain.getRow(i) );
  387. if ( ( yMultiTrain[i] == 0 ) || ( yMultiTrain[i] == 1 ) )
  388. {
  389. examplesTrain12.push_back ( *exTrainIt );
  390. yMulti12[ cnt12 ] = yMultiTrain[i];
  391. cnt12++;
  392. }
  393. else
  394. {
  395. examplesTrain3.push_back ( *exTrainIt );
  396. yMulti3[cnt3] = 2;
  397. cnt3++;
  398. }
  399. }
  400. yMulti12.resize ( examplesTrain12.size() );
  401. yMulti3.resize ( examplesTrain3.size() );
  402. //create classifier object
  403. NICE::GPHIKClassifier * classifier;
  404. classifier = new NICE::GPHIKClassifier ( &conf );
  405. bool performOptimizationAfterIncrement ( true );
  406. // training with examples for first and second class only
  407. classifier->train ( examplesTrain12, yMulti12 );
  408. // add samples for third class, thereby going from binary to multi-class setting
  409. classifier->addMultipleExamples ( examplesTrain3, yMulti3, performOptimizationAfterIncrement );
  410. // create second object trained in the standard way
  411. NICE::GPHIKClassifier * classifierScratch = new NICE::GPHIKClassifier ( &conf );
  412. classifierScratch->train ( examplesTrain, yMultiTrain );
  413. // TEST both classifiers to produce equal results
  414. //------------- read the test data --------------
  415. NICE::Matrix dataTest;
  416. NICE::Vector yBinTest;
  417. NICE::Vector yMultiTest;
  418. std::string s_testData = conf.gS( "main", "testData", "toyExampleTest.data" );
  419. readData ( s_testData, dataTest, yBinTest, yMultiTest );
  420. // ------------------------------------------
  421. // ------------- PREPARATION --------------
  422. // ------------------------------------------
  423. // determine classes known during training/testing and corresponding mapping
  424. // thereby allow for non-continous class labels
  425. std::map< uint,uint > mapClNoToIdxTrain;
  426. std::map< uint,uint > mapClNoToIdxTest;
  427. prepareLabelMappings (mapClNoToIdxTrain, classifier, mapClNoToIdxTest, yMultiTest);
  428. NICE::Matrix confusionMatrix ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  429. NICE::Matrix confusionMatrixScratch ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  430. // ------------------------------------------
  431. // ------------- CLASSIFICATION --------------
  432. // ------------------------------------------
  433. compareClassifierOutputs ( classifier, classifierScratch, dataTest );
  434. evaluateClassifier ( confusionMatrix, classifier, dataTest, yMultiTest,
  435. mapClNoToIdxTrain,mapClNoToIdxTest );
  436. evaluateClassifier ( confusionMatrixScratch, classifierScratch, dataTest, yMultiTest,
  437. mapClNoToIdxTrain,mapClNoToIdxTest );
  438. // post-process confusion matrices
  439. confusionMatrix.normalizeColumnsL1();
  440. double arr ( confusionMatrix.trace()/confusionMatrix.cols() );
  441. confusionMatrixScratch.normalizeColumnsL1();
  442. double arrScratch ( confusionMatrixScratch.trace()/confusionMatrixScratch.cols() );
  443. if ( verbose )
  444. {
  445. std::cerr << "confusionMatrix: " << confusionMatrix << std::endl;
  446. std::cerr << "confusionMatrixScratch: " << confusionMatrixScratch << std::endl;
  447. }
  448. CPPUNIT_ASSERT_DOUBLES_EQUAL( arr, arrScratch, 1e-8);
  449. // don't waste memory
  450. delete classifier;
  451. delete classifierScratch;
  452. for (std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin(); exTrainIt != examplesTrain.end(); exTrainIt++)
  453. {
  454. delete *exTrainIt;
  455. }
  456. if (verboseStartEnd)
  457. std::cerr << "================== TestGPHIKOnlineLearnable::testOnlineLearningBinarytoMultiClass done ===================== " << std::endl;
  458. }
  459. void TestGPHIKOnlineLearnable::testOnlineLearningMultiClass()
  460. {
  461. if (verboseStartEnd)
  462. std::cerr << "================== TestGPHIKOnlineLearnable::testOnlineLearningMultiClass ===================== " << std::endl;
  463. NICE::Config conf;
  464. conf.sB ( "GPHIKClassifier", "eig_verbose", false);
  465. conf.sS ( "GPHIKClassifier", "optimization_method", "downhillsimplex");//downhillsimplex greedy
  466. std::string s_trainData = conf.gS( "main", "trainData", "toyExampleSmallScaleTrain.data" );
  467. //------------- read the training data --------------
  468. NICE::Matrix dataTrain;
  469. NICE::Vector yBinTrain;
  470. NICE::Vector yMultiTrain;
  471. readData ( s_trainData, dataTrain, yBinTrain, yMultiTrain );
  472. //----------------- convert data to sparse data structures ---------
  473. std::vector< const NICE::SparseVector *> examplesTrain;
  474. examplesTrain.resize( dataTrain.rows()-1 );
  475. std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin();
  476. for (int i = 0; i < (int)dataTrain.rows()-1; i++, exTrainIt++)
  477. {
  478. *exTrainIt = new NICE::SparseVector( dataTrain.getRow(i) );
  479. }
  480. // TRAIN INITIAL CLASSIFIER FROM SCRATCH
  481. NICE::GPHIKClassifier * classifier;
  482. classifier = new NICE::GPHIKClassifier ( &conf );
  483. //use all but the first example for training and add the first one lateron
  484. NICE::Vector yMultiRelevantTrain ( yMultiTrain.getRangeRef( 0, yMultiTrain.size()-2 ) );
  485. classifier->train ( examplesTrain , yMultiRelevantTrain );
  486. // RUN INCREMENTAL LEARNING
  487. bool performOptimizationAfterIncrement ( true );
  488. NICE::SparseVector * exampleToAdd = new NICE::SparseVector ( dataTrain.getRow( (int)dataTrain.rows()-1 ) );
  489. classifier->addExample ( exampleToAdd, yMultiTrain[ (int)dataTrain.rows()-2 ], performOptimizationAfterIncrement );
  490. if ( verbose )
  491. std::cerr << "label of example to add: " << yMultiTrain[ (int)dataTrain.rows()-1 ] << std::endl;
  492. // TRAIN SECOND CLASSIFIER FROM SCRATCH USING THE SAME OVERALL AMOUNT OF EXAMPLES
  493. examplesTrain.push_back( exampleToAdd );
  494. NICE::GPHIKClassifier * classifierScratch = new NICE::GPHIKClassifier ( &conf );
  495. classifierScratch->train ( examplesTrain, yMultiTrain );
  496. if ( verbose )
  497. std::cerr << "trained both classifiers - now start evaluating them" << std::endl;
  498. // TEST that both classifiers produce equal store-files
  499. if ( writeClassifiersForVerification )
  500. {
  501. std::string s_destination_save_IL ( "myClassifierIL.txt" );
  502. std::filebuf fbOut;
  503. fbOut.open ( s_destination_save_IL.c_str(), ios::out );
  504. std::ostream os (&fbOut);
  505. //
  506. classifier->store( os );
  507. //
  508. fbOut.close();
  509. std::string s_destination_save_scratch ( "myClassifierScratch.txt" );
  510. std::filebuf fbOutScratch;
  511. fbOutScratch.open ( s_destination_save_scratch.c_str(), ios::out );
  512. std::ostream osScratch (&fbOutScratch);
  513. //
  514. classifierScratch->store( osScratch );
  515. //
  516. fbOutScratch.close();
  517. }
  518. // TEST both classifiers to produce equal results
  519. //------------- read the test data --------------
  520. NICE::Matrix dataTest;
  521. NICE::Vector yBinTest;
  522. NICE::Vector yMultiTest;
  523. std::string s_testData = conf.gS( "main", "testData", "toyExampleTest.data" );
  524. readData ( s_testData, dataTest, yBinTest, yMultiTest );
  525. // ------------------------------------------
  526. // ------------- PREPARATION --------------
  527. // ------------------------------------------
  528. // determine classes known during training/testing and corresponding mapping
  529. // thereby allow for non-continous class labels
  530. std::map< uint,uint > mapClNoToIdxTrain;
  531. std::map< uint,uint > mapClNoToIdxTest;
  532. prepareLabelMappings (mapClNoToIdxTrain, classifier, mapClNoToIdxTest, yMultiTest);
  533. NICE::Matrix confusionMatrix ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  534. NICE::Matrix confusionMatrixScratch ( mapClNoToIdxTrain.size(), mapClNoToIdxTest.size(), 0.0);
  535. // ------------------------------------------
  536. // ------------- CLASSIFICATION --------------
  537. // ------------------------------------------
  538. evaluateClassifier ( confusionMatrix, classifier, dataTest, yMultiTest,
  539. mapClNoToIdxTrain,mapClNoToIdxTest );
  540. evaluateClassifier ( confusionMatrixScratch, classifierScratch, dataTest, yMultiTest,
  541. mapClNoToIdxTrain,mapClNoToIdxTest );
  542. // post-process confusion matrices
  543. confusionMatrix.normalizeColumnsL1();
  544. double arr ( confusionMatrix.trace()/confusionMatrix.cols() );
  545. confusionMatrixScratch.normalizeColumnsL1();
  546. double arrScratch ( confusionMatrixScratch.trace()/confusionMatrixScratch.cols() );
  547. if ( verbose )
  548. {
  549. std::cerr << "confusionMatrix: " << confusionMatrix << std::endl;
  550. std::cerr << "confusionMatrixScratch: " << confusionMatrixScratch << std::endl;
  551. }
  552. CPPUNIT_ASSERT_DOUBLES_EQUAL( arr, arrScratch, 1e-8);
  553. // don't waste memory
  554. delete classifier;
  555. delete classifierScratch;
  556. for (std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin(); exTrainIt != examplesTrain.end(); exTrainIt++)
  557. {
  558. delete *exTrainIt;
  559. }
  560. if (verboseStartEnd)
  561. std::cerr << "================== TestGPHIKOnlineLearnable::testOnlineLearningMultiClass done ===================== " << std::endl;
  562. }
  563. #endif