TestGPHIKOnlineLearnable.cpp 25 KB

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