bool MatrixDouble::subtract(const MatrixDouble &b){
    
    if( b.getNumRows() != rows ){
        errorLog << "subtract(const MatrixDouble &b) - Failed to add matrix! The rows do not match!" << endl;
        errorLog << " rows: " << rows << " b rows: " << b.getNumRows() << endl;
        return false;
    }
    
    if( b.getNumCols() != cols ){
        errorLog << "subtract(const MatrixDouble &b) - Failed to add matrix! The rows do not match!" << endl;
        errorLog << "  cols: " << cols << " b cols: " << b.getNumCols() << endl;
        return false;
    }
    
    unsigned int i,j;
    
    //Using direct pointers really helps speed up the computation time
    double **pb = b.getDataPointer();
    
    for(i=0; i<rows; i++){
        for(j=0; j<cols; j++){
            dataPtr[i*cols+j] -= pb[i][j];
        }
    }
    
    return true;
}
bool MatrixDouble::subtract(const MatrixDouble &a,const MatrixDouble &b){
    
    const unsigned int M = a.getNumRows();
    const unsigned int N = a.getNumCols();
    
    if( M != b.getNumRows() ){
        errorLog << "subtract(const MatrixDouble &a,const MatrixDouble &b) - Failed to add matrix! The rows do not match!";
        errorLog << " a rows: " << M << " b rows: " << b.getNumRows() << endl;
        return false;
    }
    
    if( N != b.getNumCols() ){
        errorLog << "subtract(const MatrixDouble &a,const MatrixDouble &b) - Failed to add matrix! The columns do not match!";
        errorLog << " a cols: " << N << " b cols: " << b.getNumCols() << endl;
        return false;
    }
    
    resize( M, N );
    
    UINT i,j;
    
    //Using direct pointers really helps speed up the computation time
    double **pa = a.getDataPointer();
    double **pb = b.getDataPointer();
    
    for(i=0; i<M; i++){
        for(j=0; j<N; j++){
            dataPtr[i*cols+j] = pa[i][j] - pb[i][j];
        }
    }
    
    return true;
}
Пример #3
0
void DTW::znormData(MatrixDouble &data,MatrixDouble &normData){

	const UINT R = data.getNumRows();
	const UINT C = data.getNumCols();

    if( normData.getNumRows() != R || normData.getNumCols() != C ){
        normData.resize(R,C);
    }

	for(UINT j=0; j<C; j++){
		double mean = 0.0;
		double stdDev = 0.0;

		//Calculate Mean
		for(UINT i=0; i<R; i++) mean += data[i][j];
		mean /= double(R);

		//Calculate Std Dev
		for(UINT i=0; i<R; i++)
			stdDev += SQR(data[i][j]-mean);
		stdDev = sqrt( stdDev / (R - 1.0) );

		if(constrainZNorm && stdDev < 0.01){
			//Normalize the data to 0 mean
		    for(UINT i=0; i<R; i++)
			normData[i][j] = (data[i][j] - mean);
		}else{
			//Normalize the data to 0 mean and standard deviation of 1
		    for(UINT i=0; i<R; i++)
			normData[i][j] = (data[i][j] - mean) / stdDev;
		}
	}
}
bool BernoulliRBM::predict_(MatrixDouble &inputData,MatrixDouble &outputData,const UINT rowIndex){
    
    if( !trained ){
        errorLog << "predict_(MatrixDouble &inputData,MatrixDouble &outputData,const UINT rowIndex) - Failed to run prediction - the model has not been trained." << endl;
        return false;
    }
    
    if( inputData.getNumCols() != numVisibleUnits ){
        errorLog << "predict_(MatrixDouble &inputData,MatrixDouble &outputData,const UINT rowIndex) -";
        errorLog << " Failed to run prediction - the number of columns in the input matrix (" << inputData.getNumCols() << ")";
        errorLog << " does not match the number of visible units (" << numVisibleUnits << ")." << endl;
        return false;
    }
    
    if( outputData.getNumCols() != numHiddenUnits ){
        errorLog << "predict_(MatrixDouble &inputData,MatrixDouble &outputData,const UINT rowIndex) -";
        errorLog << " Failed to run prediction - the number of columns in the output matrix (" << outputData.getNumCols() << ")";
        errorLog << " does not match the number of hidden units (" << numHiddenUnits << ")." << endl;
        return false;
    }
    
    //Propagate the data up through the RBM
    double x = 0.0;
    for(UINT j=0; j<numHiddenUnits; j++){
        x = 0;
        for(UINT i=0; i<numVisibleUnits; i++) {
            x += weightsMatrix[j][i] * inputData[rowIndex][i];
        }
        outputData[rowIndex][j] = sigmoid( x + hiddenLayerBias[j] ); //This gives P( h_j = 1 | input )
    }
    
    return true;
}
bool MatrixDouble::multiple(const MatrixDouble &a,const MatrixDouble &b,const bool aTranspose){
    
    const unsigned int M = !aTranspose ? a.getNumRows() : a.getNumCols();
    const unsigned int N = !aTranspose ? a.getNumCols() : a.getNumRows();
    const unsigned int K = b.getNumRows();
    const unsigned int L = b.getNumCols();
    
    if( N != K ) {
        errorLog << "multiple(const MatrixDouble &a,const MatrixDouble &b,const bool aTranspose) - The number of rows in a (" << K << ") does not match the number of columns in matrix b (" << N << ")" << std::endl;
        return false;
    }
    
    if( !resize( M, L ) ){
        errorLog << "multiple(const MatrixDouble &b,const MatrixDouble &c,const bool bTranspose) - Failed to resize matrix!" << endl;
        return false;
    }
    
    unsigned int i, j, k = 0;
    
    //Using direct pointers really helps speed up the computation time
    double **pa = a.getDataPointer();
    double **pb = b.getDataPointer();
    
    if( aTranspose ){
        
        for(j=0; j<L; j++){
            for(i=0; i<M; i++){
                dataPtr[i*cols+j] = 0;
                for(k=0; k<K; k++){
                    dataPtr[i*cols+j] += pa[k][i] * pb[k][j];
                }
            }
        }
        
    }else{
        
        for(j=0; j<L; j++){
            for(i=0; i<M; i++){
                dataPtr[i*cols+j] = 0;
                for(k=0; k<K; k++){
                    dataPtr[i*cols+j] += pa[i][k] * pb[k][j];
                }
            }
        }
        
    }
    
    return true;
}
Пример #6
0
void DTW::scaleData(MatrixDouble &data,MatrixDouble &scaledData){

	const UINT R = data.getNumRows();
	const UINT C = data.getNumCols();

    if( scaledData.getNumRows() != R || scaledData.getNumCols() != C ){
        scaledData.resize(R, C);
    }

	//Scale the data using the min and max values
	for(UINT i=0; i<R; i++)
		for(UINT j=0; j<C; j++)
			scaledData[i][j] = scale(data[i][j],rangesBuffer[j].minValue,rangesBuffer[j].maxValue,0.0,1.0);

}
MatrixDouble MatrixDouble::multiple(const MatrixDouble &b) const{
    
    const unsigned int M = rows;
    const unsigned int N = cols;
    const unsigned int K = b.getNumRows();
    const unsigned int L = b.getNumCols();
    
    if( N != K ) {
        errorLog << "multiple(MatrixDouble b) - The number of rows in b (" << K << ") does not match the number of columns in this matrix (" << N << ")" << std::endl;
        return MatrixDouble();
    }
    
    MatrixDouble c(M,L);
    double **pb = b.getDataPointer();
    double **pc = c.getDataPointer();
    
    unsigned int i,j,k = 0;
    for(i=0; i<M; i++){
        for(j=0; j<L; j++){
            pc[i][j] = 0;
            for(k=0; k<K; k++){
                pc[i][j] += dataPtr[i*cols+k] * pb[k][j];
            }
        }
    }
    
    return c;
}
Пример #8
0
bool KMeans::setClusters(const MatrixDouble &clusters){
    clear();
    numClusters = clusters.getNumRows();
    numInputDimensions = clusters.getNumCols();
    this->clusters = clusters;
    return true;
}
//Init the model with a pre-trained a, b, and pi matrices
DiscreteHiddenMarkovModel::DiscreteHiddenMarkovModel(const MatrixDouble &a,const MatrixDouble &b,const VectorDouble &pi,const UINT modelType,const UINT delta){
    
    numStates = 0;
    numSymbols = 0;
    numRandomTrainingIterations = 5;
	maxNumEpochs = 100;
	cThreshold = -1000;
	logLikelihood = 0.0;
	minChange = 1.0e-5;
    
    debugLog.setProceedingText("[DEBUG DiscreteHiddenMarkovModel]");
    errorLog.setProceedingText("[ERROR DiscreteHiddenMarkovModel]");
    warningLog.setProceedingText("[WARNING DiscreteHiddenMarkovModel]");
    trainingLog.setProceedingText("[TRAINING DiscreteHiddenMarkovModel]");

    if( a.getNumRows() == a.getNumRows() && a.getNumRows() == b.getNumRows() && a.getNumRows() == pi.size() ){
        this->a = a;
        this->b = b;
        this->pi = pi;
        this->modelType = modelType;
        this->delta = delta;
        numStates = b.getNumRows();
        numSymbols = b.getNumCols();
        trained = true;
    }else{
        errorLog << "DiscreteHiddenMarkovModel(...) - The a,b,pi sizes are invalid!" << endl;
    }
}
Пример #10
0
MatrixDouble MatrixDouble::multiple(const MatrixDouble &b){
    
    const unsigned int M = rows;
    const unsigned int N = cols;
    const unsigned int K = (unsigned int)b.getNumRows();
    const unsigned int L = (unsigned int)b.getNumCols();
    
    if( N != K ) {
        warningLog << "multiple(MatrixDouble b) - The number of rows in b (" << b.getNumRows() << ") does not match the number of columns in this matrix (" << N << ")" << std::endl;
        return MatrixDouble();
    }
    
    MatrixDouble c(M,L);
    
    for(unsigned int i=0; i<M; i++){
        for(unsigned int j=0; j<L; j++){
            c[i][j] = 0;
            for(unsigned int k=0; k<K; k++){
                c[i][j] += dataPtr[i][k] * b[k][j];
            }
        }
    }
    
    return c;
}
Пример #11
0
bool RBMQuantizer::train_(MatrixDouble &trainingData){
    
    //Clear any previous model
    clear();
    
    if( trainingData.getNumRows() == 0 ){
        errorLog << "train_(MatrixDouble &trainingData) - Failed to train quantizer, the training data is empty!" << endl;
        return false;
    }
    
    //Train the RBM model
    rbm.setNumHiddenUnits( numClusters );
    rbm.setLearningRate( learningRate );
    rbm.setMinNumEpochs( minNumEpochs );
    rbm.setMaxNumEpochs( maxNumEpochs );
    rbm.setMinChange( minChange );
    
    if( !rbm.train_( trainingData ) ){
        errorLog << "train_(MatrixDouble &trainingData) - Failed to train quantizer!" << endl;
        return false;
    }
    
    //Flag that the feature vector is now initalized
    initialized = true;
    trained = true;
    numInputDimensions = trainingData.getNumCols();
    numOutputDimensions = 1; //This is always 1 for the quantizer
    featureVector.resize(numOutputDimensions,0);
    quantizationDistances.resize(numClusters,0);

    return true;
}
Пример #12
0
bool KMeansQuantizer::train_(MatrixDouble &trainingData){
    
    //Clear any previous model
    clear();
    
    //Train the KMeans model
    KMeans kmeans;
    kmeans.setNumClusters(numClusters);
    kmeans.setComputeTheta( true );
    kmeans.setMinChange( minChange );
    kmeans.setMinNumEpochs( minNumEpochs );
	kmeans.setMaxNumEpochs( maxNumEpochs );
    
    if( !kmeans.train_(trainingData) ){
        errorLog << "train_(MatrixDouble &trainingData) - Failed to train quantizer!" << endl;
        return false;
    }
    
    trained = true;
    initialized = true;
    numInputDimensions = trainingData.getNumCols();
    numOutputDimensions = 1; //This is always 1 for the KMeansQuantizer
    featureVector.resize(numOutputDimensions,0);
    clusters = kmeans.getClusters();
    quantizationDistances.resize(numClusters,0);
    
    return true;
}
Пример #13
0
bool saveResults( const GestureRecognitionPipeline &pipeline, const string &filename ){
    
    infoLog << "Saving results to file: " << filename << endl;

    fstream file( filename.c_str(), fstream::out );

    if( !file.is_open() ){
        errorLog << "Failed to open results file: " << filename << endl;
        return false;
    }

    file << pipeline.getTestAccuracy() << endl;

    vector< UINT > classLabels = pipeline.getClassLabels();

    for(UINT k=0; k<pipeline.getNumClassesInModel(); k++){
        file << pipeline.getTestPrecision( classLabels[k] );
        if( k+1 < pipeline.getNumClassesInModel() ) file << "\t";
        else file << endl;
    }

    for(UINT k=0; k<pipeline.getNumClassesInModel(); k++){
        file << pipeline.getTestRecall( classLabels[k] );
        if( k+1 < pipeline.getNumClassesInModel() ) file << "\t";
        else file << endl;
    }

    for(UINT k=0; k<pipeline.getNumClassesInModel(); k++){
        file << pipeline.getTestFMeasure( classLabels[k] );
        if( k+1 < pipeline.getNumClassesInModel() ) file << "\t";
        else file << endl;
    }

    MatrixDouble confusionMatrix = pipeline.getTestConfusionMatrix();
    for(UINT i=0; i<confusionMatrix.getNumRows(); i++){
        for(UINT j=0; j<confusionMatrix.getNumCols(); j++){
            file << confusionMatrix[i][j];
            if( j+1 < confusionMatrix.getNumCols() ) file << "\t";
        }file << endl;
    }

    file.close();

    infoLog << "Results saved." << endl;

    return true;
}
Пример #14
0
void DTW::offsetTimeseries(MatrixDouble &timeseries){
    VectorDouble firstRow = timeseries.getRowVector(0);
    for(UINT i=0; i<timeseries.getNumRows(); i++){
        for(UINT j=0; j<timeseries.getNumCols(); j++){
            timeseries[i][j] -= firstRow[j];
        }
    }
}
int main (int argc, const char * argv[])
{
    //Create some input data for the PCA algorithm - this data comes from the Matlab PCA example
	MatrixDouble data(13,4);
	
	data[0][0] = 7; data[0][1] = 26; data[0][2] = 6; data[0][3] = 60;
	data[1][0] = 1; data[1][1] = 29; data[1][2] = 15; data[1][3] = 52;
	data[2][0] = 11; data[2][1] = 56; data[2][2] = 8; data[2][3] = 20;
	data[3][0] = 11; data[3][1] = 31; data[3][2] = 8; data[3][3] = 47;
	data[4][0] = 7; data[4][1] = 52; data[4][2] = 6; data[4][3] = 33;
	data[5][0] = 11; data[5][1] = 55; data[5][2] = 9; data[5][3] = 22;
	data[6][0] = 3; data[6][1] = 71; data[6][2] = 17; data[6][3] = 6;
	data[7][0] = 1; data[7][1] = 31; data[7][2] = 22; data[7][3] = 44;
	data[8][0] = 2; data[8][1] = 54; data[8][2] = 18; data[8][3] = 22;
	data[9][0] = 21; data[9][1] = 47; data[9][2] = 4; data[9][3] = 26;
	data[10][0] = 1; data[10][1] = 40; data[10][2] = 23; data[10][3] = 34;
	data[11][0] = 11; data[11][1] = 66; data[11][2] = 9; data[11][3] = 12;
	data[12][0] = 10; data[12][1] = 68; data[12][2] = 8; data[12][3] = 12;
    
    //Print the input data
    data.print("Input Data:");
	
    //Create a new principal component analysis instance
	PrincipalComponentAnalysis pca;
	
    //Run pca on the input data, setting the maximum variance value to 95% of the variance
	if( !pca.computeFeatureVector( data, 0.95 ) ){
		cout << "ERROR: Failed to compute feature vector!\n";
		return EXIT_FAILURE;
	}
    
    //Get the number of principal components
    UINT numPrincipalComponents = pca.getNumPrincipalComponents();
    cout << "Number of Principal Components: " << numPrincipalComponents << endl;
	
    //Project the original data onto the principal subspace
	MatrixDouble prjData;
	if( !pca.project( data, prjData ) ){
		cout << "ERROR: Failed to project data!\n";
		return EXIT_FAILURE;
	}
    
    //Print out the pca info
    //Print our
    pca.print("PCA Info:");
    
    //Print the projected data
    cout << "ProjectedData:\n";
	for(UINT i=0; i<prjData.getNumRows(); i++){
		for(UINT j=0; j<prjData.getNumCols(); j++){
			cout << prjData[i][j] << "\t";
		}cout << endl;
	}
    
    return EXIT_SUCCESS;
}
Пример #16
0
bool PrincipalComponentAnalysis::computeFeatureVector(const MatrixDouble &data,UINT numPrincipalComponents,bool normData) {
    trained = false;
    if( numPrincipalComponents > data.getNumCols() ) {
        errorLog << "computeFeatureVector(const MatrixDouble &data,UINT numPrincipalComponents,bool normData) - The number of principal components (";
        errorLog << numPrincipalComponents << ") is greater than the number of columns in your data (" << data.getNumCols() << ")" << endl;
        return false;
    }
    this->numPrincipalComponents = numPrincipalComponents;
    this->normData = normData;
    return computeFeatureVector_(data,MAX_NUM_PCS);
}
Пример #17
0
bool PrincipalComponentAnalysis::project(const MatrixDouble &data,MatrixDouble &prjData) {

    if( !trained ) {
        warningLog << "project(const MatrixDouble &data,MatrixDouble &prjData) - The PrincipalComponentAnalysis module has not been trained!" << endl;
        return false;
    }
    if( data.getNumCols() != numInputDimensions ) {
        warningLog << "project(const MatrixDouble &data,MatrixDouble &prjData) - The number of columns in the input vector (" << data.getNumCols() << ") does not match the number of input dimensions (" << numInputDimensions << ")!" << endl;
        return false;
    }

    MatrixDouble msData( data );
    prjData.resize(data.getNumRows(),numPrincipalComponents);

    if( normData ) {
        //Mean subtract the data
        for(UINT i=0; i<data.getNumRows(); i++)
            for(UINT j=0; j<numInputDimensions; j++)
                msData[i][j] = (msData[i][j]-mean[j])/stdDev[j];
    } else {
        //Mean subtract the data
        for(UINT i=0; i<data.getNumRows(); i++)
            for(UINT j=0; j<numInputDimensions; j++)
                msData[i][j] -= mean[j];
    }

    //Projected Data
    for(UINT row=0; row<msData.getNumRows(); row++) { //For each row in the final data
        for(UINT i=0; i<numPrincipalComponents; i++) { //For each PC
            prjData[row][i]=0;
            for(UINT j=0; j<data.getNumCols(); j++)//For each feature
                prjData[row][i] += msData[row][j] * eigenvectors[j][sortedEigenvalues[i].index];
        }
    }

    return true;
}
Пример #18
0
bool KMeans::train_(MatrixDouble &data){
	
	trained = false;
	
	if( numClusters == 0 ){
        errorLog << "train_(MatrixDouble &data) - Failed to train model. NumClusters is zero!" << endl;
		return false;
	}
    
    if( data.getNumRows() == 0 || data.getNumCols() == 0 ){
        errorLog << "train_(MatrixDouble &data) - The number of rows or columns in the data is zero!" << endl;
		return false;
	}
    
	numTrainingSamples = data.getNumRows();
	numInputDimensions = data.getNumCols();

	clusters.resize(numClusters,numInputDimensions);
	assign.resize(numTrainingSamples);
	count.resize(numClusters);

	//Randomly pick k data points as the starting clusters
	Random random;
	vector< UINT > randIndexs(numTrainingSamples);
	for(UINT i=0; i<numTrainingSamples; i++) randIndexs[i] = i;
    std::random_shuffle(randIndexs.begin(), randIndexs.end());

    //Copy the clusters
	for(UINT k=0; k<numClusters; k++){
		for(UINT j=0; j<numInputDimensions; j++){
            clusters[k][j] = data[ randIndexs[k] ][j];
		}
	}

	return trainModel( data );
}
Пример #19
0
void DTW::smoothData(MatrixDouble &data,UINT smoothFactor,MatrixDouble &resultsData){

	const UINT M = data.getNumRows();
	const UINT C = data.getNumCols();
	const UINT N = (UINT) floor(double(M)/double(smoothFactor));
	resultsData.resize(N,C);

	if(smoothFactor==1 || M<smoothFactor){
		resultsData = data;
		return;
	}

	for(UINT i=0; i<N; i++){
		for(UINT j=0; j<C; j++){
	     double mean = 0.0;
		 int index = i*smoothFactor;
		 for(UINT x=0; x<smoothFactor; x++){
			mean += data[index+x][j];
		 }
		 resultsData[i][j] = mean/smoothFactor;
		}
	}

	//Add on the data that does not fit into the window
	if(M%smoothFactor!=0.0){
		VectorDouble mean(C,0.0);
		for(UINT j=0; j<C; j++){
		 for(UINT i=N*smoothFactor; i<M; i++) mean[j] += data[i][j];
		 mean[j]/=M-(N*smoothFactor);
		}

		//Add one row to the end of the Matrix
		MatrixDouble tempMatrix(N+1,C);

		for(UINT i=0; i<N; i++)
			for(UINT j=0; j<C; j++)
				tempMatrix[i][j] = resultsData[i][j];

        for(UINT j=0; j<C; j++) tempMatrix[N][j] = mean[j];
		resultsData = tempMatrix;
	}

}
bool MatrixDouble::add(const MatrixDouble &b){
    
    if( b.getNumRows() != rows ){
        errorLog << "add(const MatrixDouble &b) - Failed to add matrix! The rows do not match!" << endl;
        return false;
    }
    
    if( b.getNumCols() != cols ){
        errorLog << "add(const MatrixDouble &b) - Failed to add matrix! The rows do not match!" << endl;
        return false;
    }
    
    unsigned int i = 0;
    
    //Using direct pointers really helps speed up the computation time
    const double *p_b = &(b[0][0]);
    
    for(i=0; i<rows*cols; i++){
        dataPtr[i] += p_b[i];
    }
    
    return true;
}
bool TimeSeriesClassificationData::addSample(const UINT classLabel,const MatrixDouble &trainingSample){
	
    if( trainingSample.getNumCols() != numDimensions ){
        errorLog << "addSample(UINT classLabel, MatrixDouble trainingSample) - The dimensionality of the training sample (" << trainingSample.getNumCols() << ") does not match that of the dataset (" << numDimensions << ")" << endl;
        return false;
    }
    
    //The class label must be greater than zero (as zero is used for the null rejection class label
    if( classLabel == GRT_DEFAULT_NULL_CLASS_LABEL && !allowNullGestureClass ){
        errorLog << "addSample(UINT classLabel, MatrixDouble sample) - the class label can not be 0!" << endl;
        return false;
    }

    TimeSeriesClassificationSample newSample(classLabel,trainingSample);
    data.push_back( newSample );
    totalNumSamples++;

    if( classTracker.size() == 0 ){
        ClassTracker tracker(classLabel,1);
        classTracker.push_back(tracker);
    }else{
        bool labelFound = false;
        for(UINT i=0; i<classTracker.size(); i++){
            if( classLabel == classTracker[i].classLabel ){
                classTracker[i].counter++;
                labelFound = true;
                break;
            }
        }
        if( !labelFound ){
            ClassTracker tracker(classLabel,1);
            classTracker.push_back(tracker);
        }
    }
    return true;
}
Пример #22
0
bool PrincipalComponentAnalysis::computeFeatureVector_(const MatrixDouble &data,const UINT analysisMode) {

    trained = false;
    const UINT M = data.getNumRows();
    const UINT N = data.getNumCols();
    this->numInputDimensions = N;

    MatrixDouble msData( M, N );

    //Compute the mean and standard deviation of the input data
    mean = data.getMean();
    stdDev = data.getStdDev();

    if( normData ) {
        //Normalize the data
        for(UINT i=0; i<M; i++)
            for(UINT j=0; j<N; j++)
                msData[i][j] = (data[i][j]-mean[j]) / stdDev[j];

    } else {
        //Mean Subtract Data
        for(UINT i=0; i<M; i++)
            for(UINT j=0; j<N; j++)
                msData[i][j] = data[i][j] - mean[j];
    }

    //Get the covariance matrix
    MatrixDouble cov = msData.getCovarianceMatrix();

    //Use Eigen Value Decomposition to find eigenvectors of the covariance matrix
    EigenvalueDecomposition eig;

    if( !eig.decompose( cov ) ) {
        mean.clear();
        stdDev.clear();
        componentWeights.clear();
        sortedEigenvalues.clear();
        eigenvectors.clear();
        errorLog << "computeFeatureVector(const MatrixDouble &data,UINT analysisMode) - Failed to decompose input matrix!" << endl;
        return false;
    }

    //Get the eigenvectors and eigenvalues
    eigenvectors = eig.getEigenvectors();
    VectorDouble eigenvalues = eig.getRealEigenvalues();

    //Any eigenvalues less than 0 are not worth anything so set to 0
    for(UINT i=0; i<eigenvalues.size(); i++) {
        if( eigenvalues[i] < 0 )
            eigenvalues[i] = 0;
    }

    //Sort the eigenvalues and compute the component weights
    double sum = 0;
    UINT componentIndex = 0;
    sortedEigenvalues.clear();
    componentWeights.resize(N,0);

    while( true ) {
        double maxValue = 0;
        UINT index = 0;
        for(UINT i=0; i<eigenvalues.size(); i++) {
            if( eigenvalues[i] > maxValue ) {
                maxValue = eigenvalues[i];
                index = i;
            }
        }
        if( maxValue == 0 || componentIndex >= eigenvalues.size() ) {
            break;
        }
        sortedEigenvalues.push_back( IndexedDouble(index,maxValue) );
        componentWeights[ componentIndex++ ] = eigenvalues[ index ];
        sum += eigenvalues[ index ];
        eigenvalues[ index ] = 0; //Set the maxValue to zero so it won't be used again
    }

    double cumulativeVariance = 0;
    switch( analysisMode ) {
    case MAX_VARIANCE:
        //Normalize the component weights and workout how many components we need to use to reach the maxVariance
        numPrincipalComponents = 0;
        for(UINT k=0; k<N; k++) {
            componentWeights[k] /= sum;
            cumulativeVariance += componentWeights[k];
            if( cumulativeVariance >= maxVariance && numPrincipalComponents==0 ) {
                numPrincipalComponents = k+1;
            }
        }
        break;
    case MAX_NUM_PCS:
        //Normalize the component weights and compute the maxVariance
        maxVariance = 0;
        for(UINT k=0; k<N; k++) {
            componentWeights[k] /= sum;
            if( k < numPrincipalComponents ) {
                maxVariance += componentWeights[k];
            }
        }
        break;
    default:
        errorLog << "computeFeatureVector(const MatrixDouble &data,UINT analysisMode) - Unknown analysis mode!" << endl;
        break;
    }

    //Flag that the features have been computed
    trained = true;

    return true;
}
void metrics_subset_data(){
    
    
    ANBC anbc;
    anbc.enableScaling(true);
    anbc.enableNullRejection(true);
    
    MinDist minDist;
    minDist.setNumClusters(4);
    minDist.enableScaling(true);
    minDist.enableNullRejection(true);
    
    //    ofstream opRecall("anbc-recall-nr-0-10.csv");
    //    opRecall <<"nrCoeff,class0,class1,class2,class3,class4,class5\n";
    //
    //    ofstream opInstanceRes("anbc-prediction-nr-2.csv");
    //    opInstanceRes <<"actualClass,predictedClass,maximumLikelihood,lZ,lY,lZ,rZ,rY,rZ\n";
    //
    //    ofstream opMetrics("anbc-precision-recall-fmeasure-nr-2.csv");
    //    opMetrics <<"class1,class2,class3,class4,class5\n";
    //
    //    ofstream opConfusion("anbc-confusion-nr-2.csv");
    //    opConfusion <<"class0,class1,class2,class3,class4,class5\n";
    
    
    ofstream opRecall("mindist-recall-nr-0-10.csv");
    opRecall <<"nrCoeff,class0,class1,class2,class3,class4,class5\n";
    
    ofstream opInstanceRes("mindist-prediction-nr-2.csv");
    opInstanceRes <<"actualClass,predictedClass,maximumLikelihood,lZ,lY,lZ,rZ,rY,rZ\n";
    
    ofstream opMetrics("mindist-precision-recall-fmeasure-nr-2.csv");
    opMetrics <<"class1,class2,class3,class4,class5\n";
    
    ofstream opConfusion("mindist-confusion-nr-2.csv");
    opConfusion <<"class0,class1,class2,class3,class4,class5\n";
    
    // Training and test data
    ClassificationData trainingData;
    ClassificationData testData;
    ClassificationData nullGestureData;
    
    string file_path = "../../../data/";
    
    if( !trainingData.loadDatasetFromFile(file_path +  "train/grt/hri-training-dataset.txt") ){
        std::cout <<"Failed to load training data!\n";
    }
    
    if( !nullGestureData.loadDatasetFromFile(file_path +  "test/grt/0.txt") ){
        std::cout <<"Failed to load null gesture data!\n";
    }
    
    
    testData = trainingData.partition(90);
    testData.sortClassLabels();
//    testData.saveDatasetToFile("anbc-validation-subset.txt");
    testData.saveDatasetToFile("mindist-validation-subset.txt");
    
    
    for(double nullRejectionCoeff = 0; nullRejectionCoeff <= 10; nullRejectionCoeff=nullRejectionCoeff+0.2){
        
        //        anbc.setNullRejectionCoeff(nullRejectionCoeff);
        //        GestureRecognitionPipeline pipeline;
        //        pipeline.setClassifier(anbc);
        
        minDist.setNullRejectionCoeff(nullRejectionCoeff);
        GestureRecognitionPipeline pipeline;
        pipeline.setClassifier(minDist);
        
        pipeline.train(trainingData);
        
        pipeline.test(testData);
        TestResult testRes = pipeline.getTestResults();
        
        opRecall << nullRejectionCoeff << ",";
        
        
        //null rejection prediction
        double accuracy = 0;
        for(UINT i=0; i<nullGestureData.getNumSamples(); i++){
            
            vector< double > inputVector = nullGestureData[i].getSample();
            
            if( !pipeline.predict( inputVector )){
                std::cout << "Failed to perform prediction for test sampel: " << i <<"\n";
            }
            
            UINT predictedClassLabel = pipeline.getPredictedClassLabel();
            if(predictedClassLabel == 0 ) accuracy++;
        }
        
        opRecall << accuracy/double(nullGestureData.getNumSamples()) << ",";
        
        
        // other classes prediction
        for(int cl = 0; cl < testRes.recall.size(); cl++ ){
            opRecall << testRes.recall[cl];
            if(cl < testRes.recall.size() - 1){
                opRecall << ",";
            }
        }
        
        opRecall<< endl;
        
        
        // Calculate instance prediction, precision, recall, fmeasure and confusion matrix for nullRejection 2.0
        if(AreDoubleSame(nullRejectionCoeff, 2.0))
        {
            //instance prediction
            for(UINT i=0; i<testData.getNumSamples(); i++){
                
                UINT actualClassLabel = testData[i].getClassLabel();
                vector< double > inputVector = testData[i].getSample();
                
                if( !pipeline.predict( inputVector )){
                    std::cout << "Failed to perform prediction for test sampel: " << i <<"\n";
                }
                
                UINT predictedClassLabel = pipeline.getPredictedClassLabel();
                double maximumLikelihood = pipeline.getMaximumLikelihood();
                
                opInstanceRes << actualClassLabel << "," << predictedClassLabel << "," << maximumLikelihood << ","
                << inputVector[0] << "," << inputVector[1] << ","  << inputVector[2] << ","  << inputVector[3] << ","  << inputVector[4] << ","  << inputVector[5] << "\n";
                
            }
            
            //precision, recall, fmeasure
            for(int cl = 0; cl < testRes.precision.size(); cl++ ){
                opMetrics << testRes.precision[cl];
                if(cl < testRes.precision.size() - 1){
                    opMetrics << ",";
                }
            }
            opMetrics<< endl;
            
            for(int cl = 0; cl < testRes.recall.size(); cl++ ){
                opMetrics << testRes.recall[cl];
                
                if(cl < testRes.recall.size() - 1){
                    opMetrics << ",";
                }
            }
            opMetrics<< endl;
            
            for(int cl = 0; cl < testRes.fMeasure.size(); cl++ ){
                opMetrics << testRes.fMeasure[cl];
                
                if(cl < testRes.fMeasure.size() - 1){
                    opMetrics << ",";
                }
            }
            opMetrics<< endl;
            
            //confusion matrix
            MatrixDouble matrix = testRes.confusionMatrix;
            for(UINT i=0; i<matrix.getNumRows(); i++){
                for(UINT j=0; j<matrix.getNumCols(); j++){
                    opConfusion << matrix[i][j];
                    
                    if(j < matrix.getNumCols() - 1){
                        opConfusion << ",";
                    }
                    
                }
                opConfusion << endl;
            }
            opConfusion << endl;
            
        }
        
        
        
    }
    
    cout << "Done\n";
}
Пример #24
0
double DTW::computeDistance(MatrixDouble &timeSeriesA,MatrixDouble &timeSeriesB,MatrixDouble &distanceMatrix,vector< IndexDist > &warpPath){

	const int M = timeSeriesA.getNumRows();
	const int N = timeSeriesB.getNumRows();
	const int C = timeSeriesA.getNumCols();
	int i,j,k,index = 0;
	double totalDist,v,normFactor = 0.;
    
    warpPath.clear();
    if( int(distanceMatrix.getNumRows()) != M || int(distanceMatrix.getNumCols()) != N ){
        distanceMatrix.resize(M, N);
    }

	switch (distanceMethod) {
		case (ABSOLUTE_DIST):
			for(i=0; i<M; i++){
				for(j=0; j<N; j++){
					distanceMatrix[i][j] = 0.0;
					for(k=0; k< C; k++){
					   distanceMatrix[i][j] += fabs(timeSeriesA[i][k]-timeSeriesB[j][k]);
					}
				}
			}
			break;
		case (EUCLIDEAN_DIST):
			//Calculate Euclidean Distance for all possible values
			for(i=0; i<M; i++){
				for(j=0; j<N; j++){
					distanceMatrix[i][j] = 0.0;
					for(k=0; k< C; k++){
						distanceMatrix[i][j] += SQR( timeSeriesA[i][k]-timeSeriesB[j][k] );
					}
					distanceMatrix[i][j] = sqrt( distanceMatrix[i][j] );
				}
			}
			break;
		case (NORM_ABSOLUTE_DIST):
			for(i=0; i<M; i++){
				for(j=0; j<N; j++){
					distanceMatrix[i][j] = 0.0;
					for(k=0; k< C; k++){
					   distanceMatrix[i][j] += fabs(timeSeriesA[i][k]-timeSeriesB[j][k]);
					}
					distanceMatrix[i][j]/=N;
				}
			}
			break;
		default:
			errorLog<<"ERROR: Unknown distance method: "<<distanceMethod<<endl;
			return -1;
			break;
	}

    //Run the recursive search function to build the cost matrix
    double distance = sqrt( d(M-1,N-1,distanceMatrix,M,N) );

    if( isinf(distance) || isnan(distance) ){
        warningLog << "DTW computeDistance(...) - Distance Matrix Values are INF!" << endl;
        return INFINITY;
    }
    
    //cout << "DIST: " << distance << endl;

    //The distMatrix values are negative so make them positive
    for(i=0; i<M; i++){
        for(j=0; j<N; j++){
            distanceMatrix[i][j] = fabs( distanceMatrix[i][j] );
        }
    }

	//Now Create the Warp Path through the cost matrix, starting at the end
    i=M-1;
	j=N-1;
	totalDist = distanceMatrix[i][j];
    warpPath.push_back( IndexDist(i,j,distanceMatrix[i][j]) );
    
	//Use dynamic programming to navigate through the cost matrix until [0][0] has been reached
    normFactor = 1;
	while( true ) {
        if( i==0 && j==0 ) break;
		if( i==0 ){ j--; }
        else{ 
            if( j==0 ) i--;
            else{
                //Find the minimum cell to move to
                v = numeric_limits<double>::max();
                index = 0;
                if( distanceMatrix[i-1][j] < v ){ v = distanceMatrix[i-1][j]; index = 1; }
                if( distanceMatrix[i][j-1] < v ){ v = distanceMatrix[i][j-1]; index = 2; }
                if( distanceMatrix[i-1][j-1] <= v ){ index = 3; }
                switch(index){
                    case(1):
                        i--;
                        break;
                    case(2):
                        j--;
                        break;
                    case(3):
                        i--;
                        j--;
                        break;
                    default:
                        warningLog << "DTW computeDistance(...) - Could not compute a warping path for the input matrix! Dist: " << distanceMatrix[i-1][j] << " i: " << i << " j: " << j << endl;
                        return INFINITY;
                        break;
                }
            }
        }
        normFactor++;
		totalDist += distanceMatrix[i][j];
		warpPath.push_back( IndexDist(i,j,distanceMatrix[i][j]) );
	}

	return totalDist/normFactor;
}
Пример #25
0
bool HMM::predict_continuous(MatrixDouble &timeseries){
    
    if( !trained ){
        errorLog << "predict_continuous(MatrixDouble &timeseries) - The HMM classifier has not been trained!" << endl;
        return false;
    }
    
	if( timeseries.getNumCols() != numInputDimensions ){
        errorLog << "predict_continuous(MatrixDouble &timeseries) - The number of columns in the input matrix (" << timeseries.getNumCols() << ") does not match the num features in the model (" << numInputDimensions << endl;
		return false;
	}
    
    //Scale the input vector if needed
    if( useScaling ){
        const UINT timeseriesLength = timeseries.getNumRows();
        for(UINT j=0; j<numInputDimensions; j++){
            for(UINT i=0; i<timeseriesLength; i++){
                timeseries[i][j] = scale(timeseries[i][j], ranges[j].minValue, ranges[j].maxValue, 0, 1);
            }
        }
    }
    
    if( classLikelihoods.size() != numClasses ) classLikelihoods.resize(numClasses,0);
    if( classDistances.size() != numClasses ) classDistances.resize(numClasses,0);
    
    std::fill(classLikelihoods.begin(),classLikelihoods.end(),0);
    std::fill(classDistances.begin(),classDistances.end(),0);
    
    bestDistance = -1000;
    UINT bestIndex = 0;
    double minValue = -1000;
    
    const UINT numModels = (UINT)continuousModels.size();
    vector< IndexedDouble > results(numModels);
    for(UINT i=0; i<numModels; i++){
        
        //Run the prediction for this model
        if( continuousModels[i].predict_( timeseries ) ){
            results[i].value = continuousModels[i].getLoglikelihood();
            results[i].index = continuousModels[i].getClassLabel();
        }else{
            errorLog << "predict_(VectorDouble &inputVector) - Prediction failed for model: " << i << endl;
            return false;
        }
        
        if( results[i].value < minValue ){
            minValue = results[i].value;
        }
        
        if( results[i].value > bestDistance ){
            bestDistance = results[i].value;
            bestIndex = i;
        }
    }
    
    //Store the phase from the best model
    phase = continuousModels[ bestIndex ].getPhase();
    
    //Sort the results
    std::sort(results.begin(),results.end(),IndexedDouble::sortIndexedDoubleByValueDescending);
    
    //Run the majority vote
    const double committeeWeight = 1.0 / committeeSize;
    for(UINT i=0; i<committeeSize; i++){
        classDistances[ getClassLabelIndexValue( results[i].index ) ] += Util::scale(results[i].value, -1000, 0, 0, committeeWeight, true);
    }
    
    //Turn the class distances into likelihoods
    double sum = Util::sum(classDistances);
    if( sum > 0 ){
        for(UINT k=0; k<numClasses; k++){
            classLikelihoods[k] = classDistances[k] / sum;
        }
        
        //Find the maximum label
        for(UINT k=0; k<numClasses; k++){
            if( classDistances[k] > bestDistance ){
                bestDistance = classDistances[k];
                bestIndex = k;
            }
        }
        
        maxLikelihood = classLikelihoods[ bestIndex ];
        predictedClassLabel = classLabels[ bestIndex ];
    }else{
        //If the sum is not greater than 1, then no class is close to any model
        maxLikelihood = 0;
        predictedClassLabel = 0;
    }
    return true;
}
Пример #26
0
bool ANBC_Model::train(UINT classLabel,MatrixDouble &trainingData,VectorDouble &weightsVector){

	//Check to make sure the column sizes match
	if( trainingData.getNumCols() != weightsVector.size() ){
		N = 0;
		return false;
	}
    
	UINT M = trainingData.getNumRows();
	N = trainingData.getNumCols();
    this->classLabel = classLabel;

	//Update the weights buffer
	weights = weightsVector;

	//Resize the buffers
	mu.resize( N );
	sigma.resize( N );

	//Calculate the mean for each dimension
	for(UINT j=0; j<N; j++){
		mu[j] = 0.0;

		for(UINT i=0; i<M; i++){
			mu[j] += trainingData[i][j];
        }

		mu[j] /= double(M);
        
        if( mu[j] == 0 ){
            return false;
        }
	}

	//Calculate the sample standard deviation
	for(UINT j=0; j<N; j++){
		sigma[j] = 0.0;

		for(UINT i=0; i<M; i++){
			sigma[j] += SQR( trainingData[i][j]-mu[j] );
        }

		sigma[j] = sqrt( sigma[j]/double(M-1) );
        
        if( sigma[j] == 0 ){
            return false;
        }
	}

	//Now compute the threshold
    double meanPrediction = 0.0;
	VectorDouble predictions(M);
	for(UINT i=0; i<M; i++){
		//Test the ith training example
		vector<double> testData(N);
		for(UINT j=0; j<N; j++) {
			testData[j] = trainingData[i][j];
        }
        
		predictions[i] = predict(testData);
        meanPrediction += predictions[i];
	}

	//Calculate the mean prediction value
	meanPrediction /= double(M);

	//Calculate the standard deviation
	double stdDev = 0.0;
	for(UINT i=0; i<M; i++) {
		stdDev += SQR( predictions[i]-meanPrediction );
    }
	stdDev = sqrt( stdDev / (double(M)-1.0) );

	threshold = meanPrediction-(stdDev*gamma);

	//Update the training mu and sigma values so the threshold value can be dynamically computed at a later stage
	trainingMu = meanPrediction;
	trainingSigma = stdDev;

	return true;
}
Пример #27
0
bool KMeansFeatures::train_(MatrixDouble &trainingData){
    
    if( !initialized ){
        errorLog << "train_(MatrixDouble &trainingData) - The quantizer has not been initialized!" << endl;
        return false;
    }
    
    //Reset any previous model
    featureDataReady = false;
    
    const UINT M = trainingData.getNumRows();
    const UINT N = trainingData.getNumCols();
    
    numInputDimensions = N;
    numOutputDimensions = numClustersPerLayer[ numClustersPerLayer.size()-1 ];
    
    //Scale the input data if needed
    ranges = trainingData.getRanges();
    if( useScaling ){
        for(UINT i=0; i<M; i++){
            for(UINT j=0; j<N; j++){
                trainingData[i][j] = scale(trainingData[i][j],ranges[j].minValue,ranges[j].maxValue,0,1.0);
            }
        }
    }
    
    //Train the KMeans model at each layer
    const UINT K = (UINT)numClustersPerLayer.size();
    for(UINT k=0; k<K; k++){
        KMeans kmeans;
        kmeans.setNumClusters( numClustersPerLayer[k] );
        kmeans.setComputeTheta( true );
        kmeans.setMinChange( minChange );
        kmeans.setMinNumEpochs( minNumEpochs );
        kmeans.setMaxNumEpochs( maxNumEpochs );
        
        trainingLog << "Layer " << k+1 << "/" << K << " NumClusters: " << numClustersPerLayer[k] << endl;
        if( !kmeans.train_( trainingData ) ){
            errorLog << "train_(MatrixDouble &trainingData) - Failed to train kmeans model at layer: " << k << endl;
            return false;
        }
        
        //Save the clusters
        clusters.push_back( kmeans.getClusters() );
        
        //Project the data through the current layer to use as training data for the next layer
        if( k+1 != K ){
            MatrixDouble data( M, numClustersPerLayer[k] );
            VectorDouble input( trainingData.getNumCols() );
            VectorDouble output( data.getNumCols() );
            
            for(UINT i=0; i<M; i++){
                
                //Copy the data into the sample
                for(UINT j=0; j<input.size(); j++){
                    input[j] = trainingData[i][j];
                }
                
                //Project the sample through the current layer
                if( !projectDataThroughLayer( input, output, k ) ){
                    errorLog << "train_(MatrixDouble &trainingData) - Failed to project sample through layer: " << k << endl;
                    return false;
                }
                
                //Copy the result into the training data for the next layer
                for(UINT j=0; j<output.size(); j++){
                    data[i][j] = output[j];
                }
            }
            
            //Swap the data for the next layer
            trainingData = data;
            
        }
        
    }
    
    //Flag that the kmeans model has been trained
    trained = true;
    featureVector.resize( numOutputDimensions, 0 );
    
    return true;
}
bool GaussianMixtureModels::train(const MatrixDouble &data,const UINT K){

	modelTrained = false;
    failed = false;

	//Clear any previous training results
	det.clear();
	invSigma.clear();

    if( data.getNumRows() == 0 ){
        errorLog << "train(const MatrixDouble &trainingData,const unsigned int K) - Training Failed! Training data is empty!" << endl;
        return false;
    }

	//Resize the variables
	M = data.getNumRows();
	N = data.getNumCols();
	this->K = K;
	
	//Resize mu and resp
	mu.resize(K,N);
	resp.resize(M,K);
	
	//Resize sigma
	sigma.resize(K);
	for(UINT k=0; k<K; k++){
		sigma[k].resize(N,N);
	}
	
	//Resize frac and lndets
	frac.resize(K);
	lndets.resize(K);

	//Pick K random starting points for the inital guesses of Mu
	Random random;
	vector< UINT > randomIndexs(M);
	for(UINT i=0; i<M; i++) randomIndexs[i] = i;
	for(UINT i=0; i<M; i++){
		SWAP(randomIndexs[ random.getRandomNumberInt(0,M) ],randomIndexs[ random.getRandomNumberInt(0,M) ]);
	}
	for(UINT k=0; k<K; k++){
		for(UINT n=0; n<N; n++){
			mu[k][n] = data[ randomIndexs[k] ][n];
		}
	}

	//Setup sigma and the uniform prior on P(k)
	for(UINT k=0; k<K; k++){
		frac[k] = 1.0/double(K);
		for(UINT i=0; i<N; i++){
			for(UINT j=0; j<N; j++) sigma[k][i][j] = 0;
			sigma[k][i][i] = 1.0e-10;   //Set the diagonal to a small number
		}
	}

	loglike = 0;
	UINT iterCounter = 0;
	bool keepGoing = true;
	double change = 99.9e99;
    
	while( keepGoing ){
		change = estep( data );
		mstep( data );

		if( fabs( change ) < minChange ) keepGoing = false;
		if( ++iterCounter >= maxIter ) keepGoing = false;
		if( failed ) keepGoing = false;
	}

	if( failed ){
		errorLog << "train(UnlabelledClassificationData &trainingData,unsigned int K) - Training failed!" << endl;
		return modelTrained;
	}

	//Compute the inverse of sigma and the determinants for prediction
	if( !computeInvAndDet() ){
        det.clear();
        invSigma.clear();
        errorLog << "train(UnlabelledClassificationData &trainingData,unsigned int K) - Failed to compute inverse and determinat!" << endl;
        return false;
    }

    //Flag that the model was trained
	modelTrained = true;

	return true;
}
int main (int argc, const char * argv[])
{
    //Load some training data from a file
    ClassificationData trainingData;
    
    if( !trainingData.loadDatasetFromFile("HelloWorldTrainingData.grt") ){
        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
    ClassificationData 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;
    }
    
    //Save the pipeline to a file
	if( !pipeline.savePipelineToFile( "HelloWorldPipeline.grt" ) ){
        cout << "ERROR: Failed to save the pipeline!\n";
        return EXIT_FAILURE;
    }
    
	//Load the pipeline from a file
	if( !pipeline.loadPipelineFromFile( "HelloWorldPipeline.grt" ) ){
        cout << "ERROR: Failed to load 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;
    
    MatrixDouble 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;
}
Пример #30
0
bool DTW::predict(MatrixDouble inputTimeSeries){

    if( !trained ){
        errorLog << "predict(Matrix<double> &inputTimeSeries) - The DTW templates have not been trained!" << endl;
        return false;
    }

    if( classLikelihoods.size() != numTemplates ) classLikelihoods.resize(numTemplates);
    if( classDistances.size() != numTemplates ) classDistances.resize(numTemplates);

    predictedClassLabel = 0;
    maxLikelihood = DEFAULT_NULL_LIKELIHOOD_VALUE;
    for(UINT k=0; k<classLikelihoods.size(); k++){
        classLikelihoods[k] = 0;
        classDistances[k] = DEFAULT_NULL_LIKELIHOOD_VALUE;
    }

	if( numFeatures != inputTimeSeries.getNumCols() ){
        errorLog << "predict(Matrix<double> &inputTimeSeries) - The number of features in the model (" << numFeatures << ") do not match that of the input time series (" << inputTimeSeries.getNumCols() << ")" << endl;
        return false;
    }

	//Perform any preprocessing if requried
    MatrixDouble *timeSeriesPtr = &inputTimeSeries;
    MatrixDouble processedTimeSeries;
    MatrixDouble tempMatrix;
	if(useScaling){
        scaleData(*timeSeriesPtr,processedTimeSeries);
        timeSeriesPtr = &processedTimeSeries;
    }
    
    //Normalize the data if needed
	if( useZNormalisation ){
        znormData(*timeSeriesPtr,processedTimeSeries);
        timeSeriesPtr = &processedTimeSeries;
    }

	//Smooth the data if required
	if( useSmoothing ){
		smoothData(*timeSeriesPtr,smoothingFactor,tempMatrix);
		timeSeriesPtr = &tempMatrix;
	}
    
    //Offset the timeseries if required
    if( offsetUsingFirstSample ){
        offsetTimeseries( *timeSeriesPtr );
    }

	//Make the prediction by finding the closest template
    double sum = 0;
    if( distanceMatrices.size() != numTemplates ) distanceMatrices.resize( numTemplates );
    if( warpPaths.size() != numTemplates ) warpPaths.resize( numTemplates );
    
	//Test the timeSeries against all the templates in the timeSeries buffer
	for(UINT k=0; k<numTemplates; k++){
		//Perform DTW
		classDistances[k] = computeDistance(templatesBuffer[k].timeSeries,*timeSeriesPtr,distanceMatrices[k],warpPaths[k]);
        classLikelihoods[k] = classDistances[k];
        sum += classLikelihoods[k];
	}

	//See which gave the min distance
	UINT closestTemplateIndex = 0;
	bestDistance = classDistances[0];
	for(UINT k=1; k<numTemplates; k++){
		if( classDistances[k] < bestDistance ){
			bestDistance = classDistances[k];
			closestTemplateIndex = k;
		}
	}
    
    //Normalize the class likelihoods and check which class has the maximum likelihood
    UINT maxLikelihoodIndex = 0;
    maxLikelihood = 0;
    for(UINT k=0; k<numTemplates; k++){
        classLikelihoods[k] = (sum-classLikelihoods[k])/sum;
        if( classLikelihoods[k] > maxLikelihood ){
            maxLikelihood = classLikelihoods[k];
            maxLikelihoodIndex = k;
        }
    }

    if( useNullRejection ){

        switch( rejectionMode ){
            case TEMPLATE_THRESHOLDS:
                if( bestDistance <= nullRejectionThresholds[ closestTemplateIndex ] ) predictedClassLabel = templatesBuffer[ closestTemplateIndex ].classLabel;
                else predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
                break;
            case CLASS_LIKELIHOODS:
                if( maxLikelihood >= 0.99 )  predictedClassLabel = templatesBuffer[ maxLikelihoodIndex ].classLabel;
                else predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
                break;
            case THRESHOLDS_AND_LIKELIHOODS:
                if( bestDistance <= nullRejectionThresholds[ closestTemplateIndex ] && maxLikelihood >= 0.99 )
                    predictedClassLabel = templatesBuffer[ closestTemplateIndex ].classLabel;
                else predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
                break;
            default:
                errorLog << "predict(Matrix<double> &timeSeries) - Unknown RejectionMode!" << endl;
                return false;
                break;
        }

	}else predictedClassLabel = templatesBuffer[ closestTemplateIndex ].classLabel;

    return true;
}