test/ncc.cc

Code
Comments
Other
Rev Date Author Line
504 01 Feb 06 markus 1 // $Id$
504 01 Feb 06 markus 2
675 10 Oct 06 jari 3 /*
2119 12 Dec 09 peter 4   Copyright (C) 2006 Jari Häkkinen, Markus Ringnér
2119 12 Dec 09 peter 5   Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson, Markus Ringnér
4207 26 Aug 22 peter 6   Copyright (C) 2010, 2012, 2022 Peter Johansson
504 01 Feb 06 markus 7
1437 25 Aug 08 peter 8   This file is part of the yat library, http://dev.thep.lu.se/yat
675 10 Oct 06 jari 9
675 10 Oct 06 jari 10   The yat library is free software; you can redistribute it and/or
675 10 Oct 06 jari 11   modify it under the terms of the GNU General Public License as
1486 09 Sep 08 jari 12   published by the Free Software Foundation; either version 3 of the
675 10 Oct 06 jari 13   License, or (at your option) any later version.
675 10 Oct 06 jari 14
675 10 Oct 06 jari 15   The yat library is distributed in the hope that it will be useful,
675 10 Oct 06 jari 16   but WITHOUT ANY WARRANTY; without even the implied warranty of
675 10 Oct 06 jari 17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
675 10 Oct 06 jari 18   General Public License for more details.
675 10 Oct 06 jari 19
675 10 Oct 06 jari 20   You should have received a copy of the GNU General Public License
1487 10 Sep 08 jari 21   along with yat. If not, see <http://www.gnu.org/licenses/>.
675 10 Oct 06 jari 22 */
675 10 Oct 06 jari 23
2881 18 Nov 12 peter 24 #include <config.h>
2881 18 Nov 12 peter 25
1241 16 Mar 08 peter 26 #include "Suite.h"
1241 16 Mar 08 peter 27
675 10 Oct 06 jari 28 #include "yat/classifier/MatrixLookup.h"
675 10 Oct 06 jari 29 #include "yat/classifier/MatrixLookupWeighted.h"
675 10 Oct 06 jari 30 #include "yat/classifier/NCC.h"
675 10 Oct 06 jari 31 #include "yat/classifier/Target.h"
1587 17 Oct 08 peter 32 #include "yat/utility/DataIterator.h"
1587 17 Oct 08 peter 33 #include "yat/utility/DataWeight.h"
1121 22 Feb 08 peter 34 #include "yat/utility/Matrix.h"
1587 17 Oct 08 peter 35 #include "yat/utility/MatrixWeighted.h"
1052 07 Feb 08 peter 36 #include "yat/statistics/EuclideanDistance.h"
1052 07 Feb 08 peter 37 #include "yat/statistics/PearsonDistance.h"
675 10 Oct 06 jari 38 #include "yat/utility/utility.h"
675 10 Oct 06 jari 39
504 01 Feb 06 markus 40 #include <cassert>
504 01 Feb 06 markus 41 #include <fstream>
504 01 Feb 06 markus 42 #include <iostream>
931 05 Oct 07 markus 43 #include <stdexcept>
504 01 Feb 06 markus 44 #include <sstream>
504 01 Feb 06 markus 45 #include <string>
504 01 Feb 06 markus 46 #include <limits>
504 01 Feb 06 markus 47 #include <cmath>
504 01 Feb 06 markus 48
680 11 Oct 06 jari 49 using namespace theplu::yat;
504 01 Feb 06 markus 50
1483 09 Sep 08 peter 51 void predict_nan_data_unweighted_data(test::Suite& suite);
2338 16 Oct 10 peter 52 void compile_test(test::Suite& suite);
1483 09 Sep 08 peter 53
1241 16 Mar 08 peter 54 int main(int argc,char* argv[])
4200 19 Aug 22 peter 55 {
1241 16 Mar 08 peter 56   test::Suite suite(argc, argv);
1241 16 Mar 08 peter 57   suite.err() << "testing ncc" << std::endl;
504 01 Feb 06 markus 58
1483 09 Sep 08 peter 59   predict_nan_data_unweighted_data(suite);
1483 09 Sep 08 peter 60
1013 01 Feb 08 markus 61   /////////////////////////////////////////////
4200 19 Aug 22 peter 62   // First test of constructor and training
1013 01 Feb 08 markus 63   /////////////////////////////////////////////
931 05 Oct 07 markus 64   classifier::MatrixLookup ml(4,4);
916 30 Sep 07 peter 65   std::vector<std::string> vec(4, "pos");
916 30 Sep 07 peter 66   vec[3]="bjds";
916 30 Sep 07 peter 67   classifier::Target target(vec);
1157 26 Feb 08 markus 68    classifier::NCC<statistics::EuclideanDistance> ncctmp;
1241 16 Mar 08 peter 69   suite.err() << "training...\n";
1157 26 Feb 08 markus 70   ncctmp.train(ml,target);
1241 16 Mar 08 peter 71   suite.err() << "done\n";
1013 01 Feb 08 markus 72
1013 01 Feb 08 markus 73   /////////////////////////////////////////////
1013 01 Feb 08 markus 74   // A test of predictions using unweighted data
1013 01 Feb 08 markus 75   /////////////////////////////////////////////
1241 16 Mar 08 peter 76   suite.err() << "test of predictions using unweighted test data\n";
1121 22 Feb 08 peter 77   utility::Matrix data1(3,4);
1013 01 Feb 08 markus 78   for(size_t i=0;i<3;i++) {
1013 01 Feb 08 markus 79     data1(i,0)=3-i;
1013 01 Feb 08 markus 80     data1(i,1)=5-i;
1013 01 Feb 08 markus 81     data1(i,2)=i+1;
1013 01 Feb 08 markus 82     data1(i,3)=i+3;
1013 01 Feb 08 markus 83   }
1013 01 Feb 08 markus 84   std::vector<std::string> vec1(4, "pos");
1013 01 Feb 08 markus 85   vec1[0]="neg";
1013 01 Feb 08 markus 86   vec1[1]="neg";
1013 01 Feb 08 markus 87
1013 01 Feb 08 markus 88   classifier::MatrixLookup ml1(data1);
1013 01 Feb 08 markus 89   classifier::Target target1(vec1);
1013 01 Feb 08 markus 90
1157 26 Feb 08 markus 91   classifier::NCC<statistics::EuclideanDistance> ncc1;
1157 26 Feb 08 markus 92   ncc1.train(ml1,target1);
1121 22 Feb 08 peter 93   utility::Matrix prediction1;
1013 01 Feb 08 markus 94   ncc1.predict(ml1,prediction1);
1121 22 Feb 08 peter 95   utility::Matrix result1(2,4);
1013 01 Feb 08 markus 96   result1(0,0)=result1(0,1)=result1(1,2)=result1(1,3)=sqrt(3.0);
1013 01 Feb 08 markus 97   result1(0,2)=result1(0,3)=result1(1,0)=result1(1,1)=sqrt(11.0);
1241 16 Mar 08 peter 98   if (!suite.equal_range(prediction1.begin(), prediction1.end(),
1241 16 Mar 08 peter 99                          result1.begin())) {
1241 16 Mar 08 peter 100     suite.add(false);
1241 16 Mar 08 peter 101     suite.err() << "Difference to expected prediction too large\n";
1013 01 Feb 08 markus 102   }
1013 01 Feb 08 markus 103
1013 01 Feb 08 markus 104   //////////////////////////////////////////////////////////////////////////
1013 01 Feb 08 markus 105   // A test of predictions using unweighted training and weighted test data
1013 01 Feb 08 markus 106   //////////////////////////////////////////////////////////////////////////
1241 16 Mar 08 peter 107   suite.err() << "test of predictions using unweighted training and weighted test data\n";
1587 17 Oct 08 peter 108   utility::MatrixWeighted xw11(3,4);
1587 17 Oct 08 peter 109   xw11(0,0)=xw11(1,1)=xw11(2,2)=xw11(1,3)=utility::DataWeight(0,0);
1587 17 Oct 08 peter 110   std::copy(data1.begin(), data1.end(), utility::data_iterator(xw11.begin()));
1587 17 Oct 08 peter 111   classifier::MatrixLookupWeighted mlw1(xw11);
1587 17 Oct 08 peter 112   //classifier::MatrixLookupWeighted mlw1(data1,weights1);
4200 19 Aug 22 peter 113   ncc1.predict(mlw1,prediction1);
1013 01 Feb 08 markus 114   result1(0,2)=result1(0,3)=result1(1,0)=result1(1,1)=sqrt(15.0);
1241 16 Mar 08 peter 115   if (!suite.equal_range(prediction1.begin(), prediction1.end(),
1241 16 Mar 08 peter 116                          result1.begin())) {
1241 16 Mar 08 peter 117     suite.add(false);
1241 16 Mar 08 peter 118     suite.err() << "Difference to expected prediction too large\n";
1013 01 Feb 08 markus 119   }
1013 01 Feb 08 markus 120
1076 12 Feb 08 markus 121   //////////////////////////////////////////////////////////////////////////
1076 12 Feb 08 markus 122   // A test of predictions using weighted training resulting in NaN's
1076 12 Feb 08 markus 123   // in centroids and unweighted test data
1076 12 Feb 08 markus 124   //////////////////////////////////////////////////////////////////////////
1241 16 Mar 08 peter 125   suite.err() << "test of predictions using nan centroids and unweighted test data\n";
1587 17 Oct 08 peter 126   utility::MatrixWeighted xw12(3,4);
1587 17 Oct 08 peter 127   xw12(1,0)=xw12(1,1)=utility::DataWeight(0,0);
1587 17 Oct 08 peter 128   std::copy(data1.begin(), data1.end(), utility::data_iterator(xw12.begin()));
1587 17 Oct 08 peter 129   classifier::MatrixLookupWeighted mlw2(xw12);
1587 17 Oct 08 peter 130   //classifier::MatrixLookupWeighted mlw2(data1,weights2);
1157 26 Feb 08 markus 131   classifier::NCC<statistics::EuclideanDistance> ncc2;
1157 26 Feb 08 markus 132   ncc2.train(mlw2,target1);
4200 19 Aug 22 peter 133   ncc2.predict(ml1,prediction1);
1076 12 Feb 08 markus 134   result1(0,0)=result1(0,1)=result1(1,2)=result1(1,3)=sqrt(3.0);
1076 12 Feb 08 markus 135   result1(1,0)=result1(1,1)=sqrt(11.0);
1076 12 Feb 08 markus 136   result1(0,2)=result1(0,3)=sqrt(15.0);
4200 19 Aug 22 peter 137   if(!std::isnan(ncc2.centroids()(1,0)))
1241 16 Mar 08 peter 138     suite.add(false);
1241 16 Mar 08 peter 139   if (!suite.equal_range(prediction1.begin(), prediction1.end(),
1241 16 Mar 08 peter 140                          result1.begin())) {
1241 16 Mar 08 peter 141     suite.add(false);
1241 16 Mar 08 peter 142     suite.err() << "Difference to expected prediction too large\n";
1076 12 Feb 08 markus 143   }
1013 01 Feb 08 markus 144
1013 01 Feb 08 markus 145   //////////////////////////////////////////////////////////////////////////
1142 25 Feb 08 markus 146   // A test of predictions when a centroid has nan for all variables that a
1142 25 Feb 08 markus 147   // test sample has non-zero weights for.
1142 25 Feb 08 markus 148   //////////////////////////////////////////////////////////////////////////
1241 16 Mar 08 peter 149   suite.err() << "test of predictions using nan centroids and weighted test data\n";
1241 16 Mar 08 peter 150   suite.err() << "... using EuclideanDistance" << std::endl;
1587 17 Oct 08 peter 151   xw11(0,0).weight() = xw11(2,0).weight()=0;
1157 26 Feb 08 markus 152   classifier::NCC<statistics::EuclideanDistance> ncc3;
1157 26 Feb 08 markus 153   ncc3.train(mlw2,target1);
4200 19 Aug 22 peter 154   ncc3.predict(mlw1,prediction1);
1142 25 Feb 08 markus 155   if(!std::isnan(ncc3.centroids()(1,0))) {
1241 16 Mar 08 peter 156     suite.add(false);
1241 16 Mar 08 peter 157     suite.err() << "Training failed: expected nan in centroid" << std::endl;
1142 25 Feb 08 markus 158   }
1142 25 Feb 08 markus 159   if(!(std::isnan(prediction1(0,0)) &&
1241 16 Mar 08 peter 160        suite.equal(prediction1(1,0),sqrt(3.0)) &&
1241 16 Mar 08 peter 161        suite.equal(prediction1(0,1),sqrt(3.0)) &&
1241 16 Mar 08 peter 162        suite.equal(prediction1(1,1),sqrt(15.0)) &&
4200 19 Aug 22 peter 163        suite.equal(prediction1(0,2),sqrt(27.0)) )) {
1241 16 Mar 08 peter 164     suite.add(false);
1587 17 Oct 08 peter 165     if (!std::isnan(prediction1(0,0)))
1587 17 Oct 08 peter 166       suite.err() << "prediction1(0,0): " << prediction1(0,0) << "  "
1587 17 Oct 08 peter 167                   << "expected NaN\n";
1241 16 Mar 08 peter 168     suite.err() << "Test failed: predictions incorrect" << std::endl;
1142 25 Feb 08 markus 169   }
1241 16 Mar 08 peter 170   suite.err() << "... using PearsonDistance" << std::endl;;
1157 26 Feb 08 markus 171   classifier::NCC<statistics::PearsonDistance> ncc4;
1157 26 Feb 08 markus 172   ncc4.train(mlw2,target1);
4200 19 Aug 22 peter 173   ncc4.predict(mlw1,prediction1);
1142 25 Feb 08 markus 174   if(!std::isnan(ncc4.centroids()(1,0))) {
1241 16 Mar 08 peter 175     suite.add(false);
1241 16 Mar 08 peter 176     suite.err() << "Training failed: expected nan in centroid" << std::endl;
1142 25 Feb 08 markus 177   }
1142 25 Feb 08 markus 178   if(!(std::isnan(prediction1(0,0)) &&
1142 25 Feb 08 markus 179        std::isnan(prediction1(0,2)) &&
1142 25 Feb 08 markus 180        std::isnan(prediction1(1,0)) &&
1241 16 Mar 08 peter 181        suite.equal(prediction1(0,1), 0) &&
1241 16 Mar 08 peter 182        suite.equal(prediction1(1,2), 0) &&
4200 19 Aug 22 peter 183        suite.equal(prediction1(1,3), 0) &&
1241 16 Mar 08 peter 184        suite.equal(prediction1(0,3), 2.0) &&
1241 16 Mar 08 peter 185        suite.equal(prediction1(1,1), 2.0) )) {
4200 19 Aug 22 peter 186     suite.add(false);
1241 16 Mar 08 peter 187     suite.err() << "Test failed: predictions incorrect" << std::endl;
1142 25 Feb 08 markus 188   }
1142 25 Feb 08 markus 189
1143 25 Feb 08 markus 190   ////////////////////////////////////////////////////////////////
1143 25 Feb 08 markus 191   // A test of when a class has no training samples, should give nan
4200 19 Aug 22 peter 192   // in predictions.
1143 25 Feb 08 markus 193   ////////////////////////////////////////////////////////////////
1143 25 Feb 08 markus 194   //Keep only the second class in the training samples
1143 25 Feb 08 markus 195   std::vector<size_t> ind(2,2);
1143 25 Feb 08 markus 196   ind[1]=3;
1143 25 Feb 08 markus 197   classifier::Target target2(target1,utility::Index(ind));
1587 17 Oct 08 peter 198   classifier::MatrixLookupWeighted mlw3(xw12,
1484 09 Sep 08 peter 199                                         utility::Index(data1.rows()),
1484 09 Sep 08 peter 200                                         utility::Index(ind));
1157 26 Feb 08 markus 201   classifier::NCC<statistics::PearsonDistance> ncc5;
1157 26 Feb 08 markus 202   ncc5.train(mlw3,target2);
4200 19 Aug 22 peter 203   ncc5.predict(mlw1,prediction1);
4200 19 Aug 22 peter 204   if (!(std::isnan(prediction1(0,0)) && std::isnan(prediction1(0,1)) &&
1143 25 Feb 08 markus 205         std::isnan(prediction1(0,2)) && std::isnan(prediction1(0,3)) &&
1143 25 Feb 08 markus 206         std::isnan(prediction1(1,0)) &&
1241 16 Mar 08 peter 207         suite.equal(prediction1(1,1), 2.0) &&
1241 16 Mar 08 peter 208         suite.equal(prediction1(1,2),0) &&
1241 16 Mar 08 peter 209         suite.equal(prediction1(1,3),0) )) {
1241 16 Mar 08 peter 210     suite.err() << "Difference to expected prediction too large\n";
1241 16 Mar 08 peter 211     suite.add(false);
1143 25 Feb 08 markus 212   }
1142 25 Feb 08 markus 213
1142 25 Feb 08 markus 214   //////////////////////////////////////////////////////////////////////////
1013 01 Feb 08 markus 215   // A test of predictions using Sorlie data
1013 01 Feb 08 markus 216   //////////////////////////////////////////////////////////////////////////
1241 16 Mar 08 peter 217   suite.err() << "test with Sorlie data\n";
1251 03 Apr 08 peter 218   std::ifstream is(test::filename("data/sorlie_centroid_data.txt").c_str());
1587 17 Oct 08 peter 219   utility::MatrixWeighted data_weight(is,'\t');
504 01 Feb 06 markus 220   is.close();
504 01 Feb 06 markus 221
1251 03 Apr 08 peter 222   is.open(test::filename("data/sorlie_centroid_classes.txt").c_str());
504 01 Feb 06 markus 223   classifier::Target targets(is);
504 01 Feb 06 markus 224   is.close();
504 01 Feb 06 markus 225
1587 17 Oct 08 peter 226   classifier::MatrixLookupWeighted dataviewweighted(data_weight);
1157 26 Feb 08 markus 227    classifier::NCC<statistics::PearsonDistance> ncc;
1241 16 Mar 08 peter 228   suite.err() << "training...\n";
1157 26 Feb 08 markus 229   ncc.train(dataviewweighted,targets);
504 01 Feb 06 markus 230
632 05 Sep 06 markus 231   // Comparing the centroids to stored result
1251 03 Apr 08 peter 232   is.open(test::filename("data/sorlie_centroids.txt").c_str());
1121 22 Feb 08 peter 233   utility::Matrix centroids(is);
632 05 Sep 06 markus 234   is.close();
632 05 Sep 06 markus 235
632 05 Sep 06 markus 236   if(centroids.rows() != ncc.centroids().rows() ||
632 05 Sep 06 markus 237      centroids.columns() != ncc.centroids().columns()) {
1241 16 Mar 08 peter 238     suite.err() << "Error in the dimensionality of centroids\n";
4200 19 Aug 22 peter 239     suite.err() << "Nof rows: " << centroids.rows() << " expected: "
632 05 Sep 06 markus 240            << ncc.centroids().rows() << std::endl;
4200 19 Aug 22 peter 241     suite.err() << "Nof columns: " << centroids.columns() << " expected: "
632 05 Sep 06 markus 242            << ncc.centroids().columns() << std::endl;
632 05 Sep 06 markus 243   }
632 05 Sep 06 markus 244
1668 20 Dec 08 peter 245   if (!suite.equal_range_fix(centroids.begin(), centroids.end(),
1668 20 Dec 08 peter 246                              ncc.centroids().begin(), 1e-11)) {
1241 16 Mar 08 peter 247     suite.add(false);
1241 16 Mar 08 peter 248     suite.err() << "Difference to stored centroids too large\n";
632 05 Sep 06 markus 249   }
632 05 Sep 06 markus 250
1241 16 Mar 08 peter 251   suite.err() << "...predicting...\n";
1121 22 Feb 08 peter 252   utility::Matrix prediction;
634 05 Sep 06 markus 253   ncc.predict(dataviewweighted,prediction);
4200 19 Aug 22 peter 254
632 05 Sep 06 markus 255   // Comparing the prediction to stored result
1251 03 Apr 08 peter 256   is.open(test::filename("data/sorlie_centroid_predictions.txt").c_str());
1121 22 Feb 08 peter 257   utility::Matrix result(is,'\t');
504 01 Feb 06 markus 258   is.close();
504 01 Feb 06 markus 259
1668 20 Dec 08 peter 260   if (!suite.equal_range_fix(result.begin(), result.end(),
1668 20 Dec 08 peter 261                              prediction.begin(), 1e-11)) {
1241 16 Mar 08 peter 262     suite.add(false);
1241 16 Mar 08 peter 263     suite.err() << "Difference to stored prediction too large\n";
504 01 Feb 06 markus 264   }
2338 16 Oct 10 peter 265   compile_test(suite);
931 05 Oct 07 markus 266
1241 16 Mar 08 peter 267   return suite.return_value();
504 01 Feb 06 markus 268 }
1483 09 Sep 08 peter 269
2338 16 Oct 10 peter 270
2338 16 Oct 10 peter 271 void compile_test(test::Suite& suite)
2338 16 Oct 10 peter 272 {
2338 16 Oct 10 peter 273   if (false) {
2338 16 Oct 10 peter 274     boost::detail::dummy_constructor dummy;
2338 16 Oct 10 peter 275     test::distance_archetype distance(dummy);
2338 16 Oct 10 peter 276     classifier::NCC<test::distance_archetype> ncc(distance);
2338 16 Oct 10 peter 277   }
2338 16 Oct 10 peter 278 }
2338 16 Oct 10 peter 279
2338 16 Oct 10 peter 280
1483 09 Sep 08 peter 281 void predict_nan_data_unweighted_data(test::Suite& suite)
1483 09 Sep 08 peter 282 {
1483 09 Sep 08 peter 283   //////////////////////////////////////////////////////////////////////////
1483 09 Sep 08 peter 284   // A test of predictions using weighted training resulting in NaN's
1483 09 Sep 08 peter 285   // in centroids and unweighted test data
1483 09 Sep 08 peter 286   //////////////////////////////////////////////////////////////////////////
1483 09 Sep 08 peter 287   suite.err() << "test of predictions using nan centroids and unweighted test data\n";
1483 09 Sep 08 peter 288   utility::Matrix data1(3,4);
1483 09 Sep 08 peter 289   for(size_t i=0;i<3;i++) {
1483 09 Sep 08 peter 290     data1(i,0)=3-i;
1483 09 Sep 08 peter 291     data1(i,1)=5-i;
1483 09 Sep 08 peter 292     data1(i,2)=i+1;
1483 09 Sep 08 peter 293     data1(i,3)=i+3;
1483 09 Sep 08 peter 294   }
1587 17 Oct 08 peter 295   utility::MatrixWeighted xw(data1);
1483 09 Sep 08 peter 296   std::vector<std::string> vec1(4, "pos");
1483 09 Sep 08 peter 297   vec1[0]="neg";
1483 09 Sep 08 peter 298   vec1[1]="neg";
1483 09 Sep 08 peter 299
1483 09 Sep 08 peter 300   classifier::MatrixLookup ml1(data1);
1483 09 Sep 08 peter 301   classifier::Target target1(vec1);
1483 09 Sep 08 peter 302   utility::Matrix prediction1;
1483 09 Sep 08 peter 303   utility::Matrix result1(2,4);
1483 09 Sep 08 peter 304
1587 17 Oct 08 peter 305   xw(1,0).weight()=xw(1,1).weight()=0.0;
1483 09 Sep 08 peter 306
4200 19 Aug 22 peter 307
1587 17 Oct 08 peter 308   classifier::MatrixLookupWeighted mlw2(xw);
1483 09 Sep 08 peter 309   classifier::NCC<statistics::EuclideanDistance> ncc2;
1483 09 Sep 08 peter 310   ncc2.train(mlw2,target1);
4200 19 Aug 22 peter 311   ncc2.predict(ml1,prediction1);
1483 09 Sep 08 peter 312   result1(0,0)=result1(0,1)=result1(1,2)=result1(1,3)=sqrt(3.0);
1483 09 Sep 08 peter 313   result1(1,0)=result1(1,1)=sqrt(11.0);
1483 09 Sep 08 peter 314   result1(0,2)=result1(0,3)=sqrt(15.0);
4200 19 Aug 22 peter 315   if(!std::isnan(ncc2.centroids()(1,0)))
1483 09 Sep 08 peter 316     suite.add(false);
1483 09 Sep 08 peter 317   if (!suite.equal_range(prediction1.begin(), prediction1.end(),
1483 09 Sep 08 peter 318                          result1.begin())) {
1483 09 Sep 08 peter 319     suite.add(false);
1483 09 Sep 08 peter 320     suite.err() << "Difference to expected prediction too large\n";
1483 09 Sep 08 peter 321   }
1483 09 Sep 08 peter 322 }