bool combineModels( CommandLineParser &parser ){ infoLog << "Combining models..." << endl; string directoryPath = ""; string modelFilename = ""; if( !parser.get("data-dir",directoryPath) ){ errorLog << "Failed to parse data-directory from command line! You can set the data-directory using the --data-dir option." << endl; printUsage(); return false; } //Get the filename if( !parser.get("model-filename",modelFilename) ){ errorLog << "Failed to parse filename from command line! You can set the model filename using the --model." << endl; printUsage(); return false; } Vector< string > files; infoLog << "- Parsing data directory: " << directoryPath << endl; //Parse the directory to get all the csv files if( !Util::parseDirectory( directoryPath, ".grt", files ) ){ errorLog << "Failed to parse data directory!" << endl; return false; } RandomForests forest; //Used to validate the random forest type GestureRecognitionPipeline *mainPipeline = NULL; // Points to the first valid pipeline that all the models will be merged to Vector< GestureRecognitionPipeline* > pipelineBuffer; //Stores the pipeline for each file that is loaded unsigned int inputVectorSize = 0; //Set to zero to mark we haven't loaded any models yet const unsigned int numFiles = files.getSize(); bool mainPipelineSet = false; bool combineModelsSuccessful = false; pipelineBuffer.reserve( numFiles ); //Loop over the files, load them, and add valid random forest pipelines to the pipelineBuffer so they can be combined with the mainPipeline for(unsigned int i=0; i<numFiles; i++){ infoLog << "- Loading model " << files[i] << ". File " << i+1 << " of " << numFiles << endl; GestureRecognitionPipeline *pipeline = new GestureRecognitionPipeline; if( pipeline->load( files[i] ) ){ infoLog << "- Pipeline loaded. Number of input dimensions: " << pipeline->getInputVectorDimensionsSize() << endl; if( pipelineBuffer.size() == 0 ){ inputVectorSize = pipeline->getInputVectorDimensionsSize(); } if( pipeline->getInputVectorDimensionsSize() != inputVectorSize ){ warningLog << "- Pipeline " << i+1 << " input vector size does not match the size of the first pipeline!" << endl; }else{ Classifier *classifier = pipeline->getClassifier(); if( classifier ){ if( classifier->getClassifierType() == forest.getClassifierType() ){ //Validate the classifier is a random forest if( !mainPipelineSet ){ mainPipelineSet = true; mainPipeline = pipeline; }else pipelineBuffer.push_back( pipeline ); }else{ warningLog << "- Pipeline " << i+1 << " does not contain a random forest classifer! Classifier type: " << classifier->getClassifierType() << endl; } } } }else{ warningLog << "- WARNING: Failed to load model from file: " << files[i] << endl; } } if( mainPipelineSet ){ //Combine the random forest models with the main pipeline model const unsigned int numPipelines = pipelineBuffer.getSize(); RandomForests *mainForest = mainPipeline->getClassifier< RandomForests >(); for(unsigned int i=0; i<numPipelines; i++){ infoLog << "- Combing model " << i+1 << " of " << numPipelines << " with main model..." << endl; RandomForests *f = pipelineBuffer[i]->getClassifier< RandomForests >(); if( !mainForest->combineModels( *f ) ){ warningLog << "- WARNING: Failed to combine model " << i+1 << " with the main model!" << endl; } } if( mainPipeline->getTrained() ){ infoLog << "- Saving combined pipeline to file..." << endl; combineModelsSuccessful = mainPipeline->save( modelFilename ); } }else{ errorLog << "Failed to combined models, no models were loaded!" << endl; } //Cleanup the pipeline buffer for(unsigned int i=0; i<pipelineBuffer.getSize(); i++){ delete pipelineBuffer[i]; pipelineBuffer[i] = NULL; } return combineModelsSuccessful; }
bool computeFeatureWeights( CommandLineParser &parser ){ infoLog << "Computing feature weights..." << endl; string resultsFilename = ""; string modelFilename = ""; bool combineWeights = false; //Get the model filename if( !parser.get("model-filename",modelFilename) ){ errorLog << "Failed to parse filename from command line! You can set the model filename using the --model." << endl; printUsage(); return false; } //Get the results filename if( !parser.get("filename",resultsFilename) ){ errorLog << "Failed to parse results filename from command line! You can set the results filename using the -f." << endl; printUsage(); return false; } //Get the results filename parser.get("combine-weights",combineWeights); //Load the model GestureRecognitionPipeline pipeline; if( !pipeline.load( modelFilename ) ){ errorLog << "Failed to load model from file: " << modelFilename << endl; printUsage(); return false; } //Make sure the pipeline contains a random forest model and that it is trained RandomForests *forest = pipeline.getClassifier< RandomForests >(); if( !forest ){ errorLog << "Model loaded, but the pipeline does not contain a RandomForests classifier!" << endl; printUsage(); return false; } if( !forest->getTrained() ){ errorLog << "Model loaded, but the RandomForests classifier is not trained!" << endl; printUsage(); return false; } //Compute the feature weights if( combineWeights ){ VectorFloat weights = forest->getFeatureWeights(); if( weights.getSize() == 0 ){ errorLog << "Failed to compute feature weights!" << endl; printUsage(); return false; } //Save the results to a file fstream file; file.open( resultsFilename.c_str(), fstream::out ); const unsigned int N = weights.getSize(); for(unsigned int i=0; i<N; i++){ file << weights[i] << endl; } file.close(); }else{ double norm = 0.0; const unsigned int K = forest->getForestSize(); const unsigned int N = forest->getNumInputDimensions(); VectorFloat tmp( N, 0.0 ); MatrixDouble weights(K,N); for(unsigned int i=0; i<K; i++){ DecisionTreeNode *tree = forest->getTree(i); tree->computeFeatureWeights( tmp ); norm = 1.0 / Util::sum( tmp ); for(unsigned int j=0; j<N; j++){ tmp[j] *= norm; weights[i][j] = tmp[j]; tmp[j] = 0; } } //Save the results to a file weights.save( resultsFilename ); } return true; }
bool test( CommandLineParser &parser ){ infoLog << "Testing model..." << endl; string datasetFilename = ""; string modelFilename = ""; string resultsFilename = ""; //Get the model filename if( !parser.get("model-filename",modelFilename) ){ errorLog << "Failed to parse model filename from command line! You can set the model filename using the -m." << endl; printUsage(); return false; } //Get the filename if( !parser.get("dataset-filename",datasetFilename) ){ errorLog << "Failed to parse dataset filename from command line! You can set the dataset filename using the -f." << endl; printUsage(); return false; } //Get the model filename parser.get("results-filename",resultsFilename,string("results.txt")); //Load the pipeline from a file GestureRecognitionPipeline pipeline; infoLog << "- Loading model..." << endl; if( !pipeline.load( modelFilename ) ){ errorLog << "Failed to load model from file: " << modelFilename << endl; printUsage(); return false; } infoLog << "- Model loaded!" << endl; //Load the data to test the classifier ClassificationData data; infoLog << "- Loading Training Data..." << endl; if( !data.load( datasetFilename ) ){ errorLog << "Failed to load data!\n"; return false; } const unsigned int N = data.getNumDimensions(); infoLog << "- Num training samples: " << data.getNumSamples() << endl; infoLog << "- Num dimensions: " << N << endl; infoLog << "- Num classes: " << data.getNumClasses() << endl; //Test the classifier if( !pipeline.test( data ) ){ errorLog << "Failed to test pipeline!" << endl; return false; } infoLog << "- Test complete in " << pipeline.getTestTime()/1000.0 << " seconds with and accuracy of: " << pipeline.getTestAccuracy() << endl; return saveResults( pipeline, resultsFilename ); }