int main (int argc, const char * argv[])
{

    //We are going to use the Iris dataset, you can find more about the orginal dataset at: http://en.wikipedia.org/wiki/Iris_flower_data_set
    
    //Create a new instance of LabelledClassificationData to hold the training data
    LabelledClassificationData trainingData;
    
    //Load the training dataset from a file, the file should be in the same directory as this program
    if( !trainingData.loadDatasetFromFile("IrisData.txt") ){
        cout << "Failed to load Iris data from file!\n";
        return EXIT_FAILURE;
    }
    
    //Print some basic stats about the dataset we have loaded
    trainingData.printStats();
    
    //Partition the training dataset into a training dataset and test dataset
    //We will use 60% of the data to train the algorithm and 40% of the data to test it
    //The true parameter flags that we want to use stratified sampling, which means there 
    //should be an equal class distribution between the training and test datasets
    LabelledClassificationData testData = trainingData.partition( 60, true );
    
    //Setup the gesture recognition pipeline
    GestureRecognitionPipeline pipeline;
    
    //Add a KNN classification algorithm as the main classifier with a K value of 10
    pipeline.setClassifier( KNN(10) );
    
    //Train the KNN algorithm using the training dataset
    if( !pipeline.train( trainingData ) ){
        cout << "Failed to train the pipeline!\n";
        return EXIT_FAILURE;
    }
    
    //Test the KNN model using the test dataset
    if( !pipeline.test( testData ) ){
        cout << "Failed to test the pipeline!\n";
        return EXIT_FAILURE;
    }
    
    //Print some metrics about how successful the classification was
    //Print the accuracy
    cout << "The classification accuracy was: " << pipeline.getTestAccuracy() << "%\n" << endl;
    
    //Print the precision for each class
    for(UINT k=0; k<pipeline.getNumClassesInModel(); k++){
        UINT classLabel = pipeline.getClassLabels()[k];
        double classPrecision = pipeline.getTestPrecision( classLabel );
        cout << "The precision for class " << classLabel << " was " << classPrecision << endl;
    }
    cout << endl;
    
    //Print the recall for each class
    for(UINT k=0; k<pipeline.getNumClassesInModel(); k++){
        UINT classLabel = pipeline.getClassLabels()[k];
        double classRecall = pipeline.getTestRecall( classLabel );
        cout << "The recall for class " << classLabel << " was " << classRecall << endl;
    }
    cout << endl;
    
    //Print the confusion matrix
    Matrix< double > confusionMatrix = pipeline.getTestConfusionMatrix();
    cout << "Confusion Matrix: \n";
    for(UINT i=0; i<confusionMatrix.getNumRows(); i++){
        for(UINT j=0; j<confusionMatrix.getNumCols(); j++){
            cout << confusionMatrix[i][j] << "\t";
        }
        cout << endl;
        
    }
    cout << endl;

    return EXIT_SUCCESS;
}
int main (int argc, const char * argv[])
{

    //Create a new KNN classifier with a K value of 10
    KNN knn(10);
    knn.setNullRejectionCoeff( 10 );
    knn.enableScaling( true );
    knn.enableNullRejection( true );
    
    //Train the classifier with some training data
    LabelledClassificationData trainingData;
    
    if( !trainingData.loadDatasetFromFile("KNNTrainingData.txt") ){
        cout << "Failed to load training data!\n";
        return EXIT_FAILURE;
    }
    
    //Use 20% of the training dataset to create a test dataset
    LabelledClassificationData testData = trainingData.partition( 80 );
    
    //Train the classifier
    bool trainSuccess = knn.train( trainingData );
    
    if( !trainSuccess ){
        cout << "Failed to train classifier!\n";
        return EXIT_FAILURE;
    }
    
    //Save the knn model to a file
    bool saveSuccess = knn.saveModelToFile("KNNModel.txt");
    
    if( !saveSuccess ){
        cout << "Failed to save the classifier model!\n";
        return EXIT_FAILURE;
    }
    
    //Load the knn model from a file
    bool loadSuccess = knn.loadModelFromFile("KNNModel.txt");
    
    if( !loadSuccess ){
        cout << "Failed to load the classifier model!\n";
        return EXIT_FAILURE;
    }
    
    //Use the test dataset to test the KNN model
    double accuracy = 0;
    for(UINT i=0; i<testData.getNumSamples(); i++){
        //Get the i'th test sample
        UINT classLabel = testData[i].getClassLabel();
        vector< double > inputVector = testData[i].getSample();
        
        //Perform a prediction using the classifier
        bool predictSuccess = knn.predict( inputVector );
        
        if( !predictSuccess ){
            cout << "Failed to perform prediction for test sampel: " << i <<"\n";
            return EXIT_FAILURE;
        }
        
        //Get the predicted class label
        UINT predictedClassLabel = knn.getPredictedClassLabel();
        vector< double > classLikelihoods = knn.getClassLikelihoods();
        vector< double > classDistances = knn.getClassDistances();
        
        //Update the accuracy
        if( classLabel == predictedClassLabel ) accuracy++;
        
        cout << "TestSample: " << i <<  " ClassLabel: " << classLabel << " PredictedClassLabel: " << predictedClassLabel << endl;
    }
    
    cout << "Test Accuracy: " << accuracy/double(testData.getNumSamples())*100.0 << "%" << endl;
    
    return EXIT_SUCCESS;

}
int main (int argc, const char * argv[])
{
    //Load some training data from a file
    LabelledClassificationData trainingData;
    
    if( !trainingData.loadDatasetFromFile("HelloWorldTrainingData.txt") ){
        cout << "ERROR: Failed to load training data from file\n";
        return EXIT_FAILURE;
    }
    
    cout << "Data Loaded\n";
    
    //Print out some stats about the training data
    trainingData.printStats();
    
    //Partition the training data into a training dataset and a test dataset. 80 means that 80% 
    //of the data will be used for the training data and 20% will be returned as the test dataset
    LabelledClassificationData testData = trainingData.partition(80);
    
    //Create a new Gesture Recognition Pipeline using an Adaptive Naive Bayes Classifier
    GestureRecognitionPipeline pipeline;
    pipeline.setClassifier( ANBC() );
    
    //Train the pipeline using the training data
    if( !pipeline.train( trainingData ) ){
        cout << "ERROR: Failed to train the pipeline!\n";
        return EXIT_FAILURE;
    }
    
    //Test the pipeline using the test data
    if( !pipeline.test( testData ) ){
        cout << "ERROR: Failed to test the pipeline!\n";
        return EXIT_FAILURE;
    }
    
    //Print some stats about the testing
    cout << "Test Accuracy: " << pipeline.getTestAccuracy() << endl;
    
    cout << "Precision: ";
    for(UINT k=0; k<pipeline.getNumClassesInModel(); k++){
        UINT classLabel = pipeline.getClassLabels()[k];
        cout << "\t" << pipeline.getTestPrecision(classLabel);
    }cout << endl;
    
    cout << "Recall: ";
    for(UINT k=0; k<pipeline.getNumClassesInModel(); k++){
        UINT classLabel = pipeline.getClassLabels()[k];
        cout << "\t" << pipeline.getTestRecall(classLabel);
    }cout << endl;
    
    cout << "FMeasure: ";
    for(UINT k=0; k<pipeline.getNumClassesInModel(); k++){
        UINT classLabel = pipeline.getClassLabels()[k];
        cout << "\t" << pipeline.getTestFMeasure(classLabel);
    }cout << endl;
    
    Matrix< double > confusionMatrix = pipeline.getTestConfusionMatrix();
    cout << "ConfusionMatrix: \n";
    for(UINT i=0; i<confusionMatrix.getNumRows(); i++){
        for(UINT j=0; j<confusionMatrix.getNumCols(); j++){
            cout << confusionMatrix[i][j] << "\t";
        }cout << endl;
    }
    
    return EXIT_SUCCESS;
}