diff --git a/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifier.h b/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifier.h index 9411f43e1a..4786dd854a 100644 --- a/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifier.h +++ b/Modules/Classification/CLVigraRandomForest/include/mitkVigraRandomForestClassifier.h @@ -1,109 +1,110 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkVigraRandomForestClassifier_h #define mitkVigraRandomForestClassifier_h #include #include //#include #include #include namespace mitk { class MITKCLVIGRARANDOMFOREST_EXPORT VigraRandomForestClassifier : public AbstractClassifier { public: mitkClassMacro(VigraRandomForestClassifier,AbstractClassifier) itkFactorylessNewMacro(Self) itkCloneMacro(Self) VigraRandomForestClassifier(); VigraRandomForestClassifier(const VigraRandomForestClassifier & other) { this->m_RandomForest = other.m_RandomForest; } ~VigraRandomForestClassifier(); void Train(const Eigen::MatrixXd &X, const Eigen::MatrixXi &Y); void OnlineTrain(const Eigen::MatrixXd &X, const Eigen::MatrixXi &Y); Eigen::MatrixXi Predict(const Eigen::MatrixXd &X); - Eigen::MatrixXi WeightedPredict(const Eigen::MatrixXd &X); + Eigen::MatrixXi PredictWeighted(const Eigen::MatrixXd &X); + bool SupportsPointWiseWeight(); bool SupportsPointWiseProbability(); void ConvertParameter(); void SetRandomForest(const vigra::RandomForest & rf) { m_RandomForest = rf; } const vigra::RandomForest & GetRandomForest() const { return m_RandomForest; } void UsePointWiseWeight(bool); void SetMaximumTreeDepth(int); void SetMinimumSplitNodeSize(int); void SetPrecision(double); void SetSamplesPerTree(double); void UseSampleWithReplacement(bool); void SetTreeCount(int); void SetWeightLambda(double); void SetTreeWeights(Eigen::MatrixXd weights); void SetTreeWeight(int treeId, double weight); Eigen::MatrixXd GetTreeWeights() const; void SetNthItems(const char *val, unsigned int idx); std::string GetNthItem(unsigned int idx); void SetItemList(std::vector); std::vector GetItemList(); void PrintParameter(std::ostream &str = std::cout); private: // *------------------- // * THREADING // *------------------- struct TrainingData; struct PredictionData; struct EigenToVigraTransform; struct Parameter; Eigen::MatrixXd m_TreeWeights; Parameter * m_Parameter; vigra::RandomForest m_RandomForest; static ITK_THREAD_RETURN_TYPE TrainTreesCallback(void *); static ITK_THREAD_RETURN_TYPE PredictCallback(void *); static ITK_THREAD_RETURN_TYPE WeightedPredictCallback(void *); static void WeightedPredict(PredictionData *data, vigra::MultiArrayView<2, double> & X, vigra::MultiArrayView<2, int> & Y, vigra::MultiArrayView<2, double> & P); }; } #endif //mitkVigraRandomForestClassifier_h diff --git a/Modules/Classification/CLVigraRandomForest/test/mitkVigraRandomForestTest.cpp b/Modules/Classification/CLVigraRandomForest/test/mitkVigraRandomForestTest.cpp index 7a96c9104c..32cbd5bb3a 100644 --- a/Modules/Classification/CLVigraRandomForest/test/mitkVigraRandomForestTest.cpp +++ b/Modules/Classification/CLVigraRandomForest/test/mitkVigraRandomForestTest.cpp @@ -1,285 +1,286 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkIOUtil.h" #include "itkArray2D.h" #include #include #include #include #include #include #include class mitkVigraRandomForestTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkVigraRandomForestTestSuite ); MITK_TEST(TrainThreadedDecisionForest_MatlabDataSet_shouldReturnTrue); + MITK_TEST(PredictWeightedDecisionForest_PredifinedForest_shouldReturnFalse); MITK_TEST(TrainThreadedDecisionForest_BreastCancerDataSet_shouldReturnTrue); CPPUNIT_TEST_SUITE_END(); private: typedef Eigen::Matrix MatrixDoubleType; typedef Eigen::Matrix MatrixIntType; Eigen::MatrixXd m_TrainingMatrixX; Eigen::MatrixXi m_TrainingLabelMatrixY; Eigen::MatrixXd m_TestXPredict; Eigen::MatrixXi m_TestYPredict; mitk::VigraRandomForestClassifier::Pointer classifier; public: /*Reading an file, which includes the trainingdataset and the testdataset, and convert the content of the file into an 2dim matrixpair. There are an delimiter, which separates the matrix into an trainingmatrix and testmatrix */ template std::pair,Eigen::Matrix >convertCSVToMatrix(const std::string &path, char delimiter,double range, bool isXMatrix) { typename itk::CSVArray2DFileReader::Pointer fr = itk::CSVArray2DFileReader::New(); fr->SetFileName(path); fr->SetFieldDelimiterCharacter(delimiter); fr->HasColumnHeadersOff(); fr->HasRowHeadersOff(); fr->Parse(); try{ fr->Update(); }catch(itk::ExceptionObject& ex){ cout << "Exception caught!" << std::endl; cout << ex << std::endl; } typename itk::CSVArray2DDataObject::Pointer p = fr->GetOutput(); unsigned int maxrowrange = p->GetMatrix().rows(); unsigned int c = p->GetMatrix().cols(); unsigned int percentRange = (unsigned int)(maxrowrange*range); if(isXMatrix == true){ Eigen::Matrix trainMatrixX(percentRange,c); Eigen::Matrix testMatrixXPredict(maxrowrange-percentRange,c); - for(int row = 0; row < percentRange; row++){ - for(int col = 0; col < c; col++){ + for(unsigned int row = 0; row < percentRange; row++){ + for(unsigned int col = 0; col < c; col++){ trainMatrixX(row,col) = p->GetData(row,col); } } - for(int row = percentRange; row < maxrowrange; row++){ - for(int col = 0; col < c; col++){ + for(unsigned int row = percentRange; row < maxrowrange; row++){ + for(unsigned int col = 0; col < c; col++){ testMatrixXPredict(row-percentRange,col) = p->GetData(row,col); } } return std::make_pair(trainMatrixX,testMatrixXPredict); } - else if(isXMatrix == false){ + else{ Eigen::Matrix trainLabelMatrixY(percentRange,c); Eigen::Matrix testMatrixYPredict(maxrowrange-percentRange,c); - for(int row = 0; row < percentRange; row++){ - for(int col = 0; col < c; col++){ + for(unsigned int row = 0; row < percentRange; row++){ + for(unsigned int col = 0; col < c; col++){ trainLabelMatrixY(row,col) = p->GetData(row,col); } } - for(int row = percentRange; row < maxrowrange; row++){ - for(int col = 0; col < c; col++){ + for(unsigned int row = percentRange; row < maxrowrange; row++){ + for(unsigned int col = 0; col < c; col++){ testMatrixYPredict(row-percentRange,col) = p->GetData(row,col); } } - return std::make_pair(trainLabelMatrixY,testMatrixYPredict); } + } /* Reading an csv-data and transfer the included datas into an matrix. */ template Eigen::Matrix readCsvData(const std::string &path, char delimiter) { typename itk::CSVArray2DFileReader::Pointer fr = itk::CSVArray2DFileReader::New(); fr->SetFileName(path); fr->SetFieldDelimiterCharacter(delimiter); fr->HasColumnHeadersOff(); fr->HasRowHeadersOff(); fr->Parse(); try{ fr->Update(); }catch(itk::ExceptionObject& ex){ cout << "Exception caught!" << std::endl; cout << ex << std::endl; } typename itk::CSVArray2DDataObject::Pointer p = fr->GetOutput(); unsigned int maxrowrange = p->GetMatrix().rows(); unsigned int maxcols = p->GetMatrix().cols(); Eigen::Matrix matrix(maxrowrange,maxcols); for(int rows = 0; rows < maxrowrange; rows++){ for(int cols = 0; cols < maxcols; cols++ ){ matrix(rows,cols) = p->GetData(rows,cols); } } return matrix; } /* Write the content of the array into an own csv-data in the following sequence: root.csv: 1 2 3 0 0 4 writen.csv: 1 1:2 2:3 3:0 4:0 5:4 */ template void writeMatrixToCsv(Eigen::Matrix paramMatrix,const std::string &path) { std::ofstream outputstream (path,std::ofstream::out); // 682 if(outputstream.is_open()){ for(int i = 0; i < paramMatrix.rows(); i++){ outputstream << paramMatrix(i,0); for(int j = 1; j < 11; j++){ outputstream << " " << j << ":" << paramMatrix(i,j); } outputstream << endl; } outputstream.close(); } else{ cout << "Unable to write into CSV" << endl; } } /* Train the classifier with an exampledataset of mattlab. Note: The included data are gaußan normaldistributed. */ void TrainThreadedDecisionForest_MatlabDataSet_shouldReturnTrue() { /* Declarating an featurematrixdataset, the first matrix of the matrixpair is the trainingmatrix and the second one is the testmatrix.*/ std::pair matrixDouble; matrixDouble = convertCSVToMatrix(GetTestDataFilePath("Classification/FeaturematrixMatlab.csv"),';',0.5,true); m_TrainingMatrixX = matrixDouble.first; m_TestXPredict = matrixDouble.second; /* The declaration of the labelmatrixdataset is equivalent to the declaration of the featurematrixdataset.*/ std::pair matrixInt; matrixInt = convertCSVToMatrix(GetTestDataFilePath("Classification/LabelmatrixMatlab.csv"),';',0.5,false); m_TrainingLabelMatrixY = matrixInt.first; m_TestYPredict = matrixInt.second; classifier = mitk::VigraRandomForestClassifier::New(); /* Train the classifier, by giving trainingdataset for the labels and features. The result in an colunmvector of the labels.*/ classifier->Train(m_TrainingMatrixX,m_TrainingLabelMatrixY); Eigen::MatrixXi classes = classifier->Predict(m_TestXPredict); /* Testing the matching between the calculated colunmvector and the result of the RandomForest */ unsigned int maxrows = classes.rows(); bool isYPredictVector = false; int count = 0; - for(int i= 0; i < maxrows; i++){ + for(unsigned int i= 0; i < maxrows; i++){ if(classes(i,0) == m_TestYPredict(i,0)){ isYPredictVector = true; count++; } } MITK_INFO << 100*count/(double)(maxrows) << "%"; MITK_TEST_CONDITION(isIntervall(m_TestYPredict,classes,97,99),"Testvalue is in range."); } // Method for intervalltesting template bool isIntervall(Eigen::Matrix expected, Eigen::Matrix actual, double lowrange, double toprange) { bool isInIntervall = false; int count = 0; unsigned int rowRange = expected.rows(); unsigned int colRange = expected.cols(); - for(int i = 0; i < rowRange; i++){ - for(int j = 0; j < colRange; j++){ + for(unsigned int i = 0; i < rowRange; i++){ + for(unsigned int j = 0; j < colRange; j++){ if(expected(i,j) == actual(i,j)){ count++; } } double valueOfMatch = 100*count/(double)(rowRange); if((lowrange <= valueOfMatch) && (toprange >= valueOfMatch)){ isInIntervall = true; } } return isInIntervall; } /* Train the classifier with the dataset of breastcancer patients from the LibSVM Libary */ void TrainThreadedDecisionForest_BreastCancerDataSet_shouldReturnTrue() { /* Declarating an featurematrixdataset, the first matrix of the matrixpair is the trainingmatrix and the second one is the testmatrix.*/ std::pair matrixDouble; matrixDouble = convertCSVToMatrix(GetTestDataFilePath("Classification/FeaturematrixBreastcancer.csv"),';',0.5,true); m_TrainingMatrixX = matrixDouble.first; m_TestXPredict = matrixDouble.second; /* The declaration of the labelmatrixdataset is equivalent to the declaration of the featurematrixdataset.*/ std::pair matrixInt; matrixInt = convertCSVToMatrix(GetTestDataFilePath("Classification/LabelmatrixBreastcancer.csv"),';',0.5,false); m_TrainingLabelMatrixY = matrixInt.first; m_TestYPredict = matrixInt.second; classifier = mitk::VigraRandomForestClassifier::New(); /* Train the classifier, by giving trainingdataset for the labels and features. The result in an colunmvector of the labels.*/ classifier->Train(m_TrainingMatrixX,m_TrainingLabelMatrixY); Eigen::MatrixXi classes = classifier->Predict(m_TestXPredict); /* Testing the matching between the calculated colunmvector and the result of the RandomForest */ unsigned int maxrows = classes.rows(); bool isYPredictVector = false; int count = 0; - for(int i= 0; i < maxrows; i++){ + for(unsigned int i= 0; i < maxrows; i++){ if(classes(i,0) == m_TestYPredict(i,0)){ isYPredictVector = true; count++; } } MITK_INFO << 100*count/(double)(maxrows) << "%"; MITK_TEST_CONDITION(isIntervall(m_TestYPredict,classes,97,99),"Testvalue is in range."); } void TestThreadedDecisionForest() { } }; MITK_TEST_SUITE_REGISTRATION(mitkVigraRandomForest) \ No newline at end of file