From 3b3eba96fb1d9251f4d0cec9ca2d27ba7f66a65a Mon Sep 17 00:00:00 2001 From: Jakhes <dean.schmitz@schmitzbauer.de> Date: Sat, 12 Nov 2022 00:15:17 +0100 Subject: [PATCH] Finishing lcc tests --- .../local_coordinate_coding.cpp | 205 ++---------------- .../local_coordinate_coding.pl | 131 ++--------- .../local_coordinate_coding_test.pl | 44 ++-- 3 files changed, 58 insertions(+), 322 deletions(-) diff --git a/src/methods/local_coordinate_coding/local_coordinate_coding.cpp b/src/methods/local_coordinate_coding/local_coordinate_coding.cpp index 8cd6474..231c4c0 100644 --- a/src/methods/local_coordinate_coding/local_coordinate_coding.cpp +++ b/src/methods/local_coordinate_coding/local_coordinate_coding.cpp @@ -15,11 +15,6 @@ using namespace mlpack; using namespace std; using namespace mlpack::lcc; -// Global Variable of the LocalCoordinateCoding object so it can be accessed from all functions -LocalCoordinateCoding lccGlobObj; - -bool normalizeData = false; - // input: const arma::mat & data, // const size_t atoms, @@ -27,219 +22,47 @@ bool normalizeData = false; // const size_t maxIterations = 0, // const double tolerance = 0.01, // const DictionaryInitializer & initializer = DictionaryInitializer() +// const arma::mat & toEncodedata, +// arma::mat & codes <- // output: // description: -// Initializes the model and trains it so encode/6 can be called after -// -void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, - SP_integer normalize, SP_integer atoms, double lambda, SP_integer maxIterations, double tolerance) -{ - normalizeData = normalize == 1; - - // convert the Prolog array to arma::mat - mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - - if (normalizeData) - { - Log::Info << "Normalizing data before coding..." << endl; - for (size_t i = 0; i < data.n_cols; ++i) - data.col(i) /= arma::norm(data.col(i), 2); - } - - - try - { - lccGlobObj = LocalCoordinateCoding(data, atoms, lambda, maxIterations, tolerance);lccGlobObj = LocalCoordinateCoding(atoms, lambda, maxIterations, tolerance); - } - catch(const std::exception& e) - { - raisePrologSystemExeption(e.what()); - } -} - - -// input: const size_t atoms = 0, -// const double lambda = 0.0, -// const size_t maxIterations = 0, -// const double tolerance = 0.01 -// output: -// description: -// Initializes the model but doesnt train it so train/4 has to be called befor encode/6 can be used. +// Initializes the model, trains it and encodes each point of the given data via distance-weighted LARS. // -void initModelNoTrain(SP_integer normalize, SP_integer atoms, double lambda, SP_integer maxIterations, double tolerance) -{ - normalizeData = normalize == 1; - - - try - { - lccGlobObj = LocalCoordinateCoding(atoms, lambda, maxIterations, tolerance); - } - catch(const std::exception& e) - { - raisePrologSystemExeption(e.what()); - } -} - - -// input: const arma::mat & data, -// arma::mat & codes <- -// output: -// description: -// Code each point via distance-weighted LARS. -// -void encode(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, +void lcc(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + SP_integer normalize, SP_integer atoms, double lambda, SP_integer maxIterations, double tolerance, + float *toEncodeDataMatArr, SP_integer toEncodeDataMatSize, SP_integer toEncodeDataMatRowNum, float **codesMatArr, SP_integer *codesMatColNum, SP_integer *codesMatRowNum) { // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); + mat toEncodeData = convertArrayToMat(toEncodeDataMatArr, toEncodeDataMatSize, toEncodeDataMatRowNum); // create the ReturnMat mat codesReturnMat; - // Normalize each point if the user asked for it. - if (IO::HasParam("normalize")) + if (normalize == 1) { - Log::Info << "Normalizing test data before coding..." << endl; + Log::Info << "Normalizing data before coding..." << endl; for (size_t i = 0; i < data.n_cols; ++i) data.col(i) /= arma::norm(data.col(i), 2); - } - - - try - { - lccGlobObj.Encode(data, codesReturnMat); - } - catch(const std::exception& e) - { - raisePrologSystemExeption(e.what()); - } - - - // return the Matrix - returnMatrixInformation(codesReturnMat, codesMatArr, codesMatColNum, codesMatRowNum); -} - -// TODO: wrong inputs -// input: const arma::mat & data, -// const arma::mat & codes, -// const arma::uvec & adjacencies -// output: -// description: -// Compute objective function given the list of adjacencies. -// -void objective(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, - float **codesMatArr, SP_integer *codesMatColNum, SP_integer *codesMatRowNum, - float **adjacenciesArr, SP_integer *adjacenciesArrSize) -{ - // convert the Prolog arrays to arma::mat - mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - // create the ReturnMat - mat codesReturnMat; - - // create the ReturnVector - uvec adjacenciesReturnVector; - - // Normalize each point if the user asked for it. - if (IO::HasParam("normalize")) - { Log::Info << "Normalizing test data before coding..." << endl; - for (size_t i = 0; i < data.n_cols; ++i) - data.col(i) /= arma::norm(data.col(i), 2); + for (size_t i = 0; i < toEncodeData.n_cols; ++i) + toEncodeData.col(i) /= arma::norm(toEncodeData.col(i), 2); } - + try { - lccGlobObj.Objective(data, codesReturnMat, adjacenciesReturnVector); + LocalCoordinateCoding(data, atoms, lambda, maxIterations, tolerance) + .Encode(toEncodeData, codesReturnMat); } catch(const std::exception& e) { raisePrologSystemExeption(e.what()); } - - - // return the Matrix - returnMatrixInformation(codesReturnMat, codesMatArr, codesMatColNum, codesMatRowNum); - - // return the Vector - returnVectorInformation(arma::conv_to<vec>::from(adjacenciesReturnVector), adjacenciesArr, adjacenciesArrSize); -} - -// TODO: wrong inputs -// input: const arma::mat & data, -// const arma::mat & codes, -// const arma::uvec & adjacencies -// output: -// description: -// Learn dictionary by solving linear system. -// -void optimizeDictionary(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, - float **codesMatArr, SP_integer *codesMatColNum, SP_integer *codesMatRowNum, - float **adjacenciesArr, SP_integer *adjacenciesArrSize) -{ - // convert the Prolog arrays to arma::mat - mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - - // create the ReturnMat - mat codesReturnMat; - - // create the ReturnVector - uvec adjacenciesReturnVector; - - // Normalize each point if the user asked for it. - if (IO::HasParam("normalize")) - { - Log::Info << "Normalizing test data before coding..." << endl; - for (size_t i = 0; i < data.n_cols; ++i) - data.col(i) /= arma::norm(data.col(i), 2); - } - try - { - lccGlobObj.OptimizeDictionary(data, codesReturnMat, adjacenciesReturnVector); - } - catch(const std::exception& e) - { - raisePrologSystemExeption(e.what()); - } - - // return the Matrix returnMatrixInformation(codesReturnMat, codesMatArr, codesMatColNum, codesMatRowNum); - - // return the Vector - returnVectorInformation(arma::conv_to<vec>::from(adjacenciesReturnVector), adjacenciesArr, adjacenciesArrSize); -} - - -// input: const arma::mat & data, -// const DictionaryInitializer & initializer = DictionaryInitializer() -// output: double final objective value -// description: -// Run local coordinate coding and train the model. -// -double train(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum) -{ - // convert the Prolog arrays to arma::mat - mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - - if (normalizeData) - { - Log::Info << "Normalizing data before coding..." << endl; - for (size_t i = 0; i < data.n_cols; ++i) - data.col(i) /= arma::norm(data.col(i), 2); - } - - - try - { - return lccGlobObj.Train(data); - } - catch(const std::exception& e) - { - raisePrologSystemExeption(e.what()); - } } \ No newline at end of file diff --git a/src/methods/local_coordinate_coding/local_coordinate_coding.pl b/src/methods/local_coordinate_coding/local_coordinate_coding.pl index 97c4580..08a1dca 100644 --- a/src/methods/local_coordinate_coding/local_coordinate_coding.pl +++ b/src/methods/local_coordinate_coding/local_coordinate_coding.pl @@ -1,10 +1,5 @@ -:- module(local_coordinate_coding, [ lcc_initModelWithTrain/7, - lcc_initModelNoTrain/5, - lcc_encode/4, - lcc_objective/5, - lcc_optimizeDictionary/5, - lcc_train/3]). +:- module(local_coordinate_coding, [lcc/11]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -29,123 +24,33 @@ %% float32 lambda => 0.0, %% int maxIterations => 0, %% float32 tolerance => 0.01 -%% -%% --Output-- -%% -%% --Description-- -%% Initializes the model and trains it so encode/6 can be called after -%% -lcc_initModelWithTrain(DataList, DataRows, Normalize, Atoms, Lambda, MaxIterations, Tolerance) :- - convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), - initModelWithTrainI(X, Xsize, Xrownum, Normalize, Atoms, Lambda, MaxIterations, Tolerance). - -foreign(initModelWithTrain, c, initModelWithTrainI( +pointer(float_array), +integer, +integer, - +integer, - +integer, +float32, +integer, +float32)). - - -%% --Input-- -%% bool normalize => (1)true / (0)false => false, -%% int atoms => 0, -%% float32 lambda => 0.0, -%% int maxIterations => 0, -%% float32 tolerance => 0.01 -%% -%% --Output-- -%% -%% --Description-- -%% Initializes the model but doesnt train it so train/4 has to be called befor encode/6 can be used. -%% -lcc_initModelNoTrain(Normalize, Atoms, Lambda, MaxIterations, Tolerance) :- - initModelNoTrainI(Normalize, Atoms, Lambda, MaxIterations, Tolerance). - -foreign(initModelNoTrain, c, initModelNoTrainI( +integer, - +integer, +float32, +integer, +float32)). - - -%% --Input-- %% mat data %% %% --Output-- %% mat codes %% %% --Description-- -%% Code each point via distance-weighted LARS. -%% -lcc_encode(DataList, DataRows, CodesList, YCols) :- - convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), - encodeI(X, Xsize, Xrows, Y, YCols, YRows), - convert_float_array_to_2d_list(Y, YCols, YRows, CodesList). - -foreign(encode, c, encodeI( +pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, -integer)). - - -%% --Input-- -%% mat data -%% -%% --Output-- -%% mat codes, -%% vec adjacencies -%% -%% --Description-- -%% Compute objective function given the list of adjacencies. -%% -lcc_objective(DataList, DataRows, CodesList, YCols, AdjacenciesList) :- - convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), - objectiveI(X, Xsize, Xrows, Y, YCols, YRows, Z, Zsize), - convert_float_array_to_2d_list(Y, YCols, YRows, CodesList), - convert_float_array_to_list(Z, Zsize, AdjacenciesList). - -foreign(objective, c, objectiveI( +pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, -integer, - -pointer(float_array), -integer)). - - -%% --Input-- -%% mat data -%% -%% --Output-- -%% mat codes, -%% vec adjacencies -%% -%% --Description-- -%% Learn dictionary by solving linear system. -%% -lcc_optimizeDictionary(DataList, DataRows, CodesList, YCols, AdjacenciesList) :- - convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), - optimizeDictionaryI(X, Xsize, Xrows, Y, YCols, YRows, Z, Zsize), - convert_float_array_to_2d_list(Y, YCols, YRows, CodesList), - convert_float_array_to_list(Z, Zsize, AdjacenciesList). - -foreign(optimizeDictionary, c, optimizeDictionaryI( +pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, -integer, - -pointer(float_array), -integer)). - - -%% --Input-- -%% mat data -%% -%% --Output-- -%% float32 final objective value -%% -%% --Description-- -%% Run local coordinate coding and train the model. +%% Initializes the model and trains it so encode/6 can be called after %% -lcc_train(DataList, DataRows, ReturnValue) :- - convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), - trainI(X, Xsize, Xrows, ReturnValue). +lcc(DataList, DataRows, Normalize, Atoms, Lambda, MaxIterations, Tolerance, TestDataList, TestDataRows, CodesList, ZRows) :- + Atoms > 0, + Lambda >= 0, + MaxIterations >= 0, + Tolerance > 0, + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + Atoms < (Xsize / Xrownum), + convert_list_to_float_array(TestDataList, TestDataRows, array(Ysize, Yrownum, Y)), + lccI(X, Xsize, Xrownum, Normalize, Atoms, Lambda, MaxIterations, Tolerance, Y, Ysize, Yrownum, Z, ZCols, ZRows), + convert_float_array_to_2d_list(Z, ZCols, ZRows, CodesList). -foreign(train, c, trainI( +pointer(float_array), +integer, +integer, - [-float32])). +foreign(lcc, c, lccI( +pointer(float_array), +integer, +integer, + +integer, + +integer, +float32, +integer, +float32, + +pointer(float_array), +integer, +integer, + -pointer(float_array), -integer, -integer)). %% Defines the functions that get connected from main.cpp -foreign_resource(local_coordinate_coding, [ initModelWithTrain, - initModelNoTrain, - encode, - objective, - optimizeDictionary, - train]). +foreign_resource(local_coordinate_coding, [lcc]). :- load_foreign_resource(local_coordinate_coding). diff --git a/src/methods/local_coordinate_coding/local_coordinate_coding_test.pl b/src/methods/local_coordinate_coding/local_coordinate_coding_test.pl index 0bdb5de..d4682db 100644 --- a/src/methods/local_coordinate_coding/local_coordinate_coding_test.pl +++ b/src/methods/local_coordinate_coding/local_coordinate_coding_test.pl @@ -6,38 +6,46 @@ :- use_module(local_coordinate_coding). :- use_module('../../helper_files/helper.pl'). -reset_Model :- - lcc_initModel(1,0,50,0.0001). %% -%% TESTING predicate predicate/10 +%% TESTING predicate lcc/11 %% -:- begin_tests(predicate). +:- begin_tests(lcc). %% Failure Tests -test(testDescription, [error(domain_error('expectation' , culprit), _)]) :- - reset_Model_No_Train(perceptron), - train([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, [0,0,0,0], 2, culprit, 50, 0.0001, _). +test(lcc_Bad_Atom_Input, fail) :- + lcc([5.1,3.5,1.4, 4.9,3.0,1.4, 4.7,3.2,1.3, 4.6,3.1,1.5], 3, 0, -2, 0.0, 0, 0.01, [5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, _, _), + lcc([5.1,3.5,1.4, 4.9,3.0,1.4, 4.7,3.2,1.3, 4.6,3.1,1.5], 3, 0, 4, 0.0, 0, 0.01, [5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, _, _). + +test(lcc_Negative_Lambda, fail) :- + lcc([5.1,3.5,1.4, 4.9,3.0,1.4, 4.7,3.2,1.3, 4.6,3.1,1.5], 3, 0, 2, -1.0, 0, 0.01, [5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, _, _). + +test(lcc_Negative_MaxIterations, fail) :- + lcc([5.1,3.5,1.4, 4.9,3.0,1.4, 4.7,3.2,1.3, 4.6,3.1,1.5], 3, 0, 2, 0.0, -1, 0.01, [5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, _, _). + +test(lcc_Negative_Tolerance, fail) :- + lcc([5.1,3.5,1.4, 4.9,3.0,1.4, 4.7,3.2,1.3, 4.6,3.1,1.5], 3, 0, 2, 0.0, 0, -0.01, [5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, _, _). + +test(lcc_Different_Dims, [error(_,system_error('matrix multiplication: incompatible matrix dimensions: 2x4 and 3x4'))]) :- + lcc([5.1,3.5,1.4, 4.9,3.0,1.4, 4.7,3.2,1.3, 4.6,3.1,1.5], 4, 0, 2, 0.0, 0, 0.01, [5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, _, _). -test(testDescription2, [error(_,system_error('The values of the Label have to start at 0 and be >= 0 and < the given numClass!'))]) :- - reset_Model_No_Train(perceptron), - train([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, [0,1,0,2], 2, perceptron, 50, 0.0001, _). - %% Successful Tests -test(testDescription3, [true(Error =:= 1)]) :- - reset_Model_No_Train(perceptron), - train([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, [0,0,0,0], 2, perceptron, 50, 0.0001, Error). +test(lcc_Normal_Use) :- + lcc([5.1,3.5,1.4, 4.9,3.0,1.4, 4.7,3.2,1.3, 4.6,3.1,1.5], 3, 0, 2, 0.0, 0, 0.01, [5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 3, CodesList, _), + print('\nCodes: '), + print(CodesList). -test(testDescription4, [true(Error =:= 0.9797958971132711)]) :- - reset_Model_No_Train(perceptron), +test(lcc_CSV_Input) :- open('src/data_csv/iris2.csv', read, File), take_csv_row(File, skipFirstRow,10, Data), - train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + lcc(Data, 4, 1, 5, 1.5, 50, 0.042, [5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 4, CodesList, _), + print('\nCodes: '), + print(CodesList). -:- end_tests(predicate). +:- end_tests(lcc). run_local_coordinate_coding_tests :- run_tests. -- GitLab