From 40d1dfc8026fbaea3eba422ae55faa37fcace2f8 Mon Sep 17 00:00:00 2001 From: Jakhes <dean.schmitz@schmitzbauer.de> Date: Tue, 11 Oct 2022 22:42:00 +0200 Subject: [PATCH] Adding Sparse_coding tests --- src/helper_files/helper.pl | 1 + src/methods/new_method/new_method_test.pl | 4 +- src/methods/sparse_coding/sparse_coding.cpp | 27 ++- src/methods/sparse_coding/sparse_coding.pl | 49 +++- .../sparse_coding/sparse_coding_test.pl | 221 ++++++++++++++---- test_all.pl | 4 +- 6 files changed, 236 insertions(+), 70 deletions(-) diff --git a/src/helper_files/helper.pl b/src/helper_files/helper.pl index dd56e21..85a9f77 100644 --- a/src/helper_files/helper.pl +++ b/src/helper_files/helper.pl @@ -46,6 +46,7 @@ convert_float_array_to_list(Mem, Index, Count, [Val|Rest]) :- get_contents(Mem, Index , Val). %% takes library(struct) array and fills a 2D [[a], [b]] with the content of the array from 0 to to given Index +%% The data gets transposed since in most mlpack matrices is every col a data point convert_float_array_to_2d_list(Mem, ColNum, RowNum, Out) :- convert_float_array_to_2d_list(Mem, RowNum, ColNum, 0, Out). diff --git a/src/methods/new_method/new_method_test.pl b/src/methods/new_method/new_method_test.pl index 1aee96d..7f0a5ab 100644 --- a/src/methods/new_method/new_method_test.pl +++ b/src/methods/new_method/new_method_test.pl @@ -32,8 +32,8 @@ test(testDescription3, [true(Error =:= 1)]) :- test(testDescription4, [true(Error =:= 0.9797958971132711)]) :- reset_Model_No_Train(perceptron), open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), - take_csv_row(File, skipFirstRow,10, Records), - train(Records, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + 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). :- end_tests(predicate). diff --git a/src/methods/sparse_coding/sparse_coding.cpp b/src/methods/sparse_coding/sparse_coding.cpp index dda7851..be067ef 100644 --- a/src/methods/sparse_coding/sparse_coding.cpp +++ b/src/methods/sparse_coding/sparse_coding.cpp @@ -32,6 +32,13 @@ SparseCoding sparseCoding; void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, SP_integer atoms, double lambda1, double lambda2, SP_integer maxIterations, double objTolerance, double newtonTolerance) { + if (dataMatSize/ dataMatRowNum < atoms) + { + raisePrologSystemExeption("There have to be more DataPoints than Atoms!"); + return; + } + + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); @@ -68,8 +75,17 @@ void encode(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, mat codesReturnMat; - sparseCoding.Encode(data, codesReturnMat); - + try + { + sparseCoding.Encode(data, codesReturnMat); + } + catch(const std::exception& e) + { + std::cerr << e.what() << '\n'; + raisePrologSystemExeption("Matrix has not the correct dimensions!"); + return; + } + // return the Matrix returnMatrixInformation(codesReturnMat, codesMatArr, codesMatColNum, codesMatRowNum); @@ -83,9 +99,14 @@ void encode(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, // description: double train(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum) { + if (dataMatSize/ dataMatRowNum < sparseCoding.Atoms()) + { + raisePrologSystemExeption("There have to be more DataPoints than Atoms!"); + return 0.0; + } // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); return sparseCoding.Train(data, RandomInitializer()); -} \ No newline at end of file +} diff --git a/src/methods/sparse_coding/sparse_coding.pl b/src/methods/sparse_coding/sparse_coding.pl index 624eeb9..c7f4b4e 100644 --- a/src/methods/sparse_coding/sparse_coding.pl +++ b/src/methods/sparse_coding/sparse_coding.pl @@ -1,8 +1,8 @@ -:- module(sparse_coding, [ initModelWithTrain/9, +:- module(sparse_coding, [ initModelWithTrain/8, initModelNoTrain/6, - encode/6, - train/4]). + encode/4, + train/3]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -20,6 +20,9 @@ %% definitions for the connected function + +foreign(initModelWithTrain, c, initModelWithTrainI( +pointer(float_array), +integer, +integer, + +integer, +float32, +float32, +integer, +float32, +float32)). %% --Input-- %% mat data, %% int atoms => 15, @@ -34,10 +37,18 @@ %% --Description-- %% Initializes sparse_coding model and trains it. %% -foreign(initModelWithTrain, c, initModelWithTrain( +pointer(float_array), +integer, +integer, - +integer, +float32, +float32, +integer, +float32, +float32)). - - +initModelWithTrain(MatList, MatRows, Atoms, Lambda1, Lambda2, MaxIterations, ObjTolerance, NewtonTolerance) :- + Atoms >= 0, + Lambda1 > 0, + Lambda2 >= 0, + MaxIterations >= 0, + ObjTolerance > 0, + NewtonTolerance > 0, + convert_list_to_float_array(MatList, MatRows, array(Xsize, Xrownum, X)), + initModelWithTrainI(X, Xsize, Xrownum, Atoms, Lambda1, Lambda2, MaxIterations, ObjTolerance, NewtonTolerance). + + +foreign(initModelNoTrain, c, initModelNoTrainI(+integer, +float32, +float32, +integer, +float32, +float32)). %% --Input-- %% int atoms => 15, %% float32 lambda1 => 0, @@ -51,9 +62,18 @@ foreign(initModelWithTrain, c, initModelWithTrain( +pointer(float_array), + %% --Description-- %% Initializes sparse_coding model but will not train the model, and a subsequent call to Train will be required before the model can encode points with Encode. %% -foreign(initModelNoTrain, c, initModelNoTrain(+integer, +float32, +float32, +integer, +float32, +float32)). +initModelNoTrain(Atoms, Lambda1, Lambda2, MaxIterations, ObjTolerance, NewtonTolerance) :- + Atoms >= 0, + Lambda1 > 0, + Lambda2 >= 0, + MaxIterations >= 0, + ObjTolerance > 0, + NewtonTolerance > 0, + initModelNoTrainI(Atoms, Lambda1, Lambda2, MaxIterations, ObjTolerance, NewtonTolerance). +foreign(encode, c, encodeI( +pointer(float_array), +integer, +integer, + -pointer(float_array), -integer, -integer)). %% --Input-- %% mat data %% @@ -63,10 +83,14 @@ foreign(initModelNoTrain, c, initModelNoTrain(+integer, +float32, +float32, +int %% --Description-- %% Sparse code each point in the given dataset via LARS, using the current dictionary and store the encoded data in the codes matrix. %% -foreign(encode, c, encode( +pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, -integer)). +encode(DataList, DataRows, CodesList, YCols) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + encodeI(X, Xsize, Xrownum, Y, YCols, YRows), + convert_float_array_to_2d_list(Y, YCols, YRows, CodesList). +foreign(train, c, trainI(+pointer(float_array), +integer, +integer, + [-float32])). %% --Input-- %% mat data %% @@ -76,8 +100,9 @@ foreign(encode, c, encode( +pointer(float_array), +integer, +integer, %% --Description-- %% Train the sparse coding model on the given dataset. %% -foreign(train, c, train(+pointer(float_array), +integer, +integer, - [-float32])). +train(DataList, DataRows, ReturnValue) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + trainI(X, Xsize, Xrownum, ReturnValue). %% Defines the functions that get connected from main.cpp diff --git a/src/methods/sparse_coding/sparse_coding_test.pl b/src/methods/sparse_coding/sparse_coding_test.pl index e8f2663..8cbb930 100644 --- a/src/methods/sparse_coding/sparse_coding_test.pl +++ b/src/methods/sparse_coding/sparse_coding_test.pl @@ -1,56 +1,175 @@ + :- use_module(library(plunit)). :- use_module(sparse_coding). :- use_module('../../helper_files/helper.pl'). -reset_Model :- - initModel(1,0,50,0.0001). - -:- begin_tests(lists). - -%% alpha tests -test(alpha_std_init) :- - reset_Model, - alpha(0). -test(alpha_wrong_input, fail) :- - reset_Model, - alpha(1). -test(alpha_after_train, A =:= 9223372036854775808) :- - reset_Model, - convert_list_to_float_array([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, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize), - alpha(A). - -%% train tests -test(correct_train) :- - reset_Model, - convert_list_to_float_array([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, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train, fail) :- - reset_Model, - convert_list_to_float_array([],3, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train2, fail) :- - reset_Model, - convert_list_to_float_array([],0, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train3, fail) :- - reset_Model, - convert_list_to_float_array([1,2],0, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train3, fail) :- - reset_Model, - convert_list_to_float_array([1,2,44,3],3, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -test(false_train4) :- - reset_Model, - convert_list_to_float_array([1,2,44,3],2, array(Xsize, Xrownum, X)), - convert_list_to_float_array([0.2,0.2,0.2,0.2], array(Ysize, Y)), - train(X,Xsize, Xrownum,Y, Ysize). -:- end_tests(lists). \ No newline at end of file + +reset_Model_With_Train_A :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,20, Data), + initModelWithTrain(Data,4,15,0.1,0.0,100,0.01,0.000001). +reset_Model_No_Train_A :- + initModelNoTrain(2,0.1,0.0,100,0.01,0.000001). + + +%% +%% TESTING predicate initModelWithTrain/8 +%% +:- begin_tests(initModelWithTrain). + +%% Failure Tests + +test(initModelWithTrain_Negative_RowNum, fail) :- + initModelWithTrain([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,15,0.1,0.0,100,0.01,0.000001). + +test(initModelWithTrain_Negative_Atoms, fail) :- + initModelWithTrain([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,-15,0.1,0.0,100,0.01,0.000001). + +test(initModelWithTrain_Negative_MaxIterations, fail) :- + initModelWithTrain([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,15,0.1,0.0,-100,0.01,0.000001). + +test(initModelWithTrain_Negative_ObjTolerance, fail) :- + initModelWithTrain([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,15,0.1,0.0,100,-0.01,0.000001). + +test(initModelWithTrain_Negative_NewtonTolerance, fail) :- + initModelWithTrain([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,15,0.1,0.0,100,0.01,-0.000001). + +test(initModelWithTrain_Empty_List, fail) :- + initModelWithTrain([], 3,15,0.1,0.0,100,0.01,-0.000001). + +test(initModelWithTrain_Data_Amount_Smaller_Than_Atoms, [error(_,system_error('There have to be more DataPoints than Atoms!'))]) :- + initModelWithTrain([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,10,0.1,0.0,2,0.01,0.000001). + + +%% Successful Tests + +test(initModelWithTrain_Direct_Input_Use) :- + initModelWithTrain([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, 3,0.1,0.0,2,0.01,0.000001). + +test(initModelWithTrain_Changed_Input) :- + initModelWithTrain([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 6,2,2.3,0.1,30,0.002,0.0001). + +test(initModelWithTrain_CSV_Use) :- + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,20, Data), + initModelWithTrain(Data,4,15,0.1,0.0,100,0.01,0.000001). + +:- end_tests(initModelWithTrain). + + +%% +%% TESTING predicate initModelNoTrain/6 +%% +:- begin_tests(initModelNoTrain). + +%% Failure Tests + +test(initModelNoTrain_Negative_Atoms, fail) :- + initModelNoTrain(-15,0.1,0.0,100,0.01,0.000001). + +test(initModelNoTrain_Negative_MaxIterations, fail) :- + initModelNoTrain(15,0.1,0.0,-100,0.01,0.000001). + +test(initModelNoTrain_Negative_ObjTolerance, fail) :- + initModelNoTrain(15,0.1,0.0,100,-0.01,0.000001). + +test(initModelNoTrain_Negative_NewtonTolerance, fail) :- + initModelNoTrain(15,0.1,0.0,100,0.01,-0.000001). + +test(initModelNoTrain_Empty_List, fail) :- + initModelNoTrain(15,0.1,0.0,100,0.01,-0.000001). + + +%% Successful Tests + +test(initModelNoTrain_Normal_Input_Use) :- + initModelNoTrain(15,0.1,0.0,100,0.01,0.000001). + +test(initModelNoTrain_Changed_Input) :- + initModelNoTrain(5,2.3,0.2,200,0.002,0.0001). + +:- end_tests(initModelNoTrain). + + +%% +%% TESTING predicate encode/4 +%% +:- begin_tests(encode). + +%% Failure Tests + +test(encode_With_No_Trained_Model, [error(_,system_error('Matrix has not the correct dimensions!'))]) :- + reset_Model_No_Train_A, + encode([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, CodesRows), + print(CodesList), + print('\n'), + print(CodesRows). + +test(encode_With_Not_Fitting_Data, [error(_,system_error('Matrix has not the correct dimensions!'))]) :- + reset_Model_No_Train_A, + encode([5.1,3.5,1.4,4.9,3.0,1.4,4.7,3.2,1.3,4.6,3.1,1.5], 2, CodesList, CodesRows), + print(CodesList), + print('\n'), + print(CodesRows). + + +%% Successful Tests + +test(encode_Normal_Use1) :- + reset_Model_With_Train_A, + encode([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, CodesRows), + print(CodesList), + print('\n'), + print(CodesRows). + + +test(encode_Normal_Use2) :- + reset_Model_No_Train_A, + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,10, Data), + train(Data, 4, _), + encode([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, CodesRows), + print(CodesList), + print('\n'), + print(CodesRows). + +:- end_tests(encode). + + +%% +%% TESTING predicate train/3 +%% +:- begin_tests(train). + +%% Failure Tests + +test(train_With_Negative_RowNum, fail) :- + reset_Model_No_Train_A, + 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, _). + +test(train_With_Empty_Data_List1, fail) :- + reset_Model_No_Train_A, + train([], 1, _). + +test(train_With_Empty_Data_List2, fail) :- + reset_Model_No_Train_A, + train([], 0, _). + + +%% Successful Tests + +test(train_With_Direkt_Input) :- + reset_Model_No_Train_A, + 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, ObjectiveValue), + print(ObjectiveValue). + +test(train_With_CSV_Input) :- + reset_Model_No_Train_A, + open('/home/afkjakhes/eclipse-workspace/prolog-mlpack-libary/src/data_csv/iris2.csv', read, File), + take_csv_row(File, skipFirstRow,20, Data), + train(Data, 4, ObjectiveValue), + print(ObjectiveValue). + +:- end_tests(train). + diff --git a/test_all.pl b/test_all.pl index ec3331c..e6c45d1 100644 --- a/test_all.pl +++ b/test_all.pl @@ -1,4 +1,4 @@ -:- use_module(library(plunit)). - :- ['src/methods/adaboost/adaboost_test.pl']. + +:- ['src/methods/sparse_coding/sparse_coding_test.pl']. \ No newline at end of file -- GitLab