From 70070da24b14a7d1b8c797dc7e0745c5897fbb3f Mon Sep 17 00:00:00 2001 From: Jakhes <dean.schmitz@schmitzbauer.de> Date: Sun, 16 Oct 2022 19:43:34 +0200 Subject: [PATCH] Preparing Methods for tests --- src/methods/dbscan/dbscan.pl | 10 +- src/methods/decision_tree/decision_tree.pl | 30 +-- src/methods/hoeffding_tree/hoeffding_tree.cpp | 16 +- src/methods/hoeffding_tree/hoeffding_tree.pl | 39 ++-- .../hoeffding_tree/hoeffding_tree_test.pl | 150 ++++++++---- src/methods/kde/kde.cpp | 57 ++++- src/methods/kde/kde.pl | 33 ++- src/methods/kde/kde_test.pl | 147 ++++++++---- src/methods/kernel_pca/kernel_pca.cpp | 20 +- src/methods/kernel_pca/kernel_pca.pl | 35 ++- src/methods/kernel_pca/kernel_pca_test.pl | 84 +++---- src/methods/kfn/kfn.cpp | 40 +++- src/methods/kfn/kfn.pl | 38 +-- src/methods/kfn/kfn_test.pl | 146 ++++++++---- src/methods/kmeans/kmeans_test.pl | 90 +++---- src/methods/knn/knn.cpp | 38 ++- src/methods/knn/knn.pl | 27 ++- src/methods/knn/knn_test.pl | 85 +++---- src/methods/lars/lars.cpp | 185 +++++++++------ src/methods/lars/lars.pl | 116 +++++++--- src/methods/lars/lars_test.pl | 39 +++- src/methods/linear_SVM/linear_SVM.cpp | 126 ++++++---- src/methods/linear_SVM/linear_SVM.pl | 50 +++- src/methods/linear_SVM/linear_SVM_test.pl | 39 +++- .../linear_regression/linear_regression.cpp | 1 - .../linear_regression/linear_regression.pl | 80 +++++-- .../linear_regression_test.pl | 39 +++- src/methods/lmnn/lmnn.cpp | 107 +++++---- src/methods/lmnn/lmnn.pl | 8 +- src/methods/lmnn/lmnn_test.pl | 84 +++---- .../local_coordinate_coding.cpp | 89 +++++-- .../local_coordinate_coding.pl | 56 +++-- .../local_coordinate_coding_test.pl | 84 +++---- .../logistic_regression.cpp | 219 ++++++++++++------ .../logistic_regression.pl | 90 ++++--- .../logistic_regression_test.pl | 84 +++---- src/methods/lsh/lsh.cpp | 94 ++++++-- src/methods/lsh/lsh.pl | 55 ++++- src/methods/lsh/lsh_test.pl | 84 +++---- src/methods/mean_shift/mean_shift.cpp | 13 +- src/methods/mean_shift/mean_shift.pl | 10 +- src/methods/mean_shift/mean_shift_test.pl | 39 +++- .../naive_bayes_classifier.cpp | 152 ++++++++---- .../naive_bayes_classifier.pl | 77 ++++-- .../naive_bayes_classifier_test.pl | 84 +++---- src/methods/nca/nca.cpp | 82 ++++--- src/methods/nca/nca.pl | 12 +- src/methods/nca/nca_test.pl | 84 +++---- test_all.pl | 73 ++++++ 49 files changed, 2239 insertions(+), 1201 deletions(-) diff --git a/src/methods/dbscan/dbscan.pl b/src/methods/dbscan/dbscan.pl index 3fc5743..d3c86b9 100644 --- a/src/methods/dbscan/dbscan.pl +++ b/src/methods/dbscan/dbscan.pl @@ -16,6 +16,11 @@ %% definitions for the connected function +foreign(dbscan, c, dbscanI( +float32, +integer, +integer, + +string, +string, + +pointer(float_array), +integer, +integer, + -pointer(float_array), -integer, + -pointer(float_array), -integer, -integer)). %% --Input-- %% double epsilon %% int minPoints @@ -31,11 +36,6 @@ %% --Description-- %% This is a one predicate model where you configure the model with the input parameters and get returned the results in the same predicate. %% -foreign(dbscan, c, dbscanI( +float32, +integer, +integer, - +string, +string, - +pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, - -pointer(float_array), -integer, -integer)). dbscan(Epsilon, MinPoints, BatchMode, SelectionType, TreeType, DataList, DataRows, AssignList, CentroidsList, ZCols) :- Epsilon > 0, MinPoints > 0, diff --git a/src/methods/decision_tree/decision_tree.pl b/src/methods/decision_tree/decision_tree.pl index 687ea26..3bcb22a 100644 --- a/src/methods/decision_tree/decision_tree.pl +++ b/src/methods/decision_tree/decision_tree.pl @@ -20,9 +20,6 @@ %% definitions for the connected function -foreign(initModel, c, initModelI( +pointer(float_array), +integer, +integer, - +pointer(float_array), +integer, - +integer, +integer, +float32, +integer)). %% --Input-- %% mat dataset, %% vec labels, @@ -47,10 +44,11 @@ initModel(DataList, DataRows, LabelsList, NumClasses, MinimumLeafSize, MinimumGa convert_list_to_float_array(LabelsList, array(Ysize, Y)), initModelI(X, Xsize, Xrownum, Y, Ysize, NumClasses, MinimumLeafSize, MinimumGainSplit, MaximumDepth). +foreign(initModel, c, initModelI( +pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +integer, +integer, +float32, +integer)). + -foreign(classifyPoint, c, classifyPointI(+pointer(float_array), +integer, - -integer, - -pointer(float_array), -integer)). %% --Input-- %% vec point %% @@ -66,10 +64,11 @@ classifyPoint(DataList, Prediction, AssignList) :- classifyPointI(X, Xsize, Prediction, Y, Ysize), convert_float_array_to_list(Y, Ysize, AssignList). +foreign(classifyPoint, c, classifyPointI(+pointer(float_array), +integer, + -integer, + -pointer(float_array), -integer)). + -foreign(classifyMatrix, c, classifyMatrixI( +pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, - -pointer(float_array), -integer, -integer)). %% --Input-- %% mat data %% @@ -86,11 +85,11 @@ classifyMatrix(DataList, DataRows, PredictionList, ProbsList, ZCols) :- convert_float_array_to_list(Y, Ysize, PredictionList), convert_float_array_to_2d_list(Z, ZCols, ZRows, ProbsList). +foreign(classifyMatrix, c, classifyMatrixI( +pointer(float_array), +integer, +integer, + -pointer(float_array), -integer, + -pointer(float_array), -integer, -integer)). + -foreign(train, c, trainI(+pointer(float_array), +integer, +integer, - +pointer(float_array), +integer, - +integer, +integer, +float32, +integer, - [-float32])). %% --Input-- %% mat data, %% vec labels, @@ -116,6 +115,11 @@ train(DataList, DataRows, LabelsList, NumClasses, MinimumLeafSize, MinimumGainSp convert_list_to_float_array(LabelsList, array(Ysize, Y)), trainI(X, Xsize, Xrownum, Y, Ysize, NumClasses, MinimumLeafSize, MinimumGainSplit, MaximumDepth, Entropy). +foreign(train, c, trainI(+pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +integer, +integer, +float32, +integer, + [-float32])). + %% Defines the functions that get connected from main.cpp foreign_resource(decision_tree, [ initModel, diff --git a/src/methods/hoeffding_tree/hoeffding_tree.cpp b/src/methods/hoeffding_tree/hoeffding_tree.cpp index 1a443e3..9e33262 100644 --- a/src/methods/hoeffding_tree/hoeffding_tree.cpp +++ b/src/methods/hoeffding_tree/hoeffding_tree.cpp @@ -18,7 +18,7 @@ using namespace mlpack::tree; // Global Variable of the HoeffdingTreeModel object so it can be accessed from all functions HoeffdingTreeModel hoeffdingTreeObj; -// TODO: + // input: const TreeType & type = GINI_HOEFFDING, // const arma::mat & dataset, // const data::DatasetInfo & datasetInfo, @@ -33,10 +33,14 @@ HoeffdingTreeModel hoeffdingTreeObj; // const size_t observationsBeforeBinning // output: // description: +// Construct the Hoeffding tree with the given parameters and given training data. +// void initAndBuildModel(char const *treeType, float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, - SP_integer numClasses, SP_integer batchTraining, double successProbability, SP_integer maxSamples, SP_integer checkInterval, SP_integer minSamples, SP_integer bins, SP_integer observationsBeforeBinning) + SP_integer numClasses, + SP_integer batchTraining, + double successProbability, SP_integer maxSamples, SP_integer checkInterval, SP_integer minSamples, SP_integer bins, SP_integer observationsBeforeBinning) { // convert the Prolog arrays to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); @@ -58,12 +62,14 @@ void initAndBuildModel(char const *treeType, hoeffdingTreeObj.BuildModel(data, data::DatasetInfo(data.n_rows), labelsVector, numClasses, (batchTraining == 1), successProbability, maxSamples, checkInterval, minSamples, bins, observationsBeforeBinning); } -// TODO: + // input: const arma::mat & dataset, // arma::Row< size_t > & predictions <-, // arma::rowvec & probabilities <- // output: // description: +// Classify the given points, using this node and the entire (sub)tree beneath it. +// void classify(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float **predictArr, SP_integer *predictArrSize, float **probsArr, SP_integer *probsArrSize) @@ -88,12 +94,14 @@ void classify(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNu returnVectorInformation(probsReturnVector, probsArr, probsArrSize); } -// TODO: + // input: const arma::mat & dataset, // const arma::Row< size_t > & labels, // const bool batchTraining // output: // description: +// Train in streaming mode on the given dataset. +// void train(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, SP_integer batchTraining) diff --git a/src/methods/hoeffding_tree/hoeffding_tree.pl b/src/methods/hoeffding_tree/hoeffding_tree.pl index 01b525c..39eeb3c 100644 --- a/src/methods/hoeffding_tree/hoeffding_tree.pl +++ b/src/methods/hoeffding_tree/hoeffding_tree.pl @@ -1,7 +1,7 @@ -:- module(hoeffding_tree, [ initAndBuildModel/14, - classify/7, - train/6]). +:- module(hoeffding_tree, [ initAndBuildModel/12, + classify/4, + train/4]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -19,6 +19,10 @@ %% definitions for the connected function +foreign(initAndBuildModel, c, initAndBuildModelI(+string, + +pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +integer, +integer, +float32, +integer, +integer, +integer, +integer, +integer)). %% --Input-- %% string treeType => "gini-hoeffding", "gini-binary", "info-hoeffding", "info-binary", %% mat dataset, @@ -38,12 +42,15 @@ %% Construct the Hoeffding tree with the given parameters and given training data. %% The tree may be trained either in batch mode (which looks at all points before splitting, and propagates these points to the created children for further training), or in streaming mode, where each point is only considered once. (In general, batch mode will give better-performing trees, but will have higher memory and runtime costs for the same dataset.) %% -foreign(initAndBuildModel, c, initAndBuildModel(+string, - +pointer(float_array), +integer, +integer, - +pointer(float_array), +integer, - +integer, +integer, +float32, +integer, +integer, +integer, +integer, +integer)). +initAndBuildModel(TreeType, DataList, DataRows, LabelsList, NumClasses, BatchTraining, SuccessProbability, MaxSamples, CheckInterval, MinSamples, Bins, ObservationsBeforeBinning) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(LabelsList, array(Ysize, Y)), + initAndBuildModelI(TreeType, X, Xsize, Xrownum, Y, Ysize, NumClasses, BatchTraining, SuccessProbability, MaxSamples, CheckInterval, MinSamples, Bins, ObservationsBeforeBinning). +foreign(classify, c, classifyI( +pointer(float_array), +integer, +integer, + -pointer(float_array), -integer, + -pointer(float_array), -integer)). %% --Input-- %% mat data %% @@ -55,11 +62,16 @@ foreign(initAndBuildModel, c, initAndBuildModel(+string, %% Classify the given points, using this node and the entire (sub)tree beneath it. %% The predicted labels for each point are returned, as well as an estimate of the probability that the prediction is correct for each point. This estimate is simply the MajorityProbability for the leaf that each point bins to. %% -foreign(classify, c, classify( +pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, - -pointer(float_array), -integer)). +classify(TestList, TestRows, PredicList, ProbsList) :- + convert_list_to_float_array(TestList, TestRows, array(Xsize, Xrownum, X)), + classifyI(X, Xsize, Xrownum, Y, Ysize, Z, Zsize), + convert_float_array_to_list(Y, Ysize, PredicList), + convert_float_array_to_list(Z, Zsize, ProbsList). +foreign(train, c, trainI(+pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +integer)). %% --Input-- %% mat data, %% vec labels, @@ -71,9 +83,10 @@ foreign(classify, c, classify( +pointer(float_array), +integer, +integer, %% Train in streaming mode on the given dataset. %% This takes one pass. Be sure that initAndBuildModel/14 has been called first! %% -foreign(train, c, train(+pointer(float_array), +integer, +integer, - +pointer(float_array), +integer, - +integer)). +train(DataList, DataRows, LabelsList, BatchTraining) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(LabelsList, array(Ysize, Y)), + trainI(X, Xsize, Xrownum, Y, Ysize, BatchTraining). %% Defines the functions that get connected from main.cpp diff --git a/src/methods/hoeffding_tree/hoeffding_tree_test.pl b/src/methods/hoeffding_tree/hoeffding_tree_test.pl index cf01d51..2043446 100644 --- a/src/methods/hoeffding_tree/hoeffding_tree_test.pl +++ b/src/methods/hoeffding_tree/hoeffding_tree_test.pl @@ -1,56 +1,106 @@ + +:- module(hoeffding_tree_tests, [run_hoeffding_tree_tests/0]). + :- use_module(library(plunit)). :- use_module(hoeffding_tree). :- 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 + initAndBuildModel(1,0,50,0.0001). + +%% +%% TESTING predicate initAndBuildModel/12 +%% +:- begin_tests(initAndBuildModel). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(initAndBuildModel). + + +%% +%% TESTING predicate classify/4 +%% +:- begin_tests(classify). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(classify). + + +%% +%% TESTING predicate train/4 +%% +:- begin_tests(train). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(train). + +run_hoeffding_tree_tests :- + run_tests. + diff --git a/src/methods/kde/kde.cpp b/src/methods/kde/kde.cpp index c4d8905..6609138 100644 --- a/src/methods/kde/kde.cpp +++ b/src/methods/kde/kde.cpp @@ -18,7 +18,7 @@ using namespace mlpack::kde; // Global Variable of the KDEModel object so it can be accessed from all functions KDEModel kdeModel; -// TODO: + // input: const double bandwidth = 1.0, // const double relError = KDEDefaultParams::relError, // const double absError = KDEDefaultParams::absError, @@ -32,12 +32,14 @@ KDEModel kdeModel; // arma::mat && referenceSet, // output: // description: +// Build the KDE model with the given parameters and then trains it with the given reference data. +// void initAndBuildModel(double bandwidth, double relError, double absError, char const *kernelType, char const *treeType, char const *algorithm, SP_integer monteCarlo, double mcProb, SP_integer initialSampleSize, double mcEntryCoef, double mcBreakCoef, float *referenceMatArr, SP_integer referenceMatSize, SP_integer referenceMatRowNum) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat reference = convertArrayToMat(referenceMatArr, referenceMatSize, referenceMatRowNum); // select the kernelType @@ -65,7 +67,7 @@ void initAndBuildModel(double bandwidth, double relError, double absError, } else { - cout << "wrong kernelType input" << endl; + raisePrologSystemExeption("The given KernelType is unknown!"); } // select the treeType @@ -93,11 +95,13 @@ void initAndBuildModel(double bandwidth, double relError, double absError, } else { - cout << "wrong treeType input" << endl; + raisePrologSystemExeption("The given TreeType is unknown!"); } + kdeModel = KDEModel(bandwidth, relError, absError, kernelT, treeT, (monteCarlo == 1), mcProb, initialSampleSize, mcEntryCoef, mcBreakCoef); + if (strcmp(algorithm, "dual-tree") == 0) { KDEMode& mode = kdeModel.Mode(); @@ -110,41 +114,72 @@ void initAndBuildModel(double bandwidth, double relError, double absError, } else { - cout << "wrong algorithm input" << endl; + raisePrologSystemExeption("The given Algorithm is unknown!"); } - kdeModel.BuildModel(move(reference)); + + try + { + kdeModel.BuildModel(move(reference)); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } } -// TODO: + // input: arma::mat && querySet, // arma::vec & estimations <- // output: // description: +// Perform kernel density estimation on the given query set. +// void evaluateWithQuery(float *querySetMatArr, SP_integer querySetMatSize, SP_integer querySetMatRowNum, float **estimationsArr, SP_integer *estimationsArrSize) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat querySet = convertArrayToMat(querySetMatArr, querySetMatSize, querySetMatRowNum); // create the ReturnVector vec estimationsReturnVector; - kdeModel.Evaluate(move(querySet), estimationsReturnVector); + + try + { + kdeModel.Evaluate(move(querySet), estimationsReturnVector); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } + + // return the Vector returnVectorInformation(estimationsReturnVector, estimationsArr, estimationsArrSize); } -// TODO: + // input: arma::vec & estimations <- // output: // description: +// Perform kernel density estimation on the reference set. +// void evaluateNoQuery(float **estimationsArr, SP_integer *estimationsArrSize) { // create the ReturnVector vec estimationsReturnVector; - kdeModel.Evaluate(estimationsReturnVector); + + try + { + kdeModel.Evaluate(estimationsReturnVector); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } + // return the Vector returnVectorInformation(estimationsReturnVector, estimationsArr, estimationsArrSize); diff --git a/src/methods/kde/kde.pl b/src/methods/kde/kde.pl index 6508c8e..1b145b5 100644 --- a/src/methods/kde/kde.pl +++ b/src/methods/kde/kde.pl @@ -1,7 +1,7 @@ -:- module(kde, [ initAndBuildModel/14, - evaluateWithQuery/5, - evaluateNoQuery/2]). +:- module(kde, [ initAndBuildModel/13, + evaluateWithQuery/3, + evaluateNoQuery/1]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -19,6 +19,11 @@ %% definitions for the connected function +foreign(initAndBuildModel, c, initAndBuildModelI(+float32, +float32, +float32, + +string, +string, +string, + +integer, + +float32, +integer, +float32, +float32, + +pointer(float_array), +integer, +integer)). %% --Input-- %% float32 bandwidth => 1.0, %% float32 relError => 0.05, @@ -38,13 +43,13 @@ %% --Description-- %% Build the KDE model with the given parameters and then trains it with the given reference data. %% -foreign(initAndBuildModel, c, initAndBuildModel(+float32, +float32, +float32, - +string, +string, +string, - +integer, - +float32, +integer, +float32, +float32, - +pointer(float_array), +integer, +integer)). +initAndBuildModel(Bandwidth, RelError, AbsError, KernelType, TreeType, Algorithm, MonteCarlo, McProb, InitialSampleSize, MCEntryCoef, MCBreakCoef, DataList, DataRows) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + initAndBuildModelI(Bandwidth, RelError, AbsError, KernelType, TreeType, Algorithm, MonteCarlo, McProb, InitialSampleSize, MCEntryCoef, MCBreakCoef, X, Xsize, Xrownum). +foreign(evaluateWithQuery, c, evaluateWithQueryI(+pointer(float_array), +integer, +integer, + -pointer(float_array), -integer)). %% --Input-- %% mat querySet %% @@ -52,13 +57,15 @@ foreign(initAndBuildModel, c, initAndBuildModel(+float32, +float32, +float32, %% vec estimations %% %% --Description-- -%% Perform kernel density estimation on the given query set. %% initAndBuildModel/14 has to be called before. %% -foreign(evaluateWithQuery, c, evaluateWithQuery(+pointer(float_array), +integer, +integer, - -pointer(float_array), -integer)). +evaluateWithQuery(QueryList, QueryRows, EstimationList) :- + convert_list_to_float_array(QueryList, QueryRows, array(Xsize, Xrownum, X)), + evaluateWithQueryI(X, Xsize, Xrownum, Y, Ysize), + convert_float_array_to_list(Y, Ysize, EstimationList). +foreign(evaluateNoQuery, c, evaluateNoQueryI(-pointer(float_array), -integer)). %% --Input-- %% %% --Output-- @@ -69,7 +76,9 @@ foreign(evaluateWithQuery, c, evaluateWithQuery(+pointer(float_array), +integer, %% If possible, it returns normalized estimations. %% initAndBuildModel/14 has to be called before. %% -foreign(evaluateNoQuery, c, evaluateNoQuery(-pointer(float_array), -integer)). +evaluateNoQuery(EstimationList) :- + evaluateNoQueryI(Y, Ysize), + convert_float_array_to_list(Y, Ysize, EstimationList). %% Defines the functions that get connected from main.cpp diff --git a/src/methods/kde/kde_test.pl b/src/methods/kde/kde_test.pl index b46d742..991662c 100644 --- a/src/methods/kde/kde_test.pl +++ b/src/methods/kde/kde_test.pl @@ -1,3 +1,6 @@ + +:- module(kde_tests, [run_kde_tests/0]). + :- use_module(library(plunit)). :- use_module(kde). @@ -6,51 +9,99 @@ 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 + +%% +%% TESTING predicate initAndBuildModel/10 +%% +:- begin_tests(initAndBuildModel). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(initAndBuildModel). + + +%% +%% TESTING predicate evaluateWithQuery/10 +%% +:- begin_tests(evaluateWithQuery). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(evaluateWithQuery). + + +%% +%% TESTING predicate evaluateNoQuery/10 +%% +:- begin_tests(evaluateNoQuery). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(evaluateNoQuery). + +run_kde_tests :- + run_tests. + diff --git a/src/methods/kernel_pca/kernel_pca.cpp b/src/methods/kernel_pca/kernel_pca.cpp index 579945c..374ce41 100644 --- a/src/methods/kernel_pca/kernel_pca.cpp +++ b/src/methods/kernel_pca/kernel_pca.cpp @@ -42,7 +42,7 @@ void useNystroemKernelPCA(char const *nystroemMethod, KernelType kernel, bool ce } else { - cout << "wrong nystroem input" << endl; + raisePrologDomainExeption(nystroemMethod, 4, "The given NystoemMethod is unkown!", "kernel_pca"); } } @@ -56,7 +56,7 @@ void useNystroemKernelPCA(char const *nystroemMethod, KernelType kernel, bool ce // const size_t newDimension // output: // description: -void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer useNystoem, char const *nystroemMethod, +void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer useNystroem, char const *nystroemMethod, double degree, double offset, double bandwidth, double scale, float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float **transformedDataMatArr, SP_integer *transformedDataMatColNum, SP_integer *transformedDataMatRowNum, @@ -81,7 +81,7 @@ void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer if (strcmp(kernel, "linear") == 0) { LinearKernel lk; - if(useNystoem == 1) + if(useNystroem == 1) { useNystroemKernelPCA<LinearKernel>(nystroemMethod, lk, (centerTranformedData == 1), data, transformedDataReturnMat, eigvalReturnVector, eigvecReturnMat, returnDim); } @@ -94,7 +94,7 @@ void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer else if (strcmp(kernel, "polynomial") == 0) { PolynomialKernel pk(degree, offset); - if(useNystoem == 1) + if(useNystroem == 1) { useNystroemKernelPCA<PolynomialKernel>(nystroemMethod, pk, (centerTranformedData == 1), data, transformedDataReturnMat, eigvalReturnVector, eigvecReturnMat, returnDim); } @@ -107,7 +107,7 @@ void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer else if (strcmp(kernel, "cosine") == 0) { CosineDistance cd; - if(useNystoem == 1) + if(useNystroem == 1) { useNystroemKernelPCA<CosineDistance>(nystroemMethod, cd, (centerTranformedData == 1), data, transformedDataReturnMat, eigvalReturnVector, eigvecReturnMat, returnDim); } @@ -120,7 +120,7 @@ void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer else if (strcmp(kernel, "gaussian") == 0) { GaussianKernel gk(bandwidth); - if(useNystoem == 1) + if(useNystroem == 1) { useNystroemKernelPCA<GaussianKernel>(nystroemMethod, gk, (centerTranformedData == 1), data, transformedDataReturnMat, eigvalReturnVector, eigvecReturnMat, returnDim); } @@ -133,7 +133,7 @@ void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer else if (strcmp(kernel, "epanechnikov") == 0) { EpanechnikovKernel ek(bandwidth); - if(useNystoem == 1) + if(useNystroem == 1) { useNystroemKernelPCA<EpanechnikovKernel>(nystroemMethod, ek, (centerTranformedData == 1), data, transformedDataReturnMat, eigvalReturnVector, eigvecReturnMat, returnDim); } @@ -146,7 +146,7 @@ void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer else if (strcmp(kernel, "laplacian") == 0) { LaplacianKernel tk(bandwidth); - if(useNystoem == 1) + if(useNystroem == 1) { useNystroemKernelPCA<LaplacianKernel>(nystroemMethod, tk, (centerTranformedData == 1), data, transformedDataReturnMat, eigvalReturnVector, eigvecReturnMat, returnDim); } @@ -159,7 +159,7 @@ void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer else if (strcmp(kernel, "hyptan") == 0) { HyperbolicTangentKernel htk(scale, offset); - if(useNystoem == 1) + if(useNystroem == 1) { useNystroemKernelPCA<HyperbolicTangentKernel>(nystroemMethod, htk, (centerTranformedData == 1), data, transformedDataReturnMat, eigvalReturnVector, eigvecReturnMat, returnDim); } @@ -171,7 +171,7 @@ void kernel_pca(char const *kernel, SP_integer centerTranformedData, SP_integer } else { - cout << "wrong kernel input." << endl; + raisePrologDomainExeption(kernel, 1, "The given Kernel is unkown!", "kernel_pca"); } // return the transformedData Matrix diff --git a/src/methods/kernel_pca/kernel_pca.pl b/src/methods/kernel_pca/kernel_pca.pl index da2d6a4..be9bfd7 100644 --- a/src/methods/kernel_pca/kernel_pca.pl +++ b/src/methods/kernel_pca/kernel_pca.pl @@ -1,5 +1,5 @@ -:- module(kernel_pca, [kernel_pca/20]). +:- module(kernel_pca, [kernel_pca/16]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -17,10 +17,17 @@ %% definitions for the connected function +foreign(kernel_pca, c, kernel_pcaI( +string, +integer, +integer, +string, + +float32, +float32, +float32, +float32, + +pointer(float_array), +integer, +integer, + -pointer(float_array), -integer, -integer, + -pointer(float_array), -integer, + -pointer(float_array), -integer, -integer, + -integer)). %% --Input-- %% string kernel "advb","agbadf", %% bool centerTranformedData => (1)true / (0)false, -%% bool useNystoem => (1)true / (0)false, +%% bool useNystroem => (1)true / (0)false, %% string nystroemMethod "kmeans", "ordered", "random", %% float32 degree needed by polynomial, %% float32 offset needed by polynomial, hyptan, @@ -32,18 +39,26 @@ %% mat transformedData, %% vec eigenValues, %% mat eigenVectores, -%% int ""newDimension"" +%% int newDimension %% %% --Description-- %% This program performs Kernel Principal Components Analysis (KPCA) on the specified dataset with the specified kernel. This will transform the data onto the kernel principal components, and optionally reduce the dimensionality by ignoring the kernel principal components with the smallest eigenvalues. %% -foreign(kernel_pca, c, kernel_pca( +string, +integer, +integer, +string, - +float32, +float32, +float32, +float32, - +pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, -integer, - -pointer(float_array), -integer, - -pointer(float_array), -integer, -integer, - -integer)). +kernel_pca(Kernel, CenterTransformedData, UseNystroem, NystroemMethod, Degree, Offset, Bandwidth, Scale, DataList, DataRows, + TransformedList, TDataCols, + EigValList, + EigVecList, EigVecCols, + NewDimension) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + kernel_pcaI(Kernel, CenterTransformedData, UseNystroem, NystroemMethod, Degree, Offset, Bandwidth, Scale, + X, Xsize, Xrownum, + TData, TDataCols, TDataRows, + EigVal, EigValsize, + EigVec, EigVecCols, EigVecRows, + NewDimension), + convert_float_array_to_2d_list(TData, TDataCols, TDataRows, TransformedList), + convert_float_array_to_list(EigVal, EigValsize, EigValList), + convert_float_array_to_2d_list(EigVec, EigVecCols, EigVecRows, EigVecList). %% Defines the functions that get connected from main.cpp diff --git a/src/methods/kernel_pca/kernel_pca_test.pl b/src/methods/kernel_pca/kernel_pca_test.pl index 928e67e..92735f9 100644 --- a/src/methods/kernel_pca/kernel_pca_test.pl +++ b/src/methods/kernel_pca/kernel_pca_test.pl @@ -1,3 +1,6 @@ + +:- module(kernel_pca_tests, [run_kernel_pca_tests/0]). + :- use_module(library(plunit)). :- use_module(kernel_pca). @@ -6,51 +9,36 @@ 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 +%% +%% TESTING predicate kernel_pca/16 +%% +:- begin_tests(kernel_pca). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(kernel_pca). + +run_kernel_pca_tests :- + run_tests. + diff --git a/src/methods/kfn/kfn.cpp b/src/methods/kfn/kfn.cpp index 3fb1f7c..3793829 100644 --- a/src/methods/kfn/kfn.cpp +++ b/src/methods/kfn/kfn.cpp @@ -18,7 +18,7 @@ using namespace mlpack::neighbor; // Global Variable of the NSModel object so it can be accessed from all functions NSModel<FurthestNS> nsModelObj; -// TODO: + // input: TreeTypes treeType = TreeTypes::KD_TREE, // bool randomBasis = false, // util::Timers & timers, @@ -27,6 +27,8 @@ NSModel<FurthestNS> nsModelObj; // const double epsilon = 0 // output: // description: +// Initialize the Model and build it. +// void initAndBuildModel(char const *treeType, char const *algorithm, SP_integer randomBasis, SP_integer leafSize, double epsilon, float *referenceMatArr, SP_integer referenceMatSize, SP_integer referenceMatRowNum) @@ -68,7 +70,7 @@ void initAndBuildModel(char const *treeType, char const *algorithm, else if (strcmp(treeType, "oct") == 0) tree = NSModel<FurthestNS>::OCTREE; else - cout << "wrong treeType input" << endl; + raisePrologDomainExeption(treeType, 1, "The given TreeType is unknown!", "initAndBuildModel"); // select the searchMode @@ -83,7 +85,7 @@ void initAndBuildModel(char const *treeType, char const *algorithm, else if (strcmp(algorithm, "greedy") == 0) searchMode = GREEDY_SINGLE_TREE_MODE; else - cout << "wrong algorithm input" << endl; + raisePrologDomainExeption(algorithm, 2, "The given SearchMode is unknown!", "initAndBuildModel"); nsModelObj.TreeType() = tree; @@ -93,7 +95,7 @@ void initAndBuildModel(char const *treeType, char const *algorithm, nsModelObj.BuildModel(std::move(reference), size_t(leafSize), searchMode, epsilon); } -// TODO: + // input: util::Timers & timers, // arma::mat && querySet, // const size_t k, @@ -101,6 +103,8 @@ void initAndBuildModel(char const *treeType, char const *algorithm, // arma::mat & distances <- // output: // description: +// Perform neighbor search on the queryset. +// void searchWithQuery( float *queryMatArr, SP_integer queryMatSize, SP_integer queryMatRowNum, SP_integer k, float **neighborsMatArr, SP_integer *neighborsMatColNum, SP_integer *neighborsMatRowNum, @@ -113,24 +117,30 @@ void searchWithQuery( float *queryMatArr, SP_integer queryMatSize, SP_integer Mat< size_t > neighborsReturnMat; mat distancesReturnMat; + try + { + nsModelObj.Search(move(query), (size_t)k, neighborsReturnMat, distancesReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } - nsModelObj.Search(move(query), (size_t)k, neighborsReturnMat, distancesReturnMat); - - // return the Matrix + // return the Matrices returnMatrixInformation(neighborsReturnMat, neighborsMatArr, neighborsMatColNum, neighborsMatRowNum); - - // return the Matrix returnMatrixInformation(distancesReturnMat, distancesMatArr, distancesMatColNum, distancesMatRowNum); } -// TODO: + // input: util::Timers & timers, // const size_t k, // arma::Mat< size_t > & neighbors <-, // arma::mat & distances <- // output: // description: +// Perform monochromatic neighbor search. +// void searchNoQuery( SP_integer k, float **neighborsMatArr, SP_integer *neighborsMatColNum, SP_integer *neighborsMatRowNum, float **distancesMatArr, SP_integer *distancesMatColNum, SP_integer *distancesMatRowNum) @@ -139,8 +149,14 @@ void searchNoQuery( SP_integer k, Mat< size_t > neighborsReturnMat; mat distancesReturnMat; - - nsModelObj.Search((size_t)k, neighborsReturnMat, distancesReturnMat); + try + { + nsModelObj.Search((size_t)k, neighborsReturnMat, distancesReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } // return the Matrices diff --git a/src/methods/kfn/kfn.pl b/src/methods/kfn/kfn.pl index a90d5f7..aeeafa1 100644 --- a/src/methods/kfn/kfn.pl +++ b/src/methods/kfn/kfn.pl @@ -1,7 +1,7 @@ -:- module(kfn, [ initAndBuildModel/8, - searchWithQuery/10, - searchNoQuery/7]). +:- module(kfn, [ initAndBuildModel/7, + searchWithQuery/7, + searchNoQuery/5]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -19,6 +19,9 @@ %% definitions for the connected function +foreign(initAndBuildModel, c, initAndBuildModelI(+string, +string, + +integer, +integer, +float32, + +pointer(float_array), +integer, +integer)). %% --Input-- %% string treeType => "kd", "vp", "rp", "max-rp", "ub", "cover", "r", "r-star", "x", "ball", "hilbert-r", "r-plus", "r-plus-plus", "spill", "oct", %% string searchMode => "naive", "single_tree", "dual_tree", "greedy", @@ -32,11 +35,15 @@ %% --Description-- %% Initialize the Model and build it. %% -foreign(initAndBuildModel, c, initAndBuildModel(+string, +string, - +integer, +integer, +float32, - +pointer(float_array), +integer, +integer)). +initAndBuildModel(TreeType, SearchMode, RandomBasis, LeafSize, Epsilon, ReferenceList, ReferenceRows) :- + convert_list_to_float_array(ReferenceList, ReferenceRows, array(Xsize, Xrownum, X)), + initAndBuildModelI(TreeType, SearchMode, RandomBasis, LeafSize, Epsilon, X, Xsize, Xrownum). +foreign(searchWithQuery, c, searchWithQueryI( +pointer(float_array), +integer, +integer, + +integer, + -pointer(float_array), -integer, -integer, + -pointer(float_array), -integer, -integer)). %% --Input-- %% mat querySet, %% int k @@ -48,12 +55,16 @@ foreign(initAndBuildModel, c, initAndBuildModel(+string, +string, %% --Description-- %% Perform neighbor search on the queryset. %% -foreign(searchWithQuery, c, searchWithQuery( +pointer(float_array), +integer, +integer, - +integer, - -pointer(float_array), -integer, -integer, - -pointer(float_array), -integer, -integer)). +searchWithQuery(QueryList, QueryRows, K, NeighborsList, YCols, DistancesList, ZCols) :- + convert_list_to_float_array(QueryList, QueryRows, array(Xsize, Xrownum, X)), + searchWithQueryI(X, Xsize, Xrownum, K, Y, YCols, YRows, Z, ZCols, ZRows), + convert_float_array_to_2d_list(Y, YCols, YRows, NeighborsList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, DistancesList). +foreign(searchNoQuery, c, searchNoQueryI( +integer, + -pointer(float_array), -integer, -integer, + -pointer(float_array), -integer, -integer)). %% --Input-- %% int k %% @@ -64,9 +75,10 @@ foreign(searchWithQuery, c, searchWithQuery( +pointer(float_array), +integer, %% --Description-- %% Perform monochromatic neighbor search. %% -foreign(searchNoQuery, c, searchNoQuery( +integer, - -pointer(float_array), -integer, -integer, - -pointer(float_array), -integer, -integer)). +searchNoQuery(K, NeighborsList, YCols, DistancesList, ZCols) :- + searchNoQueryI(K, Y, YCols, YRows, Z, ZCols, ZRows), + convert_float_array_to_2d_list(Y, YCols, YRows, NeighborsList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, DistancesList). %% Defines the functions that get connected from kfn.cpp diff --git a/src/methods/kfn/kfn_test.pl b/src/methods/kfn/kfn_test.pl index 398b699..01dc66f 100644 --- a/src/methods/kfn/kfn_test.pl +++ b/src/methods/kfn/kfn_test.pl @@ -1,3 +1,6 @@ + +:- module(kfn_tests, [run_kfn_tests/0]). + :- use_module(library(plunit)). :- use_module(kfn). @@ -6,51 +9,98 @@ 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 +%% +%% TESTING predicate initAndBuildModel/7 +%% +:- begin_tests(initAndBuildModel). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(initAndBuildModel). + + +%% +%% TESTING predicate searchWithQuery/7 +%% +:- begin_tests(searchWithQuery). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(searchWithQuery). + + +%% +%% TESTING predicate searchNoQuery/5 +%% +:- begin_tests(searchNoQuery). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(searchNoQuery). + +run_kfn_tests :- + run_tests. + diff --git a/src/methods/kmeans/kmeans_test.pl b/src/methods/kmeans/kmeans_test.pl index adb3bfe..97e212c 100644 --- a/src/methods/kmeans/kmeans_test.pl +++ b/src/methods/kmeans/kmeans_test.pl @@ -1,60 +1,42 @@ + +:- module(kmeans_tests, [run_kmeans_tests/0]). + :- use_module(library(plunit)). :- use_module(kmeans). :- use_module('../../helper_files/helper.pl'). -:- begin_tests(lists). - -%% tests -test(naiveKMeans) :- - 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, 1.4, 3.0, 2.1, 0.1],4, array(Xsize, Xrownum, X)), - naiveKMeans(20, 0, 1, X, Xsize, Xrownum, 3, Y, Ysize, Centroids, Centroidscolnum, Centroidsrownum), - print(Ysize), - convert_float_array_to_list(Y, Ysize, ResultsY), - print(ResultsY), - print(Centroidscolnum), - convert_float_array_to_2d_list(Centroids, Centroidscolnum, Centroidsrownum, Results), - print(Results). - -test(dualTreeKMeans) :- - 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, 1.4, 3.0, 2.1, 0.1],4, array(Xsize, Xrownum, X)), - dualTreeKMeans(20, 0, 1, X, Xsize, Xrownum, 3, Y, Ysize, Centroids, Centroidscolnum, Centroidsrownum), - print(Ysize), - convert_float_array_to_list(Y, Ysize, ResultsY), - print(ResultsY), - print(Centroidscolnum), - convert_float_array_to_2d_list(Centroids, Centroidscolnum, Centroidsrownum, Results), - print(Results). - -test(elkanKMeans) :- - 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, 1.4, 3.0, 2.1, 0.1],4, array(Xsize, Xrownum, X)), - elkanKMeans(20, 0, 1, X, Xsize, Xrownum, 3, Y, Ysize, Centroids, Centroidscolnum, Centroidsrownum), - print(Ysize), - convert_float_array_to_list(Y, Ysize, ResultsY), - print(ResultsY), - print(Centroidscolnum), - convert_float_array_to_2d_list(Centroids, Centroidscolnum, Centroidsrownum, Results), - print(Results). - -test(hamerlyKMeans) :- - 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, 1.4, 3.0, 2.1, 0.1],4, array(Xsize, Xrownum, X)), - hamerlyKMeans(20, 0, 1, X, Xsize, Xrownum, 3, Y, Ysize, Centroids, Centroidscolnum, Centroidsrownum), - print(Ysize), - convert_float_array_to_list(Y, Ysize, ResultsY), - print(ResultsY), - print(Centroidscolnum), - convert_float_array_to_2d_list(Centroids, Centroidscolnum, Centroidsrownum, Results), - print(Results). - -test(pellegMooreKMeans) :- - 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, 1.4, 3.0, 2.1, 0.1],4, array(Xsize, Xrownum, X)), - pellegMooreKMeans(20, 0, 0, X, Xsize, Xrownum, 3, Y, Ysize, Centroids, Centroidscolnum, Centroidsrownum), - print(Ysize), - convert_float_array_to_list(Y, Ysize, ResultsY), - print(ResultsY), - print(Centroidscolnum), - convert_float_array_to_2d_list(Centroids, Centroidscolnum, Centroidsrownum, Results), - print(Results). - -:- end_tests(lists). \ No newline at end of file +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_kmeans_tests :- + run_tests. + diff --git a/src/methods/knn/knn.cpp b/src/methods/knn/knn.cpp index 7c14966..f7d4451 100644 --- a/src/methods/knn/knn.cpp +++ b/src/methods/knn/knn.cpp @@ -18,7 +18,7 @@ using namespace mlpack::neighbor; // Global Variable of the NSModel object so it can be accessed from all functions NSModel<NearestNS> nsModelObj; -// TODO: + // input: TreeTypes treeType = TreeTypes::KD_TREE, // bool randomBasis = false, // util::Timers & timers, @@ -29,6 +29,8 @@ NSModel<NearestNS> nsModelObj; // const double rho = 0 // output: // description: +// Initialize the Model and build it. +// void initAndBuildModel(char const *treeType, char const *algorithm, SP_integer randomBasis, SP_integer leafSize, double tau, double rho, double epsilon, float *referenceMatArr, SP_integer referenceMatSize, SP_integer referenceMatRowNum) @@ -70,7 +72,7 @@ void initAndBuildModel(char const *treeType, char const *algorithm, else if (strcmp(treeType, "oct") == 0) tree = NSModel<NearestNS>::OCTREE; else - cout << "wrong treeType input" << endl; + raisePrologDomainExeption(treeType, 1, "The given TreeType is unknown!", "initAndBuildModel"); // select the searchMode @@ -85,7 +87,7 @@ void initAndBuildModel(char const *treeType, char const *algorithm, else if (strcmp(algorithm, "greedy") == 0) searchMode = GREEDY_SINGLE_TREE_MODE; else - cout << "wrong algorithm input" << endl; + raisePrologDomainExeption(algorithm, 2, "The given SearchMode is unknown!", "initAndBuildModel"); nsModelObj.TreeType() = tree; @@ -98,7 +100,7 @@ void initAndBuildModel(char const *treeType, char const *algorithm, nsModelObj.BuildModel(std::move(reference), size_t(leafSize), searchMode, epsilon); } -// TODO: + // input: util::Timers & timers, // arma::mat && querySet, // const size_t k, @@ -106,6 +108,8 @@ void initAndBuildModel(char const *treeType, char const *algorithm, // arma::mat & distances <- // output: // description: +// Perform neighbor search on the queryset. +// void searchWithQuery( float *queryMatArr, SP_integer queryMatSize, SP_integer queryMatRowNum, SP_integer k, float **neighborsMatArr, SP_integer *neighborsMatColNum, SP_integer *neighborsMatRowNum, @@ -119,7 +123,14 @@ void searchWithQuery( float *queryMatArr, SP_integer queryMatSize, SP_integer mat distancesReturnMat; - nsModelObj.Search(move(query), (size_t)k, neighborsReturnMat, distancesReturnMat); + try + { + nsModelObj.Search(move(query), (size_t)k, neighborsReturnMat, distancesReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } // return the Matrices @@ -127,13 +138,15 @@ void searchWithQuery( float *queryMatArr, SP_integer queryMatSize, SP_integer returnMatrixInformation(distancesReturnMat, distancesMatArr, distancesMatColNum, distancesMatRowNum); } -// TODO: + // input: util::Timers & timers, // const size_t k, // arma::Mat< size_t > & neighbors <-, // arma::mat & distances <- // output: // description: +// Perform monochromatic neighbor search. +// void searchNoQuery( SP_integer k, float **neighborsMatArr, SP_integer *neighborsMatColNum, SP_integer *neighborsMatRowNum, float **distancesMatArr, SP_integer *distancesMatColNum, SP_integer *distancesMatRowNum) @@ -143,12 +156,17 @@ void searchNoQuery( SP_integer k, mat distancesReturnMat; - nsModelObj.Search((size_t)k, neighborsReturnMat, distancesReturnMat); + try + { + nsModelObj.Search((size_t)k, neighborsReturnMat, distancesReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } - // return the Matrix + // return the Matrices returnMatrixInformation(neighborsReturnMat, neighborsMatArr, neighborsMatColNum, neighborsMatRowNum); - - // return the Matrix returnMatrixInformation(distancesReturnMat, distancesMatArr, distancesMatColNum, distancesMatRowNum); } \ No newline at end of file diff --git a/src/methods/knn/knn.pl b/src/methods/knn/knn.pl index a4c9881..ee1144d 100644 --- a/src/methods/knn/knn.pl +++ b/src/methods/knn/knn.pl @@ -1,7 +1,7 @@ -:- module(knn, [ initAndBuildModel/10, - searchWithQuery/10, - searchNoQuery/7]). +:- module(knn, [ initAndBuildModel/9, + searchWithQuery/7, + searchNoQuery/5]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -34,7 +34,11 @@ %% --Description-- %% Initialize the Model and build it. %% -foreign(initAndBuildModel, c, initAndBuildModel(+string, +string, +initAndBuildModel(TreeType, SearchMode, RandomBasis, LeafSize, Tau, Rho, Epsilon, ReferenceList, ReferenceRows) :- + convert_list_to_float_array(ReferenceList, ReferenceRows, array(Xsize, Xrownum, X)), + initAndBuildModelI(TreeType, SearchMode, RandomBasis, LeafSize, Tau, Rho, Epsilon, X, Xsize, Xrownum). + +foreign(initAndBuildModel, c, initAndBuildModelI(+string, +string, +integer, +integer, +float32, +float32, +float32, +pointer(float_array), +integer, +integer)). @@ -51,7 +55,13 @@ foreign(initAndBuildModel, c, initAndBuildModel(+string, +string, %% --Description-- %% Perform neighbor search on the queryset. %% -foreign(searchWithQuery, c, searchWithQuery( +pointer(float_array), +integer, +integer, +searchWithQuery(QueryList, QueryRows, K, NeighborsList, YCols, DistancesList, ZCols) :- + convert_list_to_float_array(QueryList, QueryRows, array(Xsize, Xrownum, X)), + searchWithQueryI(X, Xsize, Xrownum, K, Y, YCols, YRows, Z, ZCols, ZRows), + convert_float_array_to_2d_list(Y, YCols, YRows, NeighborsList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, DistancesList). + +foreign(searchWithQuery, c, searchWithQueryI( +pointer(float_array), +integer, +integer, +integer, -pointer(float_array), -integer, -integer, -pointer(float_array), -integer, -integer)). @@ -67,7 +77,12 @@ foreign(searchWithQuery, c, searchWithQuery( +pointer(float_array), +integer, %% --Description-- %% Perform monochromatic neighbor search. %% -foreign(searchNoQuery, c, searchNoQuery( +integer, +searchNoQuery(K, NeighborsList, YCols, DistancesList, ZCols) :- + searchNoQueryI(K, Y, YCols, YRows, Z, ZCols, ZRows), + convert_float_array_to_2d_list(Y, YCols, YRows, NeighborsList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, DistancesList). + +foreign(searchNoQuery, c, searchNoQueryI( +integer, -pointer(float_array), -integer, -integer, -pointer(float_array), -integer, -integer)). diff --git a/src/methods/knn/knn_test.pl b/src/methods/knn/knn_test.pl index 9fc0d7b..7423a31 100644 --- a/src/methods/knn/knn_test.pl +++ b/src/methods/knn/knn_test.pl @@ -1,3 +1,6 @@ + +:- module(knn_tests, [run_knn_tests/0]). + :- use_module(library(plunit)). :- use_module(knn). @@ -6,51 +9,37 @@ 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 +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_knn_tests :- + run_tests. + + \ No newline at end of file diff --git a/src/methods/lars/lars.cpp b/src/methods/lars/lars.cpp index 134e108..1528da2 100644 --- a/src/methods/lars/lars.cpp +++ b/src/methods/lars/lars.cpp @@ -18,55 +18,90 @@ using namespace mlpack::regression; // Global Variable of the Lars regressor object so it can be accessed from all functions LARS regressor; -// input: const bool useCholesky, const double lambda1, const double lambda2, const double tolerance +// input: const bool useCholesky, +// const double lambda1, +// const double lambda2, +// const double tolerance // output: -void initModelNoDataNoGram(SP_integer useCholesky, double lambda1, double lambda2, double tol) +void initModelNoDataNoGram(SP_integer useCholesky, + double lambda1, double lambda2, double tol) { regressor = new LARS((useCholesky == 1), lambda1, lambda2, tol); } -// input: const bool useCholesky, const arma::mat & gramMatrix, const double lambda1, const double lambda2, const double tolerance +// input: const bool useCholesky, +// const arma::mat & gramMatrix, +// const double lambda1, +// const double lambda2, +// const double tolerance // output: -void initModelNoDataWithGram(SP_integer useCholesky, float *gramArr, SP_integer gramSize, SP_integer gramRowNum, double lambda1, double lambda2, double tol) +void initModelNoDataWithGram(SP_integer useCholesky, + float *gramArr, SP_integer gramSize, SP_integer gramRowNum, + double lambda1, double lambda2, double tol) { mat gramMatrix = convertArrayToMat(gramArr, gramSize, gramRowNum); regressor = new LARS((useCholesky == 1), gramMatrix, lambda1, lambda2, tol); } -// input: const arma::mat & dataMatrix, const arma::rowvec & responses, const bool transposeData, const bool useCholesky, const double lambda1, const double lambda2, const double tolerance +// input: const arma::mat & dataMatrix, +// const arma::rowvec & responses, +// const bool transposeData, +// const bool useCholesky, +// const double lambda1, +// const double lambda2, +// const double tolerance // output: -void initModelWithDataNoGram(float *dataArr, SP_integer dataSize, SP_integer dataRowNum, float *responsesArr, SP_integer responsesSize, SP_integer transposeData, - SP_integer useCholesky, double lambda1, double lambda2, double tol) +void initModelWithDataNoGram(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float *responsesArr, SP_integer responsesArrSize, + SP_integer transposeData, + SP_integer useCholesky, + double lambda1, double lambda2, double tol) { - if(dataSize / dataRowNum != responsesSize) + if(dataMatSize / dataMatRowNum != responsesArrSize) { cout << "Target dim doesnt fit to the Data dim" << endl; return; } - // convert the Prolog arrays to arma::rowvec and arma::mat - mat data = convertArrayToMat(dataArr, dataSize, dataRowNum); - rowvec responses = convertArrayToRowvec(responsesArr, responsesSize); + // convert the Prolog array to arma::mat + mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); + // convert the Prolog array to arma::rowvec + rowvec responsesVector = convertArrayToRowvec(responsesArr, responsesArrSize); - regressor = new LARS(data, responses, (transposeData == 1), (useCholesky == 1), lambda1, lambda2, tol); + + regressor = new LARS(data, responsesVector, (transposeData == 1), (useCholesky == 1), lambda1, lambda2, tol); } -// input: const arma::mat & dataMatrix, const arma::rowvec & responses, const bool transposeData, const bool useCholesky, const arma::mat & gramMatrix, const double lambda1, const double lambda2, const double tolerance +// input: const arma::mat & dataMatrix, +// const arma::rowvec & responses, +// const bool transposeData, +// const bool useCholesky, +// const arma::mat & gramMatrix, +// const double lambda1, +// const double lambda2, +// const double tolerance // output: -void initModelWithDataWithGram(float *dataArr, SP_integer dataSize, SP_integer dataRowNum, float *responsesArr, SP_integer responsesSize, SP_integer transposeData, - SP_integer useCholesky, float *gramArr, SP_integer gramSize, SP_integer gramRowNum, double lambda1, double lambda2, double tol) +void initModelWithDataWithGram(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float *responsesArr, SP_integer responsesArrSize, + SP_integer transposeData, + SP_integer useCholesky, + float *gramMatArr, SP_integer gramMatSize, SP_integer gramMatRowNum, + double lambda1, double lambda2, double tol) { - if(dataSize / dataRowNum != responsesSize) + if(dataMatSize / dataMatRowNum != responsesArrSize) { cout << "Target dim doesnt fit to the Data dim" << endl; return; } - // convert the Prolog arrays to arma::rowvec and arma::mat - mat data = convertArrayToMat(dataArr, dataSize, dataRowNum); - rowvec responses = convertArrayToRowvec(responsesArr, responsesSize); - mat gramMatrix = convertArrayToMat(gramArr, gramSize, gramRowNum); + // convert the Prolog array to arma::mat + mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); + // convert the Prolog array to arma::rowvec + rowvec responsesVector = convertArrayToRowvec(responsesArr, responsesArrSize); + // convert the Prolog array to arma::mat + mat gram = convertArrayToMat(gramMatArr, gramMatSize, gramMatRowNum); + - regressor = new LARS(data, responses, (transposeData == 1), (useCholesky == 1), gramMatrix, lambda1, lambda2, tol); + regressor = new LARS(data, responsesVector, (transposeData == 1), (useCholesky == 1), gram, lambda1, lambda2, tol); } // input: @@ -83,14 +118,13 @@ void activeSet(float **activeSetArr, SP_integer *activeSetSize) // input: // output: arma::vec& -void beta( float **betaArr, SP_integer *betaSize) +void beta(float **betaArr, SP_integer *betaArrSize) { - rowvec betasolution = regressor.Beta(); - - // give back the sizes and the converted results as arrays - *betaSize = betasolution.n_elem; + // create the ReturnVector + rowvec betaReturnVector = regressor.Beta(); - *betaArr = convertToArray(betasolution); + // return the Vector + returnVectorInformation(betaReturnVector, betaArr, betaArrSize); } // input: @@ -108,21 +142,26 @@ void betaPath(float **betaPathArr, SP_integer *betaPathColNum, SP_integer *betaP *betaPathArr = convertToArray(matrix); } -// input: const arma::mat &data, const arma::rowvec &responses, const bool rowMajor -// output: double minimum cost error -SP_integer computeError(float *points_mat_arr, SP_integer dataSize, SP_integer dataRowNum, float *responses_arr, SP_integer responsesSize, SP_integer rowMajor) +// input: const arma::mat &data, +// const arma::rowvec &responses, +// const bool rowMajor +// +// output: double minimum cost error +double computeError(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float *responsesArr, SP_integer responsesArrSize, SP_integer rowMajor) { - if(dataSize / dataRowNum != responsesSize) + if(dataMatSize / dataMatRowNum != responsesArrSize) { cout << "Target dim doesnt fit to the Data dim" << endl; - return 0; + return; } - // convert the Prolog arrays to arma::rowvec and arma::mat - mat data = convertArrayToMat(points_mat_arr, dataSize, dataRowNum); - rowvec responses = convertArrayToRowvec(responses_arr, responsesSize); + // convert the Prolog array to arma::mat + mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); + // convert the Prolog array to arma::rowvec + rowvec responsesVector = convertArrayToRowvec(responsesArr, responsesArrSize); // run the model function - return regressor.ComputeError(data, responses); + return regressor.ComputeError(data, responsesVector, (rowMajor == 1)); } // input: @@ -140,52 +179,64 @@ void lambdaPath(float **lambdaPathArr, SP_integer *lambdaPathSize) // input: // output: arma::mat& upper triangular cholesky factor -void matUtriCholFactor(float **factorArr, SP_integer *factorColNum, SP_integer *factorRowNum) +void matUtriCholFactor(float **factorMatArr, SP_integer *factorMatColNum, SP_integer *factorMatRowNum) { - // get the UtriCholFactor matrix - mat UtriCholFact = regressor.MatUtriCholFactor(); - - // return the matrix dimensions - *factorColNum = UtriCholFact.n_cols; - *factorRowNum = UtriCholFact.n_rows; - - // return the matrix as array - *factorArr = convertToArray(UtriCholFact); + // create the ReturnMat + mat factorReturnMat = regressor.MatUtriCholFactor(); + + // return the Matrix + returnMatrixInformation(factorReturnMat, factorMatArr, factorMatColNum, factorMatRowNum); } -// input: const arma::mat &points, arma::rowvec &predictions, const bool rowMajor +// input: const arma::mat &points, +// arma::rowvec &predictions <-, +// const bool rowMajor // output: -void predict(float *pointsArr, SP_integer pointsSize, SP_integer pointsRowNum, float **predicArr, SP_integer *predicSize, SP_integer rowMajor) +void predict(float *pointsMatArr, SP_integer pointsMatSize, SP_integer pointsMatRowNum, float **predicArr, SP_integer *predicArrSize, SP_integer rowMajor) { - // convert the array to arma::mat - mat data = convertArrayToMat(pointsArr, pointsSize, pointsRowNum); - - // run the prediction and save the result in arma::rowvec - rowvec predictions; - regressor.Predict(data, predictions, (rowMajor == 1)); - + // convert the Prolog array to arma::mat + mat points = convertArrayToMat(pointsMatArr, pointsMatSize, pointsMatRowNum); + // create the ReturnVector + rowvec predicReturnVector; + + + regressor.Predict(points, predicReturnVector, (rowMajor == 1)); - // give back the sizes and the converted results as arrays - *predicSize = predictions.n_elem; - *predicArr = convertToArray(predictions); + // return the Vector + returnVectorInformation(predicReturnVector, predicArr, predicArrSize); } -// input: const arma::mat &data, const arma::rowvec &responses, arma::vec& beta, const bool transposeData +// input: const arma::mat &data, +// const arma::rowvec &responses, +// arma::vec& beta, +// const bool transposeData +// // output: double minimum cost error -SP_integer train(float *dataArr, SP_integer dataSize, SP_integer dataRowNum, float *responsesArr, SP_integer responsesSize, float **betaArr, SP_integer *betaSize, SP_integer transposeData) +double train(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float *responsesArr, SP_integer responsesArrSize, + float **betaArr, SP_integer *betaArrSize, + SP_integer transposeData) { - if(dataSize / dataRowNum != responsesSize) + if(dataMatSize / dataMatRowNum != responsesArrSize) { cout << "Target dim doesnt fit to the Data dim" << endl; - return 0; + return; } - // convert the Prolog arrays to arma::rowvec and arma::mat - mat data = convertArrayToMat(dataArr, dataSize, dataRowNum); - rowvec responses = convertArrayToRowvec(responsesArr, responsesSize); + // convert the Prolog array to arma::mat + mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); + // convert the Prolog array to arma::rowvec + rowvec responsesVector = convertArrayToRowvec(responsesArr, responsesArrSize); - vec betaVec; + // create the ReturnVector + vec betaReturnVector; + // run the model function - return regressor.Train(data, responses, betaVec, (transposeData == 1)); + double error = regressor.Train(data, responsesVector, betaReturnVector, (transposeData == 1)); + + + // return the Vector + returnVectorInformation(betaReturnVector, betaArr, betaArrSize); + return error; } \ No newline at end of file diff --git a/src/methods/lars/lars.pl b/src/methods/lars/lars.pl index 41e573c..a7449f5 100644 --- a/src/methods/lars/lars.pl +++ b/src/methods/lars/lars.pl @@ -1,16 +1,16 @@ :- module(lars, [ initModelNoDataNoGram/4, - initModelNoDataWithGram/7, - initModelWithDataNoGram/10, - initModelWithDataWithGram/13, - activeSet/2, - beta/2, - betaPath/3, - computeError/7, - lambdaPath/2, - matUtriCholFactor/3, - predict/6, - train/9]). + initModelNoDataWithGram/6, + initModelWithDataNoGram/8, + initModelWithDataWithGram/10, + activeSet/1, + beta/1, + betaPath/2, + computeError/5, + lambdaPath/1, + matUtriCholFactor/2, + predict/4, + train/6]). :- load_files(library(str_decl), [when(compile_time), if(changed)]). @@ -38,10 +38,14 @@ %% --Description-- %% Only initialize the LARS model. %% -foreign(initModelNoDataNoGram, c, initModelNoDataNoGram(+integer, +initModelNoDataNoGram(UseCholesky, Lambda1, Lambda2, Tolerance) :- + initModelNoDataNoGramI(UseCholesky, Lambda1, Lambda2, Tolerance). + +foreign(initModelNoDataNoGram, c, initModelNoDataNoGramI(+integer, +float32, +float32, +float32)). + %% --Input-- %% bool useCholesky => (1)true / (0)false =>false, %% mat gramMatrix, @@ -54,7 +58,11 @@ foreign(initModelNoDataNoGram, c, initModelNoDataNoGram(+integer, %% --Description-- %% Initialize LARS model, and pass in a precalculated Gram matrix but dont train the model. %% -foreign(initModelNoDataWithGram, c, initModelNoDataWithGram( +integer, +initModelNoDataWithGram(UseCholesky, GramList, GramRows, Lambda1, Lambda2, Tolerance) :- + convert_list_to_float_array(GramList, GramRows, array(Zsize, Zrownum, Z)), + initModelNoDataWithGramI(UseCholesky, Z, Zsize, Zrownum, Lambda1, Lambda2, Tolerance). + +foreign(initModelNoDataWithGram, c, initModelNoDataWithGramI( +integer, +pointer(float_array), +integer, +integer, +float32, +float32, +float32)). @@ -73,13 +81,19 @@ foreign(initModelNoDataWithGram, c, initModelNoDataWithGram( +integer, %% --Description-- %% Initialize LARS model, and train the model. %% -foreign(initModelWithDataNoGram, c, initModelWithDataNoGram( +pointer(float_array), +integer, +integer, +initModelWithDataNoGram(DataList, DataRows, ResponsesList, TransposeData, UseCholesky, Lambda1, Lambda2, Tolerance) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + initModelWithDataNoGramI(X, Xsize, Xrownum, Y, Ysize, TransposeData, UseCholesky, Lambda1, Lambda2, Tolerance). + +foreign(initModelWithDataNoGram, c, initModelWithDataNoGramI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +integer, +float32, +float32, +float32)). + %% --Input-- %% mat data, %% vec responses, @@ -95,7 +109,13 @@ foreign(initModelWithDataNoGram, c, initModelWithDataNoGram( +pointer(float_a %% --Description-- %% Initialize LARS model, pass in a precalculated Gram matrix and train the model. %% -foreign(initModelWithDataWithGram, c, initModelWithDataWithGram(+pointer(float_array), +integer, +integer, +initModelWithDataWithGram(DataList, DataRows, ResponsesList, TransposeData, UseCholesky, GramList, GramRows, Lambda1, Lambda2, Tolerance) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + convert_list_to_float_array(GramList, GramRows, array(Zsize, Zrownum, Z)), + initModelWithDataWithGramI(X, Xsize, Xrownum, Y, Ysize, TransposeData, UseCholesky, Z, Zsize, Zrownum, Lambda1, Lambda2, Tolerance). + +foreign(initModelWithDataWithGram, c, initModelWithDataWithGramI(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +integer, @@ -103,6 +123,7 @@ foreign(initModelWithDataWithGram, c, initModelWithDataWithGram(+pointer(float_a +float32, +float32, +float32)). + %% --Input-- %% %% --Output-- @@ -111,7 +132,11 @@ foreign(initModelWithDataWithGram, c, initModelWithDataWithGram(+pointer(float_a %% --Description-- %% Get the set of active dimensions %% -foreign(activeSet, c, activeSet(-pointer(float_array), -integer)). +activeSet(ActiveSetList) :- + activeSetI(Y, Ysize), + convert_float_array_to_list(Y, Ysize, ActiveSetList). + +foreign(activeSet, c, activeSetI(-pointer(float_array), -integer)). %% --Input-- @@ -122,7 +147,11 @@ foreign(activeSet, c, activeSet(-pointer(float_array), -integer)). %% --Description-- %% Get the solution coefficients. %% -foreign(beta, c, beta(-pointer(float_array), -integer)). +beta(BetaList) :- + betaI(Y, Ysize), + convert_float_array_to_list(Y, Ysize, BetaList). + +foreign(beta, c, betaI(-pointer(float_array), -integer)). %% --Input-- @@ -133,7 +162,11 @@ foreign(beta, c, beta(-pointer(float_array), -integer)). %% --Description-- %% Get the set of coefficients after each iteration. The solution is the last element. %% -foreign(betaPath, c, betaPath(-pointer(float_array), -integer, -integer)). +betaPath(BetaList, XCols) :- + betaPathI(X, XCols, XRows), + convert_float_array_to_2d_list(X, XCols, XRows, BetaList). + +foreign(betaPath, c, betaPathI(-pointer(float_array), -integer, -integer)). %% --Input-- @@ -147,9 +180,15 @@ foreign(betaPath, c, betaPath(-pointer(float_array), -integer, -integer)). %% --Description-- %% Compute cost error of the given data matrix using the currently-trained LARS model.Only ||y-beta*X||2 is used to calculate cost error. %% -foreign(computeError, c, computeError( +pointer(float_array), +integer, +integer, - +pointer(float_array), +integer, +integer, - [-integer])). +computeError(DataList, DataRows, ResponsesList, RowMajor, Error) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + computeErrorI(X, Xsize, Xrownum, Y, Ysize, RowMajor, Error). + +foreign(computeError, c, computeErrorI( +pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +integer, + [-float32])). %% --Input-- @@ -160,7 +199,11 @@ foreign(computeError, c, computeError( +pointer(float_array), +integer, +intege %% --Description-- %% Get the set of values for lambda1 after each iteration; the solution is the last element. %% -foreign(lambdaPath, c, lambdaPath(-pointer(float_array), -integer)). +lambdaPath(LambdaPathList) :- + lambdaPathI(Y, Ysize), + convert_float_array_to_list(Y, Ysize, LambdaPathList). + +foreign(lambdaPath, c, lambdaPathI(-pointer(float_array), -integer)). %% --Input-- @@ -171,7 +214,11 @@ foreign(lambdaPath, c, lambdaPath(-pointer(float_array), -integer)). %% --Description-- %% Get the upper triangular cholesky factor. %% -foreign(matUtriCholFactor, c, matUtriCholFactor(-pointer(float_array), -integer, -integer)). +matUtriCholFactor(FactorList, XCols) :- + matUtriCholFactorI(X, XCols, XRows), + convert_float_array_to_2d_list(X, XCols, XRows, FactorList). + +foreign(matUtriCholFactor, c, matUtriCholFactorI(-pointer(float_array), -integer, -integer)). %% --Input-- @@ -184,7 +231,12 @@ foreign(matUtriCholFactor, c, matUtriCholFactor(-pointer(float_array), -integer, %% --Description-- %% Predict y_i for each data point in the given data matrix using the currently-trained LARS model. %% -foreign(predict, c, predict( +pointer(float_array), +integer, +integer, +predict(PointsList, PointsRows, PredicList, RowMajor) :- + convert_list_to_float_array(PointsList, PointsRows, array(Xsize, Xrownum, X)), + predictI(X, Xsize, Xrownum, Y, Ysize, RowMajor), + convert_float_array_to_list(Y, Ysize, PredicList). + +foreign(predict, c, predictI( +pointer(float_array), +integer, +integer, -pointer(float_array), -integer, +integer)). @@ -201,11 +253,17 @@ foreign(predict, c, predict( +pointer(float_array), +integer, +integer, %% --Description-- %% Train the LARS model with the given data. %% -foreign(train, c, train(+pointer(float_array), +integer, +integer, - +pointer(float_array), +integer, - -pointer(float_array), -integer, - +integer, - [-integer])). +train(DataList, DataRows, ResponsesList, BetaList, RowMajor, Error) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + trainI(X, Xsize, Xrownum, Y, Ysize, Z, Zsize, RowMajor, Error), + convert_float_array_to_list(Z, Zsize, BetaList). + +foreign(train, c, trainI( +pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + -pointer(float_array), -integer, + +integer, + [-float32])). %% Defines what functions should be connected from main.cpp diff --git a/src/methods/lars/lars_test.pl b/src/methods/lars/lars_test.pl index 20dc240..f45ca33 100644 --- a/src/methods/lars/lars_test.pl +++ b/src/methods/lars/lars_test.pl @@ -1,4 +1,8 @@ + +:- module(lars_tests, [run_lars_tests/0]). + :- use_module(library(plunit)). + :- use_module(library(structs)). :- use_module(lars). @@ -44,4 +48,37 @@ test(betaPath) :- print(Results). -:- end_tests(lists). \ No newline at end of file +:- end_tests(lists). + +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_lars_tests :- + run_tests. \ No newline at end of file diff --git a/src/methods/linear_SVM/linear_SVM.cpp b/src/methods/linear_SVM/linear_SVM.cpp index 32db245..ae2994d 100644 --- a/src/methods/linear_SVM/linear_SVM.cpp +++ b/src/methods/linear_SVM/linear_SVM.cpp @@ -19,7 +19,7 @@ using namespace mlpack::svm; // Global Variable of the LinearSVM object so it can be accessed from all functions LinearSVM<> linearSVM; -// TODO: + // input: const MatType & data, // const arma::Row< size_t > & labels, // const size_t numClasses = 2, @@ -29,12 +29,17 @@ LinearSVM<> linearSVM; // OptimizerType optimizer = OptimizerType() // output: // description: -void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, SP_integer numClasses, double lambda, - double delta, SP_integer fitIntercept, char const *optimizer) +// Initializes the linear_svm model with the given data and trains it. +// +void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float *labelsArr, SP_integer labelsArrSize, + SP_integer numClasses, double lambda, double delta, + SP_integer fitIntercept, + char const *optimizer) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec arma::Row<size_t> labels = convertArrayToVec(labelsArr, labelsArrSize); linearSVM = LinearSVM<>(numClasses, lambda, delta, (fitIntercept == 1)); @@ -49,86 +54,113 @@ void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer da } else { - cout << "Wrong optimizer input" << endl; + raisePrologDomainExeption(optimizer, 8, "The given Optimizer is unkown!", "initModelWithTrain"); + return; } } -// TODO: + // input: const size_t numClasses = 0, // const double lambda = 0.0001, // const double delta = 1.0, // const bool fitIntercept = false // output: // description: +// Initializes the linear_svm model with the given data but doesnt train it. +// void initModelNoTrain(SP_integer numClasses, double lambda, double delta, SP_integer fitIntercept) { linearSVM = LinearSVM<>(numClasses, lambda, delta, true); } -// TODO: + // input: const MatType & data, // arma::Row< size_t > & labels, // arma::mat & scores // output: // description: -void classify(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float **labelsArr, SP_integer *labelsArrSize, +// Classify the given points, returning class scores and predicted class label for each point. +// +void classify(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float **labelsArr, SP_integer *labelsArrSize, float **scoresMatArr, SP_integer *scoresMatColNum, SP_integer *scoresMatRowNum) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); // get the ReturnVector arma::Row<size_t> labelsReturnVector; - // get the ReturnMat mat scoresReturnMat; - linearSVM.Classify(data, labelsReturnVector, scoresReturnMat); - - // return the Vector lenght - *labelsArrSize = labelsReturnVector.n_elem; - - // return the Vector as Array - *labelsArr = convertToArray(labelsReturnVector); + try + { + linearSVM.Classify(data, labelsReturnVector, scoresReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } - // return the Matrix dimensions - *scoresMatColNum = scoresReturnMat.n_cols; - *scoresMatRowNum = scoresReturnMat.n_rows; - // return the Matrix as one long Array - *scoresMatArr = convertToArray(scoresReturnMat); + // return the Vector + returnVectorInformation(labelsReturnVector, labelsArr, labelsArrSize); + // return the Matrix + returnMatrixInformation(scoresReturnMat, scoresMatArr, scoresMatColNum, scoresMatRowNum); } -// TODO: + // input: const VecType & point // // output: size_t point label // description: +// Classify the given point. +// SP_integer classifyPoint(float *pointArr, SP_integer pointArrSize) { - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec rowvec pointVector = convertArrayToRowvec(pointArr, pointArrSize); - return linearSVM.Classify<rowvec>(pointVector); + try + { + return linearSVM.Classify<rowvec>(pointVector); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return 0; + } } -// TODO: + // input: const MatType & testData, // const arma::Row< size_t > & testLabels // // output: double accuracy // description: +// Computes accuracy of the learned model given the feature data and the labels associated with each data point. +// double computeAccuracy(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec arma::Row<size_t> labels = convertArrayToVec(labelsArr, labelsArrSize); - return linearSVM.ComputeAccuracy(data, labels); + + try + { + return linearSVM.ComputeAccuracy(data, labels); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return 0.0; + } } -// TODO: + // input: const MatType & data, // const arma::Row< size_t > & labels, // const size_t numClasses = 2, @@ -136,24 +168,34 @@ double computeAccuracy(float *dataMatArr, SP_integer dataMatSize, SP_integer dat // // output: double Object value of final point // description: +// Train the Linear_svm model with the given training data. +// double train(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, SP_integer numClasses, char const *optimizer) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec arma::Row<size_t> labels = convertArrayToVec(labelsArr, labelsArrSize); - if (strcmp(optimizer, "lbfgs") == 0) - { - return linearSVM.Train<ens::L_BFGS>(data, labels, numClasses); - } - else if (strcmp(optimizer, "psgd") == 0) + try { - return linearSVM.Train<ens::ParallelSGD<>>(data, labels, numClasses, ens::ParallelSGD(100, 4)); + if (strcmp(optimizer, "lbfgs") == 0) + { + return linearSVM.Train<ens::L_BFGS>(data, labels, numClasses); + } + else if (strcmp(optimizer, "psgd") == 0) + { + return linearSVM.Train<ens::ParallelSGD<>>(data, labels, numClasses, ens::ParallelSGD(100, 4)); + } + else + { + raisePrologDomainExeption(optimizer, 5, "The given Optimizer is unkown!", "train"); + return 0.0; + } } - else + catch(const std::exception& e) { - cout << "Wrong optimizer input" << endl; - return 0; + raisePrologSystemExeption(e.what()); + return 0.0; } } diff --git a/src/methods/linear_SVM/linear_SVM.pl b/src/methods/linear_SVM/linear_SVM.pl index 9e2d5e0..864abf1 100644 --- a/src/methods/linear_SVM/linear_SVM.pl +++ b/src/methods/linear_SVM/linear_SVM.pl @@ -1,10 +1,10 @@ -:- module(linear_SVM, [ initModelWithTrain/10, +:- module(linear_SVM, [ initModelWithTrain/8, initModelNoTrain/4, - classify/8, - classifyPoint/3, - computeAccuracy/6, - train/8]). + classify/5, + classifyPoint/2, + computeAccuracy/4, + train/6]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -36,7 +36,12 @@ %% --Description-- %% Initializes the linear_svm model with the given data and trains it. %% -foreign(initModelWithTrain, c, initModelWithTrain( +pointer(float_array), +integer, +integer, +initModelWithTrain(DataList, DataRows, LabelsList, NumClasses, Lambda, Delta, FitIntercept, Optimizer) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(LabelsList, array(Ysize, Y)), + initModelWithTrainI(X, Xsize, Xrownum, Y, Ysize, NumClasses, Lambda, Delta, FitIntercept, Optimizer). + +foreign(initModelWithTrain, c, initModelWithTrainI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +float32, +float32, +integer, @@ -54,7 +59,10 @@ foreign(initModelWithTrain, c, initModelWithTrain( +pointer(float_array), + %% --Description-- %% Initializes the linear_svm model with the given data but doesnt train it. %% -foreign(initModelNoTrain, c, initModelNoTrain( +integer, +float32, +float32, +initModelNoTrain(NumClasses, Lambda, Delta, FitIntercept) :- + initModelNoTrainI(NumClasses, Lambda, Delta, FitIntercept). + +foreign(initModelNoTrain, c, initModelNoTrainI( +integer, +float32, +float32, +integer)). @@ -68,7 +76,13 @@ foreign(initModelNoTrain, c, initModelNoTrain( +integer, +float32, +float32, %% --Description-- %% Classify the given points, returning class scores and predicted class label for each point. %% -foreign(classify, c, classify( +pointer(float_array), +integer, +integer, +classify(DataList, DataRows, LabelsList, ScoresList, ZCols) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), + classifyI(X, Xsize, Xrows, Y, Ysize, Z, ZCols, ZRows), + convert_float_array_to_list(Y, Ysize, LabelsList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, ScoresList). + +foreign(classify, c, classifyI( +pointer(float_array), +integer, +integer, -pointer(float_array), -integer, -pointer(float_array), -integer, -integer)). @@ -82,7 +96,11 @@ foreign(classify, c, classify( +pointer(float_array), +integer, +integer, %% --Description-- %% Classify the given point. %% -foreign(classifyPoint, c, classifyPoint(+pointer(float_array), +integer, +classifyPoint(DataList, Prediction) :- + convert_list_to_float_array(DataList, array(Xsize, X)), + classifyPointI(X, Xsize, Prediction). + +foreign(classifyPoint, c, classifyPointI(+pointer(float_array), +integer, [-integer])). @@ -97,7 +115,12 @@ foreign(classifyPoint, c, classifyPoint(+pointer(float_array), +integer, %% Computes accuracy of the learned model given the feature data and the labels associated with each data point. %% Predictions are made using the provided data and are compared with the actual labels. %% -foreign(computeAccuracy, c, computeAccuracy( +pointer(float_array), +integer, +integer, +computeAccuracy(DataList, DataRows, LabelsList, Accuracy) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(LabelsList, array(Ysize, Y)), + computeAccuracyI(X, Xsize, Xrownum, Y, Ysize, Accuracy). + +foreign(computeAccuracy, c, computeAccuracyI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, [-float32])). @@ -114,7 +137,12 @@ foreign(computeAccuracy, c, computeAccuracy( +pointer(float_array), +integer, %% --Description-- %% Train the Linear_svm model with the given training data. %% -foreign(train, c, train(+pointer(float_array), +integer, +integer, +train(DataList, DataRows, LabelsList, NumClasses, Optimizer, ObjValue) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(LabelsList, array(Ysize, Y)), + trainI(X, Xsize, Xrownum, Y, Ysize, NumClasses, Optimizer, ObjValue). + +foreign(train, c, trainI(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +string, diff --git a/src/methods/linear_SVM/linear_SVM_test.pl b/src/methods/linear_SVM/linear_SVM_test.pl index 50cdc1a..055cfd4 100644 --- a/src/methods/linear_SVM/linear_SVM_test.pl +++ b/src/methods/linear_SVM/linear_SVM_test.pl @@ -1,3 +1,6 @@ + +:- module(linear_SVM_tests, [run_linear_SVM_tests/0]). + :- use_module(library(plunit)). :- use_module(linear_SVM). @@ -16,4 +19,38 @@ test(correct_train) :- convert_list_to_float_array([1,1,0,0], array(Ysize, Y)), train(X,Xsize, Xrownum,Y, Ysize, 2, lbfgs, Result), print(Result). -:- end_tests(lists). \ No newline at end of file +:- end_tests(lists). + +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_linear_SVM_tests :- + run_tests. + diff --git a/src/methods/linear_regression/linear_regression.cpp b/src/methods/linear_regression/linear_regression.cpp index c0c1852..e71c0aa 100644 --- a/src/methods/linear_regression/linear_regression.cpp +++ b/src/methods/linear_regression/linear_regression.cpp @@ -63,7 +63,6 @@ void initModelWithWeights(float *dataMatArr, SP_integer dataMatSize, SP_integer mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); // convert the Prolog array to arma::rowvec rowvec responsesVector = convertArrayToRowvec(responsesArr, responsesArrSize); - // convert the Prolog array to arma::rowvec rowvec weightsVector = convertArrayToRowvec(weightsArr, weightsArrSize); diff --git a/src/methods/linear_regression/linear_regression.pl b/src/methods/linear_regression/linear_regression.pl index 7dbd814..cb85d07 100644 --- a/src/methods/linear_regression/linear_regression.pl +++ b/src/methods/linear_regression/linear_regression.pl @@ -1,12 +1,12 @@ -:- module(linear_regression, [ initModel/7, - initModelWithWeights/9, - computeError/6, - parameters/2, - modifyParameters/2, - predict/5, - train/7, - trainWithWeights/9]). +:- module(linear_regression, [ initModel/5, + initModelWithWeights/6, + computeError/4, + parameters/1, + modifyParameters/1, + predict/3, + train/5, + trainWithWeights/6]). :- load_files(library(str_decl), [when(compile_time), if(changed)]). @@ -34,7 +34,12 @@ %% --Description-- %% Initializes the linear_regression model and trains it but doesnt include weights. %% -foreign(initModel, c, initModel( +pointer(float_array), +integer, +integer, +initModel(DataList, DataRows, ResponsesList, Lambda, Intercept) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + initModelI(X, Xsize, Xrownum, Y, Ysize, Lambda, Intercept). + +foreign(initModel, c, initModelI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +float32, +integer)). @@ -52,11 +57,17 @@ foreign(initModel, c, initModel( +pointer(float_array), +integer, +intege %% --Description-- %% Initializes the linear_regression model, trains it and adds weights to it. %% -foreign(initModelWithWeights, c, initModelWithWeights( +pointer(float_array), +integer, +integer, - +pointer(float_array), +integer, - +pointer(float_array), +integer, - +float32, - +integer)). +initModelWithWeights(DataList, DataRows, ResponsesList, WeightsList, Lambda, Intercept) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + convert_list_to_float_array(WeightsList, array(Zsize, Z)), + initModelWithWeightsI(X, Xsize, Xrownum, Y, Ysize, Z, Zsize, Lambda, Intercept). + +foreign(initModelWithWeights, c, initModelWithWeightsI( +pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +pointer(float_array), +integer, + +float32, + +integer)). %% --Input-- @@ -69,7 +80,12 @@ foreign(initModelWithWeights, c, initModelWithWeights( +pointer(float_array), + %% --Description-- %% Calculate the L2 squared error on the given predictors and responses using this linear regression model. %% -foreign(computeError, c, computeError( +pointer(float_array), +integer, +integer, +computeError(DataList, DataRows, ResponsesList, Error) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + computeErrorI(X, Xsize, Xrownum, Y, Ysize, Error). + +foreign(computeError, c, computeErrorI(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, [-float32])). @@ -82,7 +98,11 @@ foreign(computeError, c, computeError( +pointer(float_array), +integer, +intege %% --Description-- %% Get the parameters (the b vector). %% -foreign(parameters, c, parameters(-pointer(float_array), -integer)). +parameters(ParametersList) :- + parametersI(Y, Ysize), + convert_float_array_to_list(Y, Ysize, ParametersList). + +foreign(parameters, c, parametersI(-pointer(float_array), -integer)). %% --Input-- @@ -93,7 +113,11 @@ foreign(parameters, c, parameters(-pointer(float_array), -integer)). %% --Description-- %% Modify the parameters (the b vector). %% -foreign(modifyParameters, c, modifyParameters(+pointer(float_array), +integer)). +modifyParameters(ParameterList) :- + convert_list_to_float_array(ParameterList, array(Ysize, Y)), + modifyParametersI(Y, Ysize). + +foreign(modifyParameters, c, modifyParametersI(+pointer(float_array), +integer)). %% --Input-- @@ -105,7 +129,12 @@ foreign(modifyParameters, c, modifyParameters(+pointer(float_array), +integer)) %% --Description-- %% Calculate y_i for each data point in points. %% -foreign(predict, c, predict( +pointer(float_array), +integer, +integer, +predict(PointsList, PointsRows, PredicList) :- + convert_list_to_float_array(PointsList, PointsRows, array(Xsize, Xrownum, X)), + predictI(X, Xsize, Xrownum, Y, Ysize), + convert_float_array_to_list(Y, Ysize, PredicList). + +foreign(predict, c, predictI( +pointer(float_array), +integer, +integer, -pointer(float_array), -integer)). @@ -122,7 +151,12 @@ foreign(predict, c, predict( +pointer(float_array), +integer, +integer, %% Careful! %% This will completely ignore and overwrite the existing model. This particular implementation does not have an incremental training algorithm. %% -foreign(train, c, train( +pointer(float_array), +integer, +integer, +train(DataList, DataRows, ResponsesList, Intercept, Error) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + trainI(X, Xsize, Xrownum, Y, Ysize, Intercept, Error). + +foreign(train, c, trainI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, [-float32])). @@ -142,7 +176,13 @@ foreign(train, c, train( +pointer(float_array), +integer, +integer, %% Careful! %% This will completely ignore and overwrite the existing model. This particular implementation does not have an incremental training algorithm. %% -foreign(trainWithWeights, c, trainWithWeights( +pointer(float_array), +integer, +integer, +trainWithWeights(DataList, DataRows, ResponsesList, WeightsList, Intercept, Error) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + convert_list_to_float_array(WeightsList, array(Zsize, Z)), + trainWithWeightsI(X, Xsize, Xrownum, Y, Ysize, Z, Zsize, Intercept, Error). + +foreign(trainWithWeights, c, trainWithWeightsI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +pointer(float_array), +integer, +integer, diff --git a/src/methods/linear_regression/linear_regression_test.pl b/src/methods/linear_regression/linear_regression_test.pl index 8223f1c..6fe709f 100644 --- a/src/methods/linear_regression/linear_regression_test.pl +++ b/src/methods/linear_regression/linear_regression_test.pl @@ -1,3 +1,6 @@ + +:- module(linear_regression_tests, [run_linear_regression_tests/0]). + :- use_module(library(plunit)). :- use_module(linear_regression). @@ -49,4 +52,38 @@ test(train) :- predict(X, Xsize,Xrownum, Predic, PredicSize), convert_float_array_to_list(Predic, PredicSize, [0.20000000298023224,0.20000000298023224,0.20000000298023224,0.20000000298023224]). -:- end_tests(lists). \ No newline at end of file +:- end_tests(lists). + +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_linear_regression_tests :- + run_tests. + diff --git a/src/methods/lmnn/lmnn.cpp b/src/methods/lmnn/lmnn.cpp index 6fb3f09..b8a8066 100644 --- a/src/methods/lmnn/lmnn.cpp +++ b/src/methods/lmnn/lmnn.cpp @@ -17,7 +17,6 @@ using namespace lmnn; using namespace mlpack::metric; -// TODO: // input: const arma::mat & dataset, // const arma::Row< size_t > & labels, // const size_t k, @@ -25,6 +24,8 @@ using namespace mlpack::metric; // arma::mat & outputMatrix <-, // output: // description: +// Is a single predicate that initiates the lmnn model with all the given params and then performs Large Margin Nearest Neighbors metric learning on the reference data. +// void lmnn(char const *optimizer, float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, @@ -68,63 +69,71 @@ void lmnn(char const *optimizer, } - if (strcmp(optimizer, "amsgrad") == 0) + try { - LMNN<LMetric<2>> lmnn(data, labelsVector, k); - lmnn.Regularization() = regularization; - lmnn.Range() = range; - lmnn.Optimizer().StepSize() = stepSize; - lmnn.Optimizer().MaxIterations() = passes * data.n_cols; - lmnn.Optimizer().Tolerance() = tolerance; - lmnn.Optimizer().Shuffle() = (shuffle == 1); - lmnn.Optimizer().BatchSize() = batchSize; + if (strcmp(optimizer, "amsgrad") == 0) + { + LMNN<LMetric<2>> lmnn(data, labelsVector, k); + lmnn.Regularization() = regularization; + lmnn.Range() = range; + lmnn.Optimizer().StepSize() = stepSize; + lmnn.Optimizer().MaxIterations() = passes * data.n_cols; + lmnn.Optimizer().Tolerance() = tolerance; + lmnn.Optimizer().Shuffle() = (shuffle == 1); + lmnn.Optimizer().BatchSize() = batchSize; - lmnn.LearnDistance(outputReturnMat); - } - else if (strcmp(optimizer, "amsgrad") == 0) - { - LMNN<LMetric<2>, ens::BBS_BB> lmnn(data, labelsVector, k); - lmnn.Regularization() = regularization; - lmnn.Range() = range; - lmnn.Optimizer().StepSize() = stepSize; - lmnn.Optimizer().MaxIterations() = passes * data.n_cols; - lmnn.Optimizer().Tolerance() = tolerance; - lmnn.Optimizer().Shuffle() = (shuffle == 1); - lmnn.Optimizer().BatchSize() = batchSize; + lmnn.LearnDistance(outputReturnMat); + } + else if (strcmp(optimizer, "amsgrad") == 0) + { + LMNN<LMetric<2>, ens::BBS_BB> lmnn(data, labelsVector, k); + lmnn.Regularization() = regularization; + lmnn.Range() = range; + lmnn.Optimizer().StepSize() = stepSize; + lmnn.Optimizer().MaxIterations() = passes * data.n_cols; + lmnn.Optimizer().Tolerance() = tolerance; + lmnn.Optimizer().Shuffle() = (shuffle == 1); + lmnn.Optimizer().BatchSize() = batchSize; - lmnn.LearnDistance(outputReturnMat); - } - else if (strcmp(optimizer, "amsgrad") == 0) - { - // copied advise from the lmnn.main file - // Using SGD is not recommended as the learning matrix can - // diverge to inf causing serious memory problems. - LMNN<LMetric<2>, ens::StandardSGD> lmnn(data, labelsVector, k); - lmnn.Regularization() = regularization; - lmnn.Range() = range; - lmnn.Optimizer().StepSize() = stepSize; - lmnn.Optimizer().MaxIterations() = passes * data.n_cols; - lmnn.Optimizer().Tolerance() = tolerance; - lmnn.Optimizer().Shuffle() = (shuffle == 1); - lmnn.Optimizer().BatchSize() = batchSize; + lmnn.LearnDistance(outputReturnMat); + } + else if (strcmp(optimizer, "amsgrad") == 0) + { + // copied advise from the lmnn.main file + // Using SGD is not recommended as the learning matrix can + // diverge to inf causing serious memory problems. + LMNN<LMetric<2>, ens::StandardSGD> lmnn(data, labelsVector, k); + lmnn.Regularization() = regularization; + lmnn.Range() = range; + lmnn.Optimizer().StepSize() = stepSize; + lmnn.Optimizer().MaxIterations() = passes * data.n_cols; + lmnn.Optimizer().Tolerance() = tolerance; + lmnn.Optimizer().Shuffle() = (shuffle == 1); + lmnn.Optimizer().BatchSize() = batchSize; - lmnn.LearnDistance(outputReturnMat); - } - else if (strcmp(optimizer, "amsgrad") == 0) - { - LMNN<LMetric<2>, ens::L_BFGS> lmnn(data, labelsVector, k); - lmnn.Regularization() = regularization; - lmnn.Range() = range; - lmnn.Optimizer().MaxIterations() = maxIterations; - lmnn.Optimizer().MinGradientNorm() = tolerance; + lmnn.LearnDistance(outputReturnMat); + } + else if (strcmp(optimizer, "amsgrad") == 0) + { + LMNN<LMetric<2>, ens::L_BFGS> lmnn(data, labelsVector, k); + lmnn.Regularization() = regularization; + lmnn.Range() = range; + lmnn.Optimizer().MaxIterations() = maxIterations; + lmnn.Optimizer().MinGradientNorm() = tolerance; - lmnn.LearnDistance(outputReturnMat); + lmnn.LearnDistance(outputReturnMat); + } + else + { + raisePrologDomainExeption(optimizer, 1, "The given Optimizer is unkown!", "lmnn"); + } } - else + catch(const std::exception& e) { - cout << "wrong optimizer input" << endl; + raisePrologSystemExeption(e.what()); } + // return the Matrix returnMatrixInformation(outputReturnMat, outputMatArr, outputMatColNum, outputMatRowNum); } diff --git a/src/methods/lmnn/lmnn.pl b/src/methods/lmnn/lmnn.pl index 8ed2a3a..8bf6c13 100644 --- a/src/methods/lmnn/lmnn.pl +++ b/src/methods/lmnn/lmnn.pl @@ -39,7 +39,13 @@ %% --Description-- %% Is a single predicate that initiates the lmnn model with all the given params and then performs Large Margin Nearest Neighbors metric learning on the reference data. %% -foreign(lmnn, c, lmnn( +string, +lmnn(Optimizer, DataList, DataRows, LabelsList, K, Regularization, StepSize, Passes, MaxIterations, Tolerance, Center, Shuffle, BatchSize, Range, Rank, DistanceList, ZCols) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(LabelsList, array(Ysize, Y)), + lmnnI(Optimizer, X, Xsize, Xrownum, Y, Ysize, K, Regularization, StepSize, Passes, MaxIterations, Tolerance, Center, Shuffle, BatchSize, Range, Rank, Z, ZCols, ZRows), + convert_float_array_to_2d_list(Z, ZCols, ZRows, DistanceList). + +foreign(lmnn, c, lmnnI( +string, +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, diff --git a/src/methods/lmnn/lmnn_test.pl b/src/methods/lmnn/lmnn_test.pl index 9bc9844..23c98ee 100644 --- a/src/methods/lmnn/lmnn_test.pl +++ b/src/methods/lmnn/lmnn_test.pl @@ -1,3 +1,6 @@ + +:- module(lmnn_tests, [run_lmnn_tests/0]). + :- use_module(library(plunit)). :- use_module(lmnn). @@ -6,51 +9,36 @@ 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 +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_lmnn_tests :- + run_tests. + diff --git a/src/methods/local_coordinate_coding/local_coordinate_coding.cpp b/src/methods/local_coordinate_coding/local_coordinate_coding.cpp index 1be34ba..8cd6474 100644 --- a/src/methods/local_coordinate_coding/local_coordinate_coding.cpp +++ b/src/methods/local_coordinate_coding/local_coordinate_coding.cpp @@ -20,7 +20,7 @@ LocalCoordinateCoding lccGlobObj; bool normalizeData = false; -// TODO: + // input: const arma::mat & data, // const size_t atoms, // const double lambda, @@ -29,12 +29,14 @@ bool normalizeData = false; // const DictionaryInitializer & initializer = DictionaryInitializer() // 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 arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); if (normalizeData) @@ -44,32 +46,52 @@ void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer da data.col(i) /= arma::norm(data.col(i), 2); } - lccGlobObj = LocalCoordinateCoding(data, atoms, lambda, maxIterations, tolerance); + + try + { + lccGlobObj = LocalCoordinateCoding(data, atoms, lambda, maxIterations, tolerance);lccGlobObj = LocalCoordinateCoding(atoms, lambda, maxIterations, tolerance); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } } -// TODO: + // 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. +// void initModelNoTrain(SP_integer normalize, SP_integer atoms, double lambda, SP_integer maxIterations, double tolerance) { normalizeData = normalize == 1; - lccGlobObj = LocalCoordinateCoding(atoms, lambda, maxIterations, tolerance); + + try + { + lccGlobObj = LocalCoordinateCoding(atoms, lambda, maxIterations, tolerance); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } } -// TODO: + // 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, - float **codesMatArr, SP_integer *codesMatColNum, SP_integer *codesMatRowNum) + float **codesMatArr, SP_integer *codesMatColNum, SP_integer *codesMatRowNum) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); // create the ReturnMat @@ -83,7 +105,16 @@ void encode(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, data.col(i) /= arma::norm(data.col(i), 2); } - lccGlobObj.Encode(data, codesReturnMat); + + try + { + lccGlobObj.Encode(data, codesReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } + // return the Matrix returnMatrixInformation(codesReturnMat, codesMatArr, codesMatColNum, codesMatRowNum); @@ -95,6 +126,8 @@ void encode(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, // 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) @@ -116,7 +149,16 @@ void objective(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowN data.col(i) /= arma::norm(data.col(i), 2); } - lccGlobObj.Objective(data, codesReturnMat, adjacenciesReturnVector); + + try + { + lccGlobObj.Objective(data, codesReturnMat, adjacenciesReturnVector); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } + // return the Matrix returnMatrixInformation(codesReturnMat, codesMatArr, codesMatColNum, codesMatRowNum); @@ -131,6 +173,8 @@ void objective(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowN // 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) @@ -152,7 +196,16 @@ void optimizeDictionary(float *dataMatArr, SP_integer dataMatSize, SP_integer da data.col(i) /= arma::norm(data.col(i), 2); } - lccGlobObj.Objective(data, codesReturnMat, adjacenciesReturnVector); + + try + { + lccGlobObj.OptimizeDictionary(data, codesReturnMat, adjacenciesReturnVector); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + } + // return the Matrix returnMatrixInformation(codesReturnMat, codesMatArr, codesMatColNum, codesMatRowNum); @@ -161,11 +214,13 @@ void optimizeDictionary(float *dataMatArr, SP_integer dataMatSize, SP_integer da returnVectorInformation(arma::conv_to<vec>::from(adjacenciesReturnVector), adjacenciesArr, adjacenciesArrSize); } -// TODO: + // 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 @@ -178,5 +233,13 @@ double train(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum data.col(i) /= arma::norm(data.col(i), 2); } - return lccGlobObj.Train(data); + + 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 cadc35e..9c7d2be 100644 --- a/src/methods/local_coordinate_coding/local_coordinate_coding.pl +++ b/src/methods/local_coordinate_coding/local_coordinate_coding.pl @@ -1,10 +1,10 @@ -:- module(local_coordinate_coding, [ initModelWithTrain/8, +:- module(local_coordinate_coding, [ initModelWithTrain/7, initModelNoTrain/5, - encode/6, - objective/8, - optimizeDictionary/8, - train/4]). + encode/4, + objective/5, + optimizeDictionary/5, + train/3]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -35,7 +35,11 @@ %% --Description-- %% Initializes the model and trains it so encode/6 can be called after %% -foreign(initModelWithTrain, c, initModelWithTrain( +pointer(float_array), +integer, +integer, +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)). @@ -52,7 +56,10 @@ foreign(initModelWithTrain, c, initModelWithTrain( +pointer(float_array), + %% --Description-- %% Initializes the model but doesnt train it so train/4 has to be called befor encode/6 can be used. %% -foreign(initModelNoTrain, c, initModelNoTrain( +integer, +initModelNoTrain(Normalize, Atoms, Lambda, MaxIterations, Tolerance) :- + initModelNoTrainI(Normalize, Atoms, Lambda, MaxIterations, Tolerance). + +foreign(initModelNoTrain, c, initModelNoTrainI( +integer, +integer, +float32, +integer, +float32)). @@ -65,7 +72,12 @@ foreign(initModelNoTrain, c, initModelNoTrain( +integer, %% --Description-- %% Code each point via distance-weighted LARS. %% -foreign(encode, c, encode( +pointer(float_array), +integer, +integer, +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)). @@ -79,9 +91,15 @@ foreign(encode, c, encode( +pointer(float_array), +integer, +integer, %% --Description-- %% Compute objective function given the list of adjacencies. %% -foreign(objective, c, objective(+pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, -integer, - -pointer(float_array), -integer)). +objective(DataList, DataRows, CodesList, ZCols, 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-- @@ -94,7 +112,13 @@ foreign(objective, c, objective(+pointer(float_array), +integer, +integer, %% --Description-- %% Learn dictionary by solving linear system. %% -foreign(optimizeDictionary, c, optimizeDictionary( +pointer(float_array), +integer, +integer, +optimizeDictionary(DataList, DataRows, CodesList, ZCols, 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)). @@ -108,8 +132,12 @@ foreign(optimizeDictionary, c, optimizeDictionary( +pointer(float_array), + %% --Description-- %% Run local coordinate coding and train the model. %% -foreign(train, c, train(+pointer(float_array), +integer, +integer, - [-float32])). +train(DataList, DataRows, ReturnValue) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), + trainI(X, Xsize, Xrows, ReturnValue). + +foreign(train, c, trainI( +pointer(float_array), +integer, +integer, + [-float32])). %% Defines the functions that get connected from main.cpp 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 b8968de..19da7aa 100644 --- a/src/methods/local_coordinate_coding/local_coordinate_coding_test.pl +++ b/src/methods/local_coordinate_coding/local_coordinate_coding_test.pl @@ -1,3 +1,6 @@ + +:- module(local_coordinate_tests, [run_local_coordinate_tests/0]). + :- use_module(library(plunit)). :- use_module(local_coordinate_coding). @@ -6,51 +9,36 @@ 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 +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_local_coordinate_tests :- + run_tests. + diff --git a/src/methods/logistic_regression/logistic_regression.cpp b/src/methods/logistic_regression/logistic_regression.cpp index f206bda..df09022 100644 --- a/src/methods/logistic_regression/logistic_regression.cpp +++ b/src/methods/logistic_regression/logistic_regression.cpp @@ -18,169 +18,238 @@ using namespace mlpack::regression; // Global Variable of the LogisticRegression object so it can be accessed from all functions LogisticRegression logisticRegression; -// TODO: + // input: const MatType & predictors, // const arma::Row< size_t > & responses, // const arma::rowvec & initialPoint, // const double lambda = 0 // output: // description: -void initModelNoOptimizer(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, float *responsesArr, SP_integer responsesArrSize, double lambda) +// Initialize the logistic_regression model without specifing a optimizer. +// +void initModelNoOptimizer(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, + float *responsesArr, SP_integer responsesArrSize, + double lambda) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat predictors = convertArrayToMat(predictorsMatArr, predictorsMatSize, predictorsMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec arma::Row<size_t> responsesVector = convertArrayToVec(responsesArr, responsesArrSize); - logisticRegression = LogisticRegression(predictors, responsesVector, lambda); + + try + { + logisticRegression = LogisticRegression(predictors, responsesVector, lambda); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } } -// TODO: + // input: const MatType & predictors, // const arma::Row< size_t > & responses, // OptimizerType & optimizer, // const double lambda // output: // description: -void initModelWithOptimizer(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, float *responsesArr, SP_integer responsesArrSize, char const *optimizer, double lambda) +// Initialize the logistic_regression model and specify the optimizer. +// +void initModelWithOptimizer(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, + float *responsesArr, SP_integer responsesArrSize, + char const *optimizer, + double lambda) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat predictors = convertArrayToMat(predictorsMatArr, predictorsMatSize, predictorsMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec arma::Row<size_t> responsesVector = convertArrayToVec(responsesArr, responsesArrSize); - logisticRegression = LogisticRegression<>(predictors.n_cols, lambda); - - if (strcmp(optimizer, "lbfgs") == 0) - { - logisticRegression.Train(predictors,responsesVector); - } - else if (strcmp(optimizer, "psgd") == 0) + + try { - logisticRegression.Train(predictors,responsesVector, ens::ParallelSGD(100,64)); + logisticRegression = LogisticRegression<>(predictors.n_cols, lambda); + + if (strcmp(optimizer, "lbfgs") == 0) + { + logisticRegression.Train(predictors,responsesVector); + } + else if (strcmp(optimizer, "psgd") == 0) + { + logisticRegression.Train(predictors,responsesVector, ens::ParallelSGD(100,64)); + } + else + { + raisePrologDomainExeption(optimizer, 4, "The given Optimizer is unkown!", "initModelWithOptimizer"); + } } - else + catch(const std::exception& e) { - cout << "Wrong optimizer input" << endl; + raisePrologSystemExeption(e.what()); + return; } } -// TODO: + // input: const VecType & point, // const double decisionBoundary = 0.5 // // output: size_t predicted point label // description: -SP_integer classifyPoint(float *pointArr, SP_integer pointArrSize, double decisionBoundary) +// Classify the given point. +// +SP_integer classifyPoint(float *pointArr, SP_integer pointArrSize, + double decisionBoundary) { - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec rowvec pointVector = convertArrayToRowvec(pointArr, pointArrSize); - return logisticRegression.Classify(pointVector, decisionBoundary); + try + { + return logisticRegression.Classify(pointVector, decisionBoundary); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return 0; + } } -// TODO: + // input: const MatType & dataset, // arma::Row< size_t > & labels <-, +// arma::mat & probabilities <-, // const double decisionBoundary = 0.5 // output: // description: -void classifyLabels(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float **labelsArr, SP_integer *labelsArrSize, double decisionBoundary) +// Classify the given points, returning the predicted labels and probabilities for each point. +// +void classifyMatrix(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float **labelsArr, SP_integer *labelsArrSize, + float **probsMatArr, SP_integer *probsMatColNum, SP_integer *probsMatRowNum, + double decisionBoundary) { // convert the Prolog arrays to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); // get the ReturnVector Row<size_t> labelsReturnVector; - - logisticRegression.Classify(data, labelsReturnVector, decisionBoundary); - - // return the Vector lenght - *labelsArrSize = labelsReturnVector.n_elem; - - // return the Vector as Array - *labelsArr = convertToArray(labelsReturnVector); -} - -// TODO: -// input: const MatType & dataset, -// arma::mat & probabilities <- -// output: -// description: -void classifyProbs(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float **probsMatArr, SP_integer *probsMatColNum, SP_integer *probsMatRowNum) -{ - // convert the Prolog arrays to arma::mat - mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - - // get the ReturnMat + // create the ReturnMat mat probsReturnMat; + - logisticRegression.Classify(data, probsReturnMat); - - // return the Matrix dimensions - *probsMatColNum = probsReturnMat.n_cols; - *probsMatRowNum = probsReturnMat.n_rows; - - // return the Matrix as one long Array - *probsMatArr = convertToArray(probsReturnMat); + try + { + logisticRegression.Classify(data, labelsReturnVector, decisionBoundary); + logisticRegression.Classify(data, probsReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } + + + // return the Vector + returnVectorInformation(labelsReturnVector, labelsArr, labelsArrSize); + // return the Matrix + returnMatrixInformation(probsReturnMat, probsMatArr, probsMatColNum, probsMatRowNum); } -// TODO: + // input: const MatType & predictors, // const arma::Row< size_t > & responses, // const double decisionBoundary = 0.5 // // output: double accuracy // description: -double computeAccuracy(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, float *responsesArr, SP_integer responsesArrSize, double decisionBoundary) +// Compute the accuracy of the model on the given predictors and responses, using the given decision boundary. +// +double computeAccuracy(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, + float *responsesArr, SP_integer responsesArrSize, + double decisionBoundary) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat predictors = convertArrayToMat(predictorsMatArr, predictorsMatSize, predictorsMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec arma::Row<size_t> responsesVector = convertArrayToVec(responsesArr, responsesArrSize); - return logisticRegression.ComputeAccuracy(predictors, responsesVector, decisionBoundary); + try + { + return logisticRegression.ComputeAccuracy(predictors, responsesVector, decisionBoundary); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return 0.0; + } } -// TODO: + // input: const MatType & predictors, // const arma::Row< size_t > & responses // // output: double error // description: -double computeError(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, float *responsesArr, SP_integer responsesArrSize) +// Compute the error of the model. +// +double computeError(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, + float *responsesArr, SP_integer responsesArrSize) { // convert the Prolog arrays to arma::mat mat predictors = convertArrayToMat(predictorsMatArr, predictorsMatSize, predictorsMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec arma::Row<size_t> responsesVector = convertArrayToVec(responsesArr, responsesArrSize); - return logisticRegression.ComputeError(predictors, responsesVector); + try + { + return logisticRegression.ComputeError(predictors, responsesVector); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return 0.0; + } } -// TODO: + // input: const MatType & predictors, // const arma::Row< size_t > & responses, // OptimizerType & optimizer, // CallbackTypes &&... callbacks // output: // description: -void train(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, float *responsesArr, SP_integer responsesArrSize, char const *optimizer) +// Train the logistic_regression model on the given input data. +// +void train(float *predictorsMatArr, SP_integer predictorsMatSize, SP_integer predictorsMatRowNum, + float *responsesArr, SP_integer responsesArrSize, + char const *optimizer) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat predictors = convertArrayToMat(predictorsMatArr, predictorsMatSize, predictorsMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec arma::Row<size_t> responsesVector = convertArrayToVec(responsesArr, responsesArrSize); - if (strcmp(optimizer, "lbfgs") == 0) - { - logisticRegression.Train(predictors,responsesVector); - } - else if (strcmp(optimizer, "psgd") == 0) + + try { - logisticRegression.Train(predictors,responsesVector, ens::ParallelSGD(100,64)); + if (strcmp(optimizer, "lbfgs") == 0) + { + logisticRegression.Train(predictors,responsesVector); + } + else if (strcmp(optimizer, "psgd") == 0) + { + logisticRegression.Train(predictors,responsesVector, ens::ParallelSGD(100,64)); + } + else + { + raisePrologDomainExeption(optimizer, 4, "The given Optimizer is unkown!", "initModelWithOptimizer"); + } } - else + catch(const std::exception& e) { - cout << "Wrong optimizer input" << endl; + raisePrologSystemExeption(e.what()); + return; } } diff --git a/src/methods/logistic_regression/logistic_regression.pl b/src/methods/logistic_regression/logistic_regression.pl index ea7b70a..86228c5 100644 --- a/src/methods/logistic_regression/logistic_regression.pl +++ b/src/methods/logistic_regression/logistic_regression.pl @@ -1,12 +1,11 @@ -:- module(logistic_regression, [ initModelNoOptimizer/6, - initModelWithOptimizer/7, - classifyPoint/4, - classifyLabels/6, - classifyProbs/6, - computeAccuracy/7, - computeError/6, - train/6]). +:- module(logistic_regression, [ initModelNoOptimizer/4, + initModelWithOptimizer/5, + classifyPoint/3, + classifyMatrix/6, + computeAccuracy/5, + computeError/4, + train/4]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -34,7 +33,12 @@ %% --Description-- %% Initialize the logistic_regression model without specifing a optimizer. %% -foreign(initModelNoOptimizer, c, initModelNoOptimizer( +pointer(float_array), +integer, +integer, +initModelNoOptimizer(DataList, DataRows, ResponsesList, Lambda) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + initModelNoOptimizerI(X, Xsize, Xrownum, Y, Ysize, Lambda). + +foreign(initModelNoOptimizer, c, initModelNoOptimizerI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +float32)). @@ -50,7 +54,12 @@ foreign(initModelNoOptimizer, c, initModelNoOptimizer( +pointer(float_array), + %% --Description-- %% Initialize the logistic_regression model and specify the optimizer. %% -foreign(initModelWithOptimizer, c, initModelWithOptimizer( +pointer(float_array), +integer, +integer, +initModelWithOptimizer(DataList, DataRows, ResponsesList, Responses, Lambda) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + initModelWithOptimizerI(X, Xsize, Xrownum, Y, Ysize, Responses, Lambda). + +foreign(initModelWithOptimizer, c, initModelWithOptimizerI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +string, +float32)). @@ -66,9 +75,13 @@ foreign(initModelWithOptimizer, c, initModelWithOptimizer( +pointer(float_a %% --Description-- %% Classify the given point. %% -foreign(classifyPoint, c, classifyPoint(+pointer(float_array), +integer, - +float32, - [-integer])). +classifyPoint(PointList, DecisionBoundary, PredicLabel) :- + convert_list_to_float_array(PointList, array(Xsize, X)), + classifyPointI(X, Xsize, DecisionBoundary, PredicLabel). + +foreign(classifyPoint, c, classifyPointI( +pointer(float_array), +integer, + +float32, + [-integer])). %% --Input-- @@ -77,28 +90,23 @@ foreign(classifyPoint, c, classifyPoint(+pointer(float_array), +integer, %% %% --Output-- %% vec predicLabels +%% mat probabilities %% %% --Description-- %% Classify the given points, returning the predicted labels for each point. %% -foreign(classifyLabels, c, classifyLabels( +pointer(float_array), +integer, +integer, +classifyMatrix(DataList, DataRows, PredictionList, ProbsList, ZCols, DecisionBoundary) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), + classifyMatrixI(X, Xsize, Xrows, Y, Ysize, Z, ZCols, ZRows, DecisionBoundary), + convert_float_array_to_list(Y, Ysize, PredictionList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, ProbsList). + +foreign(classifyMatrix, c, classifyMatrixI( +pointer(float_array), +integer, +integer, -pointer(float_array), -integer, + -pointer(float_array), -integer, -integer, +float32)). -%% --Input-- -%% mat data -%% -%% --Output-- -%% mat probabilities -%% -%% --Description-- -%% Classify the given points, returning class probabilities for each point. -%% -foreign(classifyProbs, c, classifyProbs(+pointer(float_array), +integer, +integer, - -pointer(float_array), -integer, -integer)). - - %% --Input-- %% mat data, %% vec responses, @@ -110,7 +118,12 @@ foreign(classifyProbs, c, classifyProbs(+pointer(float_array), +integer, +intege %% --Description-- %% Compute the accuracy of the model on the given predictors and responses, using the given decision boundary. %% -foreign(computeAccuracy, c, computeAccuracy( +pointer(float_array), +integer, +integer, +computeAccuracy(DataList, DataRows, ResponsesList, DecisionBoundary, Accuracy) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + computeAccuracyI(X, Xsize, Xrownum, Y, Ysize, DecisionBoundary, Accuracy). + +foreign(computeAccuracy, c, computeAccuracyI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +float32, [-float32])). @@ -126,7 +139,12 @@ foreign(computeAccuracy, c, computeAccuracy( +pointer(float_array), +integer, %% --Description-- %% Compute the error of the model. %% -foreign(computeError, c, computeError( +pointer(float_array), +integer, +integer, +computeError(DataList, DataRows, ResponsesList, Error) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + computeErrorI(X, Xsize, Xrownum, Y, Ysize, Error). + +foreign(computeError, c, computeErrorI( +pointer(float_array), +integer, +integer, +pointer(float_array), +integer, [-float32])). @@ -141,17 +159,21 @@ foreign(computeError, c, computeError( +pointer(float_array), +integer, +intege %% --Description-- %% Train the logistic_regression model on the given input data. %% -foreign(train, c, train(+pointer(float_array), +integer, +integer, - +pointer(float_array), +integer, - +string)). +train(DataList, DataRows, ResponsesList, Optimizer) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(ResponsesList, array(Ysize, Y)), + trainI(X, Xsize, Xrownum, Y, Ysize, Optimizer). + +foreign(train, c, trainI( +pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +string)). %% Defines the functions that get connected from main.cpp foreign_resource(logistic_regression, [ initModelNoOptimizer, initModelWithOptimizer, classifyPoint, - classifyLabels, - classifyProbs, + classifyMatrix, computeAccuracy, computeError, train]). diff --git a/src/methods/logistic_regression/logistic_regression_test.pl b/src/methods/logistic_regression/logistic_regression_test.pl index 80194c4..41cb4f1 100644 --- a/src/methods/logistic_regression/logistic_regression_test.pl +++ b/src/methods/logistic_regression/logistic_regression_test.pl @@ -1,3 +1,6 @@ + +:- module(logistic_regression_tests, [run_logistic_regression_tests/0]). + :- use_module(library(plunit)). :- use_module(logistic_regression). @@ -6,51 +9,36 @@ 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 +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_logistic_regression_tests :- + run_tests. + diff --git a/src/methods/lsh/lsh.cpp b/src/methods/lsh/lsh.cpp index f3d2f34..41c28ff 100644 --- a/src/methods/lsh/lsh.cpp +++ b/src/methods/lsh/lsh.cpp @@ -20,7 +20,7 @@ LSHSearch lshSearch; // TODO: adding support for arma::cube -// TODO: + // input: MatType referenceSet, // const size_t numProj, // const size_t numTables, @@ -29,32 +29,51 @@ LSHSearch lshSearch; // const size_t bucketSize = 500 // output: // description: +// Initiatzes the model and trains it. +// void initModel(float *referenceMatArr, SP_integer referenceMatSize, SP_integer referenceMatRowNum, SP_integer numProj, SP_integer numTables, double hashWidth, SP_integer secondHashSize, SP_integer bucketSize) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat reference = convertArrayToMat(referenceMatArr, referenceMatSize, referenceMatRowNum); - - lshSearch = LSHSearch(reference, numProj, numTables, hashWidth, secondHashSize, bucketSize); + + try + { + lshSearch = LSHSearch(reference, numProj, numTables, hashWidth, secondHashSize, bucketSize); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } } -// TODO: + // input: const arma::Mat< size_t > & foundNeighbors, // const arma::Mat< size_t > & realNeighbors // output: double recall percentage [0, 1] // description: +// Compute the recall (% of neighbors found) given the neighbors returned by searchWithQuery/12 or searchNoQuery/9 and a "ground truth" set of neighbors. +// double computeRecall(float *foundNeighborsMatArr, SP_integer foundNeighborsMatSize, SP_integer foundNeighborsMatRowNum, float *realNeighborsMatArr, SP_integer realNeighborsMatSize, SP_integer realNeighborsMatRowNum) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat Mat< size_t > foundNeighbors = conv_to<Mat< size_t >>::from(convertArrayToMat(foundNeighborsMatArr, foundNeighborsMatSize, foundNeighborsMatRowNum)); - Mat< size_t > realNeighbors = conv_to<Mat< size_t >>::from(convertArrayToMat(realNeighborsMatArr, realNeighborsMatSize, realNeighborsMatRowNum)); - return lshSearch.ComputeRecall(foundNeighbors, realNeighbors); + try + { + return lshSearch.ComputeRecall(foundNeighbors, realNeighbors); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return 0.0; + } } -// TODO: + // input: const MatType & querySet, // const size_t k, // arma::Mat< size_t > & resultingNeighbors <-, @@ -63,30 +82,39 @@ double computeRecall(float *foundNeighborsMatArr, SP_integer foundNeighborsMatSi // const size_t T = 0 // output: // description: +// Compute the nearest neighbors of the points in the given query set and store the output in the given matrices. +// void searchWithQuery(float *querySetMatArr, SP_integer querySetMatSize, SP_integer querySetMatRowNum, SP_integer k, float **resultingNeighborsMatArr, SP_integer *resultingNeighborsMatColNum, SP_integer *resultingNeighborsMatRowNum, float **distancesMatArr, SP_integer *distancesMatColNum, SP_integer *distancesMatRowNum, SP_integer numTablesToSearch, SP_integer T) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat querySet = convertArrayToMat(querySetMatArr, querySetMatSize, querySetMatRowNum); // create the ReturnMat Mat< size_t > resultingNeighborsReturnMat; - mat distancesReturnMat; - lshSearch.Search(querySet, k, resultingNeighborsReturnMat, distancesReturnMat, numTablesToSearch, T); + + try + { + lshSearch.Search(querySet, k, resultingNeighborsReturnMat, distancesReturnMat, numTablesToSearch, T); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } - // return the Matrix - returnMatrixInformation(resultingNeighborsReturnMat, resultingNeighborsMatArr, resultingNeighborsMatColNum, resultingNeighborsMatRowNum); - // return the Matrix + // return the Matrices + returnMatrixInformation(resultingNeighborsReturnMat, resultingNeighborsMatArr, resultingNeighborsMatColNum, resultingNeighborsMatRowNum); returnMatrixInformation(distancesReturnMat, distancesMatArr, distancesMatColNum, distancesMatRowNum); } -// TODO: + // input: const size_t k, // arma::Mat< size_t > & resultingNeighbors <-, // arma::mat & distances <-, @@ -94,6 +122,8 @@ void searchWithQuery(float *querySetMatArr, SP_integer querySetMatSize, SP_integ // size_t T = 0 // output: // description: +// Compute the nearest neighbors and store the output in the given matrices. +// void searchNoQuery(SP_integer k, float **resultingNeighborsMatArr, SP_integer *resultingNeighborsMatColNum, SP_integer *resultingNeighborsMatRowNum, float **distancesMatArr, SP_integer *distancesMatColNum, SP_integer *distancesMatRowNum, @@ -101,19 +131,26 @@ void searchNoQuery(SP_integer k, { // create the ReturnMat Mat< size_t > resultingNeighborsReturnMat; - mat distancesReturnMat; - lshSearch.Search(k, resultingNeighborsReturnMat, distancesReturnMat, numTablesToSearch, T); + + try + { + lshSearch.Search(k, resultingNeighborsReturnMat, distancesReturnMat, numTablesToSearch, T); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } - // return the Matrix - returnMatrixInformation(resultingNeighborsReturnMat, resultingNeighborsMatArr, resultingNeighborsMatColNum, resultingNeighborsMatRowNum); - // return the Matrix + // return the Matrices + returnMatrixInformation(resultingNeighborsReturnMat, resultingNeighborsMatArr, resultingNeighborsMatColNum, resultingNeighborsMatRowNum); returnMatrixInformation(distancesReturnMat, distancesMatArr, distancesMatColNum, distancesMatRowNum); } -// TODO: + // input: MatType referenceSet, // const size_t numProj, // const size_t numTables, @@ -123,11 +160,22 @@ void searchNoQuery(SP_integer k, // const arma::cube & projection = arma::cube() // output: // description: +// Train the LSH model on the given dataset. +// void train(float *referencesMatArr, SP_integer referencesMatSize, SP_integer referencesMatRowNum, SP_integer numProj, SP_integer numTables, double hashWidth, SP_integer secondHashSize, SP_integer bucketSize) { // convert the Prolog arrays to arma::mat mat references = convertArrayToMat(referencesMatArr, referencesMatSize, referencesMatRowNum); - lshSearch.Train(references, numProj, numTables, hashWidth, secondHashSize, bucketSize); + + try + { + lshSearch.Train(references, numProj, numTables, hashWidth, secondHashSize, bucketSize); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } } diff --git a/src/methods/lsh/lsh.pl b/src/methods/lsh/lsh.pl index eca22ab..3d3a118 100644 --- a/src/methods/lsh/lsh.pl +++ b/src/methods/lsh/lsh.pl @@ -1,9 +1,9 @@ -:- module(lsh, [initModel/8, - computeRecall/7, - searchWithQuery/12, - searchNoQuery/9, - train/8]). +:- module(lsh, [initModel/7, + computeRecall/5, + searchWithQuery/9, + searchNoQuery/7, + train/7]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -34,7 +34,12 @@ %% --Description-- %% Initiatzes the model and trains it. %% -foreign(initModel, c, initModel(+pointer(float_array), +integer, +integer, +integer, +integer, +float32, +integer, +integer)). +initModel(ReferenceList, ReferenceRows, NumProj, NumTables, HashWidth, SecondHashSize, BucketSize) :- + convert_list_to_float_array(ReferenceList, ReferenceRows, array(Xsize, Xrownum, X)), + initModelI(X, Xsize, Xrownum, NumProj, NumTables, HashWidth, SecondHashSize, BucketSize). + +foreign(initModel, c, initModelI(+pointer(float_array), +integer, +integer, + +integer, +integer, +float32, +integer, +integer)). %% --Input-- @@ -47,7 +52,14 @@ foreign(initModel, c, initModel(+pointer(float_array), +integer, +integer, +inte %% --Description-- %% Compute the recall (% of neighbors found) given the neighbors returned by searchWithQuery/12 or searchNoQuery/9 and a "ground truth" set of neighbors. %% -foreign(computeRecall, c, computeRecall(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, [-float32])). +computeRecall(FoundNeighborsList, FoundNeighborsRows, RealNeighborsList, RealNeighborsRows, Percentage) :- + convert_list_to_float_array(FoundNeighborsList, FoundNeighborsRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(RealNeighborsList, RealNeighborsRows, array(Ysize, Yrownum, Y)), + computeRecallI(X, Xsize, Xrownum, Y, Ysize, Yrownum, Percentage). + +foreign(computeRecall, c, computeRecallI(+pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, +integer, + [-float32])). %% --Input-- @@ -64,7 +76,17 @@ foreign(computeRecall, c, computeRecall(+pointer(float_array), +integer, +intege %% Compute the nearest neighbors of the points in the given query set and store the output in the given matrices. %% The matrices will be set to the size of n columns by k rows, where n is the number of points in the query dataset and k is the number of neighbors being searched for. %% -foreign(searchWithQuery, c, searchWithQuery(+pointer(float_array), +integer, +integer, +integer, -pointer(float_array), -integer, -integer, -pointer(float_array), -integer, -integer, +integer, +integer)). +searchWithQuery(QueryList, QueryRows, K, ResultingNeighborsList, YCols, DistancesList, ZCols, NumTablesToSearch, T) :- + convert_list_to_float_array(QueryList, QueryRows, array(Xsize, Xrows, X)), + searchWithQueryI(X, Xsize, Xrows, K, Y, YCols, YRows, Z, ZCols, ZRows, NumTablesToSearch, T), + convert_float_array_to_2d_list(Y, YCols, YRows, ResultingNeighborsList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, DistancesList). + +foreign(searchWithQuery, c, searchWithQueryI( +pointer(float_array), +integer, +integer, + +integer, + -pointer(float_array), -integer, -integer, + -pointer(float_array), -integer, -integer, + +integer, +integer)). %% --Input-- @@ -80,7 +102,15 @@ foreign(searchWithQuery, c, searchWithQuery(+pointer(float_array), +integer, +in %% Compute the nearest neighbors and store the output in the given matrices. %% The matrices will be set to the size of n columns by k rows, where n is the number of points in the query dataset and k is the number of neighbors being searched for. %% -foreign(searchNoQuery, c, searchNoQuery(+integer, -pointer(float_array), -integer, -integer, -pointer(float_array), -integer, -integer, +integer, +integer)). +searchNoQuery(K, ResultingNeighborsList, YCols, DistancesList, ZCols, NumTablesToSearch, T) :- + searchNoQueryI(K, Y, YCols, YRows, Z, ZCols, ZRows, NumTablesToSearch, T), + convert_float_array_to_2d_list(Y, YCols, YRows, ResultingNeighborsList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, DistancesList). + +foreign(searchNoQuery, c, searchNoQueryI( +integer, + -pointer(float_array), -integer, -integer, + -pointer(float_array), -integer, -integer, + +integer, +integer)). %% --Input-- @@ -96,7 +126,12 @@ foreign(searchNoQuery, c, searchNoQuery(+integer, -pointer(float_array), -intege %% --Description-- %% Train the LSH model on the given dataset. %% -foreign(train, c, train(+pointer(float_array), +integer, +integer, +integer, +integer, +float32, +integer, +integer)). +train(ReferenceList, ReferenceRows, NumProj, NumTables, HashWidth, SecondHashSize, BucketSize) :- + convert_list_to_float_array(ReferenceList, ReferenceRows, array(Xsize, Xrownum, X)), + trainI(X, Xsize, Xrownum, NumProj, NumTables, HashWidth, SecondHashSize, BucketSize). + +foreign(train, c, trainI(+pointer(float_array), +integer, +integer, + +integer, +integer, +float32, +integer, +integer)). %% Defines the functions that get connected from main.cpp diff --git a/src/methods/lsh/lsh_test.pl b/src/methods/lsh/lsh_test.pl index cbc0147..8461a26 100644 --- a/src/methods/lsh/lsh_test.pl +++ b/src/methods/lsh/lsh_test.pl @@ -1,3 +1,6 @@ + +:- module(lsh_tests, [run_lsh_tests/0]). + :- use_module(library(plunit)). :- use_module(lsh). @@ -6,51 +9,36 @@ 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 +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_lsh_tests :- + run_tests. + diff --git a/src/methods/mean_shift/mean_shift.cpp b/src/methods/mean_shift/mean_shift.cpp index 7db14fb..a9c72c8 100644 --- a/src/methods/mean_shift/mean_shift.cpp +++ b/src/methods/mean_shift/mean_shift.cpp @@ -16,7 +16,6 @@ using namespace std; using namespace mlpack::meanshift; - // TODO: adding support for different Kernels // // input: const double radius = 0, @@ -30,6 +29,8 @@ using namespace mlpack::meanshift; // bool useSeeds = true // output: // description: +// Perform mean shift clustering on the data, returning a list of cluster assignments and centroids. +// void meanShift(double radius, SP_integer maxIterations, float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float **assignmentsArr, SP_integer *assignmentsArrSize, @@ -45,7 +46,15 @@ void meanShift(double radius, SP_integer maxIterations, mat centroidsReturnMat; - MeanShift<>(radius, maxIterations).Cluster(data, assignmentsReturnVector, centroidsReturnMat, (forceConvergence == 1), (useSeeds == 1)); + try + { + MeanShift<>(radius, maxIterations).Cluster(data, assignmentsReturnVector, centroidsReturnMat, (forceConvergence == 1), (useSeeds == 1)); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } // return the Matrix diff --git a/src/methods/mean_shift/mean_shift.pl b/src/methods/mean_shift/mean_shift.pl index f95d7d2..b1c7037 100644 --- a/src/methods/mean_shift/mean_shift.pl +++ b/src/methods/mean_shift/mean_shift.pl @@ -1,5 +1,5 @@ -:- module(mean_shift, [meanShift/12]). +:- module(mean_shift, [meanShift/9]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -31,7 +31,13 @@ %% --Description-- %% Perform mean shift clustering on the data, returning a list of cluster assignments and centroids. %% -foreign(meanShift, c, meanShift(+float32, +integer, +meanShift(Radius, MaxIterations, DataList, DataRows, AssignmentsList, CentroidsList, ZCols, ForceConvergence, UseSeeds) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + meanShiftI(Radius, MaxIterations, X, Xsize, Xrownum, Y, Ysize, Z, ZCols, ZRows, ForceConvergence, UseSeeds), + convert_float_array_to_list(Y, Ysize, AssignmentsList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, CentroidsList). + +foreign(meanShift, c, meanShiftI(+float32, +integer, +pointer(float_array), +integer, +integer, -pointer(float_array), -integer, -pointer(float_array), -integer, -integer, diff --git a/src/methods/mean_shift/mean_shift_test.pl b/src/methods/mean_shift/mean_shift_test.pl index 789a70b..6914576 100644 --- a/src/methods/mean_shift/mean_shift_test.pl +++ b/src/methods/mean_shift/mean_shift_test.pl @@ -1,3 +1,6 @@ + +:- module(mean_shift_tests, [run_mean_shift_tests/0]). + :- use_module(library(plunit)). :- use_module(mean_shift). @@ -15,4 +18,38 @@ test(meanShift) :- convert_float_array_to_2d_list(Centroids, Centroidscolnum, Centroidsrownum, Results), print(Results). -:- end_tests(lists). \ No newline at end of file +:- end_tests(lists). + +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_mean_shift_tests :- + run_tests. + diff --git a/src/methods/naive_bayes_classifier/naive_bayes_classifier.cpp b/src/methods/naive_bayes_classifier/naive_bayes_classifier.cpp index 4de665d..acf8b74 100644 --- a/src/methods/naive_bayes_classifier/naive_bayes_classifier.cpp +++ b/src/methods/naive_bayes_classifier/naive_bayes_classifier.cpp @@ -18,7 +18,7 @@ using namespace mlpack::naive_bayes; // Global Variable of the NaiveBayesClassifier object so it can be accessed from all functions NaiveBayesClassifier<mat> naiveBayesClassifier; -// TODO: + // input: const MatType & data, // const arma::Row< size_t > & labels, // const size_t numClasses, @@ -26,27 +26,49 @@ NaiveBayesClassifier<mat> naiveBayesClassifier; // const double epsilon = 1e-10 // output: // description: -void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, - SP_integer numClasses, SP_integer incrementalVariance, double epsilon) +// Initializes the classifier as per the input and then trains it by calculating the sample mean and variances. +// +void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float *labelsArr, SP_integer labelsArrSize, + SP_integer numClasses, + SP_integer incrementalVariance, + double epsilon) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec Row<size_t> labelsVector = convertArrayToVec(labelsArr, labelsArrSize); - naiveBayesClassifier = NaiveBayesClassifier(data, labelsVector, numClasses, (incrementalVariance == 1), epsilon); + try + { + naiveBayesClassifier = NaiveBayesClassifier(data, labelsVector, numClasses, (incrementalVariance == 1), epsilon); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } } -// TODO: + // input: const size_t dimensionality = 0, // const size_t numClasses = 0, // const double epsilon = 1e-10 // output: // description: +// Initialize the Naive Bayes classifier without performing training. +// void initModelNoTrain(SP_integer dimensionality, SP_integer numClasses, double epsilon) { - naiveBayesClassifier = NaiveBayesClassifier(dimensionality, numClasses, epsilon); + try + { + naiveBayesClassifier = NaiveBayesClassifier(dimensionality, numClasses, epsilon); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } } /* @@ -78,117 +100,145 @@ void classifyPoint(float *pointArr, SP_integer pointArrSize, SP_integer *predict } */ -// TODO: + // input: const MatType & data, // arma::Row< size_t > & predictions <-, // ProbabilitiesMatType & probabilities <- // output: // description: -void classifyMatrix(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float **predicArr, SP_integer *predicArrSize, float **probsMatArr, SP_integer *probsMatColNum, SP_integer *probsMatRowNum) +// Classify the given points using the trained NaiveBayesClassifier model and also return estimates of the probabilities for each class in the given matrix. +// +void classifyMatrix(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float **predicArr, SP_integer *predicArrSize, + float **probsMatArr, SP_integer *probsMatColNum, SP_integer *probsMatRowNum) { // convert the Prolog arrays to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - + // get the ReturnVector Row<size_t> predicReturnVector; // get the ReturnMat mat probsReturnMat; - naiveBayesClassifier.Classify(data, predicReturnVector, probsReturnMat); - // return the Vector lenght - *predicArrSize = predicReturnVector.n_elem; - - // return the Vector as Array - *predicArr = convertToArray(predicReturnVector); + try + { + naiveBayesClassifier.Classify(data, predicReturnVector, probsReturnMat); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } - // return the Matrix dimensions - *probsMatColNum = probsReturnMat.n_cols; - *probsMatRowNum = probsReturnMat.n_rows; - // return the Matrix as one long Array - *probsMatArr = convertToArray(probsReturnMat); + // return the Vector + returnVectorInformation(predicReturnVector, predicArr, predicArrSize); + // return the Matrix + returnMatrixInformation(probsReturnMat, probsMatArr, probsMatColNum, probsMatRowNum); } -// TODO: + // input: // output: mat sample means // description: +// Get the sample means for each class. +// void means(float **meansMatArr, SP_integer *meansMatColNum, SP_integer *meansMatRowNum) { // get the ReturnMat mat meansReturnMat = naiveBayesClassifier.Means(); - // return the Matrix dimensions - *meansMatColNum = meansReturnMat.n_cols; - *meansMatRowNum = meansReturnMat.n_rows; - // return the Matrix as one long Array - *meansMatArr = convertToArray(meansReturnMat); + // return the Matrix + returnMatrixInformation(meansReturnMat, meansMatArr, meansMatColNum, meansMatRowNum); } -// TODO: + // input: // output: mat prior probabilities // description: +// Get the sample probabilities for each class. +// void probabilities(float **probsMatArr, SP_integer *probsMatColNum, SP_integer *probsMatRowNum) { // get the ReturnMat mat probsReturnMat = naiveBayesClassifier.Probabilities(); - // return the Matrix dimensions - *probsMatColNum = probsReturnMat.n_cols; - *probsMatRowNum = probsReturnMat.n_rows; - // return the Matrix as one long Array - *probsMatArr = convertToArray(probsReturnMat); + // return the Matrix + returnMatrixInformation(probsReturnMat, probsMatArr, probsMatColNum, probsMatRowNum); } -// TODO: + // input: const MatType & data, // const arma::Row< size_t > & labels, // const size_t numClasses, // const bool incremental = true // output: // description: -void trainMatrix(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, - SP_integer numClasses, SP_integer incrementalVariance) +// Train the Naive Bayes classifier on the given dataset. +// +void trainMatrix(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, + float *labelsArr, SP_integer labelsArrSize, + SP_integer numClasses, + SP_integer incrementalVariance) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec Row<size_t> labelsVector = convertArrayToVec(labelsArr, labelsArrSize); - naiveBayesClassifier.Train(data, labelsVector, numClasses, (incrementalVariance == 1)); + + try + { + naiveBayesClassifier.Train(data, labelsVector, numClasses, (incrementalVariance == 1)); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } } -// TODO: + // input: const VecType & point, // const size_t label // output: // description: -void trainPoint(float *pointArr, SP_integer pointArrSize, SP_integer label) +// Train the Naive Bayes classifier on the given point. +// +void trainPoint(float *pointArr, SP_integer pointArrSize, + SP_integer label) { - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec rowvec pointVector = convertArrayToRowvec(pointArr, pointArrSize); - naiveBayesClassifier.Train(pointVector, label); + + try + { + naiveBayesClassifier.Train(pointVector, label); + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } } -// TODO: + // input: // output: mat sample variances // description: +// Get the sample variances for each class. +// void variances(float **variancesMatArr, SP_integer *variancesMatColNum, SP_integer *variancesMatRowNum) { // get the ReturnMat mat variancesReturnMat = naiveBayesClassifier.Variances(); - // return the Matrix dimensions - *variancesMatColNum = variancesReturnMat.n_cols; - *variancesMatRowNum = variancesReturnMat.n_rows; - // return the Matrix as one long Array - *variancesMatArr = convertToArray(variancesReturnMat); + // return the Matrix + returnMatrixInformation(variancesReturnMat, variancesMatArr, variancesMatColNum, variancesMatRowNum); } diff --git a/src/methods/naive_bayes_classifier/naive_bayes_classifier.pl b/src/methods/naive_bayes_classifier/naive_bayes_classifier.pl index 0f3130a..da5521a 100644 --- a/src/methods/naive_bayes_classifier/naive_bayes_classifier.pl +++ b/src/methods/naive_bayes_classifier/naive_bayes_classifier.pl @@ -1,13 +1,13 @@ -:- module(naive_bayes_classifier, [ initModelWithTrain/8, +:- module(naive_bayes_classifier, [ initModelWithTrain/6, initModelNoTrain/3, - classifyMatrix/8, - means/3, - probabilities/3, - trainMatrix/7, - trainPoint/3, - variances/3]). + classifyMatrix/5, + means/2, + probabilities/2, + trainMatrix/5, + trainPoint/2, + variances/2]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -37,7 +37,16 @@ %% --Description-- %% Initializes the classifier as per the input and then trains it by calculating the sample mean and variances. %% -foreign(initModelWithTrain, c, initModelWithTrain(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +integer, +float32)). +initModelWithTrain(DataList, DataRows, LabelsList, NumClasses, IncrementalVar, Epsilon) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(LabelsList, array(Ysize, Y)), + initModelWithTrainI(X, Xsize, Xrownum, Y, Ysize, NumClasses, IncrementalVar, Epsilon). + +foreign(initModelWithTrain, c, initModelWithTrainI( +pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +integer, + +integer, + +float32)). %% --Input-- @@ -51,7 +60,12 @@ foreign(initModelWithTrain, c, initModelWithTrain(+pointer(float_array), +intege %% Initialize the Naive Bayes classifier without performing training. %% All of the parameters of the model will be initialized to zero. Be sure to use train before calling classify, otherwise the results may be meaningless. %% -foreign(initModelNoTrain, c, initModelNoTrain(+integer, +integer, +float32)). +initModelNoTrain(NumClasses, IncrementalVar, Epsilon) :- + initModelNoTrainI(NumClasses, IncrementalVar, Epsilon). + +foreign(initModelNoTrain, c, initModelNoTrainI( +integer, + +integer, + +float32)). %% --Input-- @@ -79,7 +93,15 @@ foreign(initModelNoTrain, c, initModelNoTrain(+integer, +integer, +float32)). %% Classify the given points using the trained NaiveBayesClassifier model and also return estimates of the probabilities for each class in the given matrix. %% The predicted labels for each point are stored in the given vector. %% -foreign(classifyMatrix, c, classifyMatrix(+pointer(float_array), +integer, +integer, -pointer(float_array), -integer, -pointer(float_array), -integer, -integer)). +classifyMatrix(DataList, DataRows, PredictionList, ProbsList, ZCols) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), + classifyMatrixI(X, Xsize, Xrows, Y, Ysize, Z, ZCols, ZRows), + convert_float_array_to_list(Y, Ysize, PredictionList), + convert_float_array_to_2d_list(Z, ZCols, ZRows, ProbsList). + +foreign(classifyMatrix, c, classifyMatrixI( +pointer(float_array), +integer, +integer, + -pointer(float_array), -integer, + -pointer(float_array), -integer, -integer)). %% --Input-- @@ -90,7 +112,11 @@ foreign(classifyMatrix, c, classifyMatrix(+pointer(float_array), +integer, +inte %% --Description-- %% Get the sample means for each class. %% -foreign(means, c, means(-pointer(float_array), -integer, -integer)). +means(MeansList, XCols) :- + meansI(X, XCols, XRows), + convert_float_array_to_2d_list(X, XCols, XRows, MeansList). + +foreign(means, c, meansI(-pointer(float_array), -integer, -integer)). %% --Input-- @@ -101,7 +127,11 @@ foreign(means, c, means(-pointer(float_array), -integer, -integer)). %% --Description-- %% Get the sample probabilities for each class. %% -foreign(probabilities, c, probabilities(-pointer(float_array), -integer, -integer)). +probabilities(ProbabilitiesList, XCols) :- + probabilitiesI(X, XCols, XRows), + convert_float_array_to_2d_list(X, XCols, XRows, ProbabilitiesList). + +foreign(probabilities, c, probabilitiesI(-pointer(float_array), -integer, -integer)). %% --Input-- @@ -115,7 +145,15 @@ foreign(probabilities, c, probabilities(-pointer(float_array), -integer, -intege %% --Description-- %% Train the Naive Bayes classifier on the given dataset. The data must be the same dimensionality as the existing model parameters. %% -foreign(trainMatrix, c, trainMatrix(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +integer)). +trainMatrix(DataList, DataRows, LabelsList, NumClasses, IncrementalVar) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrownum, X)), + convert_list_to_float_array(LabelsList, array(Ysize, Y)), + trainMatrixI(X, Xsize, Xrownum, Y, Ysize, NumClasses, IncrementalVar). + +foreign(trainMatrix, c, trainMatrixI( +pointer(float_array), +integer, +integer, + +pointer(float_array), +integer, + +integer, + +integer)). %% --Input-- @@ -128,7 +166,12 @@ foreign(trainMatrix, c, trainMatrix(+pointer(float_array), +integer, +integer, + %% Train the Naive Bayes classifier on the given point. %% This will use the incremental algorithm for updating the model parameters. The data must be the same dimensionality as the existing model parameters. %% -foreign(trainPoint, c, trainPoint(+pointer(float_array), +integer, +integer)). +trainPoint(DataList, Label) :- + convert_list_to_float_array(DataList, array(Xsize, X)), + trainPointI(X, Xsize, Label). + +foreign(trainPoint, c, trainPointI( +pointer(float_array), +integer, + +integer)). %% --Input-- @@ -139,7 +182,11 @@ foreign(trainPoint, c, trainPoint(+pointer(float_array), +integer, +integer)). %% --Description-- %% Get the sample variances for each class. %% -foreign(variances, c, variances(-pointer(float_array), -integer, -integer)). +variances(VariancesList, XCols) :- + variancesI(X, XCols, XRows), + convert_float_array_to_2d_list(X, XCols, XRows, VariancesList). + +foreign(variances, c, variancesI(-pointer(float_array), -integer, -integer)). %% Defines the functions that get connected from main.cpp diff --git a/src/methods/naive_bayes_classifier/naive_bayes_classifier_test.pl b/src/methods/naive_bayes_classifier/naive_bayes_classifier_test.pl index b8100c9..5ddcc33 100644 --- a/src/methods/naive_bayes_classifier/naive_bayes_classifier_test.pl +++ b/src/methods/naive_bayes_classifier/naive_bayes_classifier_test.pl @@ -1,3 +1,6 @@ + +:- module(naive_bayes_classifier_tests, [run_naive_bayes_classifier_tests/0]). + :- use_module(library(plunit)). :- use_module(naive_bayes_classifier). @@ -6,51 +9,36 @@ 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 +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_naive_bayes_classifier_tests :- + run_tests. + diff --git a/src/methods/nca/nca.cpp b/src/methods/nca/nca.cpp index 436946e..f6b0ba2 100644 --- a/src/methods/nca/nca.cpp +++ b/src/methods/nca/nca.cpp @@ -17,13 +17,16 @@ using namespace mlpack::nca; using namespace mlpack::metric; -// TODO: // input: const arma::mat & dataset, // const arma::Row< size_t > & labels, // MetricType metric = MetricType() // arma::mat & outputMatrix, // output: // description: +// Initialize the nca model and the selected optimizer. +// +// Then perform nca on the given data and return the learned distance. +// void nca( char const *optimizerType, double stepSize, SP_integer maxIterations, double tolerance, SP_integer shuffle, @@ -32,47 +35,60 @@ void nca( char const *optimizerType, float *rawLabelsArr, SP_integer rawLabelsArrSize, float **distanceMatArr, SP_integer *distanceMatColNum, SP_integer *distanceMatRowNum) { - // convert the Prolog arrays to arma::mat + // convert the Prolog array to arma::mat mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); - // convert the Prolog arrays to arma::rowvec + // convert the Prolog array to arma::rowvec Row< size_t > rawLabels = convertArrayToVec(rawLabelsArr, rawLabelsArrSize); - // copied parts of the nca.main file - // Now, normalize the labels. - arma::Col<size_t> mappings; - arma::Row<size_t> labels; - data::NormalizeLabels(rawLabels, labels, mappings); - arma::mat distance; distance.eye(); - // Now create the NCA object and run the optimization. - if (strcmp(optimizerType,"sgd") == 0) - { - NCA<LMetric<2> > nca(data, labels); - nca.Optimizer().StepSize() = stepSize; - nca.Optimizer().MaxIterations() = maxIterations; - nca.Optimizer().Tolerance() = tolerance; - nca.Optimizer().Shuffle() = (shuffle == 1); - nca.Optimizer().BatchSize() = batchSize; + try + { + // copied parts of the nca.main file + // Now, normalize the labels. + arma::Col<size_t> mappings; + arma::Row<size_t> labels; + data::NormalizeLabels(rawLabels, labels, mappings); + + // Now create the NCA object and run the optimization. + if (strcmp(optimizerType,"sgd") == 0) + { + NCA<LMetric<2> > nca(data, labels); + nca.Optimizer().StepSize() = stepSize; + nca.Optimizer().MaxIterations() = maxIterations; + nca.Optimizer().Tolerance() = tolerance; + nca.Optimizer().Shuffle() = (shuffle == 1); + nca.Optimizer().BatchSize() = batchSize; + + nca.LearnDistance(distance); + } + else if (strcmp(optimizerType,"lbfgs") == 0) + { + NCA<LMetric<2>, ens::L_BFGS> nca(data, labels); + nca.Optimizer().NumBasis() = numBasis; + nca.Optimizer().MaxIterations() = maxIterations; + nca.Optimizer().ArmijoConstant() = armijoConstant; + nca.Optimizer().Wolfe() = wolfe; + nca.Optimizer().MinGradientNorm() = tolerance; + nca.Optimizer().MaxLineSearchTrials() = maxLineSearchTrials; + nca.Optimizer().MinStep() = minStep; + nca.Optimizer().MaxStep() = maxStep; - nca.LearnDistance(distance); - } - else if (strcmp(optimizerType,"lbfgs") == 0) - { - NCA<LMetric<2>, ens::L_BFGS> nca(data, labels); - nca.Optimizer().NumBasis() = numBasis; - nca.Optimizer().MaxIterations() = maxIterations; - nca.Optimizer().ArmijoConstant() = armijoConstant; - nca.Optimizer().Wolfe() = wolfe; - nca.Optimizer().MinGradientNorm() = tolerance; - nca.Optimizer().MaxLineSearchTrials() = maxLineSearchTrials; - nca.Optimizer().MinStep() = minStep; - nca.Optimizer().MaxStep() = maxStep; + nca.LearnDistance(distance); + } + else + { + raisePrologDomainExeption(optimizerType, 1, "The given OptimizerType is unkown!", "nca"); + } + } + catch(const std::exception& e) + { + raisePrologSystemExeption(e.what()); + return; + } - nca.LearnDistance(distance); - } // return the Matrix returnMatrixInformation(distance, distanceMatArr, distanceMatColNum, distanceMatRowNum); diff --git a/src/methods/nca/nca.pl b/src/methods/nca/nca.pl index 36556bc..f083d3a 100644 --- a/src/methods/nca/nca.pl +++ b/src/methods/nca/nca.pl @@ -1,4 +1,4 @@ -:- module(nca, [nca/20]). +:- module(nca, [nca/17]). %% requirements of library(struct) :- load_files(library(str_decl), @@ -40,7 +40,15 @@ %% %% Then perform nca on the given data and return the learned distance. %% -foreign(nca, c, nca( +string, +nca(OptimizerType, StepSize, MaxIterations, Tolerance, Shuffle, NumBasis, ArmijoConstant, Wolfe, MaxLine, MinStep, MaxStept, BatchSize, + DataList, DataRows, PredictionList, DistanceList, ZCols) :- + convert_list_to_float_array(DataList, DataRows, array(Xsize, Xrows, X)), + convert_list_to_float_array(PredictionList, array(Ysize, Y)), + ncaI(OptimizerType, StepSize, MaxIterations, Tolerance, Shuffle, NumBasis, ArmijoConstant, Wolfe, MaxLine, MinStep, MaxStept, BatchSize, + X, Xsize, Xrows, Y, Ysize, Z, ZCols, ZRows), + convert_float_array_to_2d_list(Z, ZCols, ZRows, DistanceList). + +foreign(nca, c, ncaI( +string, +float32, +integer, +float32, +integer, +integer, +float32, +float32, +integer, +float32, +float32, +integer, diff --git a/src/methods/nca/nca_test.pl b/src/methods/nca/nca_test.pl index 0e5b9cf..60e83f7 100644 --- a/src/methods/nca/nca_test.pl +++ b/src/methods/nca/nca_test.pl @@ -1,3 +1,6 @@ + +:- module(nca_tests, [run_nca_tests/0]). + :- use_module(library(plunit)). :- use_module(nca). @@ -6,51 +9,36 @@ 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 + +%% +%% TESTING predicate predicate/10 +%% +:- begin_tests(predicate). + +%% 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(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(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, Data), + train(Data, 4, [0,1,0,1,1,0,1,1,1,0], 2, perceptron, 50, 0.0001, Error). + +:- end_tests(predicate). + +run_nca_tests :- + run_tests. diff --git a/test_all.pl b/test_all.pl index 749d0c9..d9e4a0a 100644 --- a/test_all.pl +++ b/test_all.pl @@ -1,7 +1,12 @@ +:- use_module('src/methods/newMethod/newMethod_test.pl'). :- use_module('src/methods/adaboost/adaboost_test.pl'). +:- use_module('src/methods/approx_kfn/approx_kfn_test.pl'). + +:- use_module('src/methods/bayesian_linear_regression/bayesian_linear_regression_test.pl'). + :- use_module('src/methods/dbscan/dbscan_test.pl'). :- use_module('src/methods/decision_tree/decision_tree_test.pl'). @@ -10,15 +15,83 @@ :- use_module('src/methods/fastmks/fastmks_test.pl'). +:- use_module('src/methods/hoefding_tree/hoefding_tree_test.pl'). + +:- use_module('src/methods/kde/kde_test.pl'). + +:- use_module('src/methods/kernel_pca/kernel_pca_test.pl'). + +:- use_module('src/methods/kfn/kfn_test.pl'). + +:- use_module('src/methods/kmeans/kmeans_test.pl'). + +:- use_module('src/methods/knn/knn_test.pl'). + +:- use_module('src/methods/lars/lars_test.pl'). + +:- use_module('src/methods/linear_regression/linear_regression_test.pl'). + +:- use_module('src/methods/linear_SVM/linear_SVM_test.pl'). + +:- use_module('src/methods/lmnn/lmnn_test.pl'). + +:- use_module('src/methods/local_coordinate_coding/local_coordinate_coding_test.pl'). + +:- use_module('src/methods/logistic_regression/logistic_regression_test.pl'). + +:- use_module('src/methods/lsh/lsh_test.pl'). + +:- use_module('src/methods/mean_shift/mean_shift_test.pl'). + +:- use_module('src/methods/naive_bayes_classifier/naive_bayes_classifier_test.pl'). + +:- use_module('src/methods/nca/nca_test.pl'). + +:- use_module('src/methods/nmf/nmf_test.pl'). + +:- use_module('src/methods/pca/pca_test.pl'). + +:- use_module('src/methods/perceptron/perceptron_test.pl'). + +:- use_module('src/methods/radical/radical_test.pl'). + +:- use_module('src/methods/random_forest/random_forest_test.pl'). + +:- use_module('src/methods/softmax_regression/softmax_regression_test.pl'). + :- use_module('src/methods/sparse_coding/sparse_coding_test.pl'). :- use_module('src/helper_files/helper_tests.pl'). run :- run_adaboost_tests, + run_approx_kfn_tests, + run_bayesian_linear_regression_tests, run_dbscan_tests, run_decision_tree_tests, run_emst_tests, run_fastmks_tests, + run_hoefding_tree_tests, + run_kde_tests, + run_kernel_pca_tests, + run_kfn_tests, + run_kmeans_tests, + run_knn_tests, + run_lars_tests, + run_linear_regression_tests, + run_linear_SVM_tests, + run_lmnn_tests, + run_local_coordinate_coding_tests, + run_logistic_regression_tests, + run_lsh_tests, + run_mean_shift_tests, + run_naive_bayes_classifier_tests, + run_nca_tests, + run_nmf_tests, + run_pca_tests, + run_perceptron_tests, + run_radical_tests, + run_random_forest_tests, + run_softmax_regression_tests, run_sparse_coding_tests, run_helper_tests. \ No newline at end of file -- GitLab