diff --git a/Makefile b/Makefile index dc3d0c91dbed63835e729a44f4af7de28088aeb1..628ac7199c7333f9465be8795d851af41c7513f9 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ all: make -C src/methods/logistic_regression splfr=$(SPLFR_PATH) make -C src/methods/mean_shift splfr=$(SPLFR_PATH) make -C src/methods/naive_bayes_classifier splfr=$(SPLFR_PATH) + make -C src/methods/perceptron splfr=$(SPLFR_PATH) clean: make -C src/methods/ada_boost clean @@ -24,3 +25,4 @@ clean: make -C src/methods/logistic_regression clean make -C src/methods/mean_shift clean make -C src/methods/naive_bayes_classifier clean + make -C src/methods/perceptron clean diff --git a/src/methods/perceptron/Makefile b/src/methods/perceptron/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3911c137838368723f9035ef9300a5381d3b1d70 --- /dev/null +++ b/src/methods/perceptron/Makefile @@ -0,0 +1,8 @@ +splfr=/usr/local/sicstus4.7.1/bin/splfr + +METHOD_NAME=perceptron + +$(METHOD_NAME).so: $(METHOD_NAME).pl $(METHOD_NAME).cpp + $(splfr) -larmadillo -fopenmp -lmlpack -lstdc++ -cxx --struct $(METHOD_NAME).pl $(METHOD_NAME).cpp ../../helper_files/helper.cpp +clean: + rm $(METHOD_NAME).so diff --git a/src/methods/perceptron/perceptron.cpp b/src/methods/perceptron/perceptron.cpp new file mode 100644 index 0000000000000000000000000000000000000000..789cf0a07725c63164a06db460a346eb8ef55875 --- /dev/null +++ b/src/methods/perceptron/perceptron.cpp @@ -0,0 +1,125 @@ +#include <sicstus/sicstus.h> +/* ex_glue.h is generated by splfr from the foreign/[2,3] facts. + Always include the glue header in your foreign resource code. +*/ +#include "perceptron_glue.h" +#include <mlpack/methods/perceptron/perceptron.hpp> +#include <mlpack/core.hpp> + +// including helper functions for converting between arma structures and arrays +#include "../../helper_files/helper.hpp" + +// some of the most used namespaces +using namespace arma; +using namespace mlpack; +using namespace std; +using namespace mlpack::perceptron; + +// Global Variable of the GlobalMethodObject object so it can be accessed from all functions +Perceptron perceptronGlobal; + +// TODO: +// input: const size_t numClasses = 0, +// const size_t dimensionality = 0, +// const size_t maxIterations = 1000 +// output: +// description: +void initModelNoTrain(SP_integer numClasses, SP_integer dimensionality, SP_integer maxIterations) +{ + perceptronGlobal = Perceptron(numClasses, dimensionality, maxIterations); +} + +// TODO: +// input: const MatType & data, +// const arma::Row< size_t > & labels, +// const size_t numClasses, +// const size_t maxIterations = 1000 +// output: +// description: +void initModelWithTrain(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, SP_integer numClasses, SP_integer maxIterations) +{ + // convert the Prolog arrays to arma::mat + mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); + + // convert the Prolog arrays to arma::rowvec + Row< size_t > labelsVector = convertArrayToVec(labelsArr, labelsArrSize); + + perceptronGlobal = Perceptron(data, labelsVector, numClasses, maxIterations); +} + +// TODO: +// input: +// output: arma::vec& biases +// description: +void biases(float **biasesArr, SP_integer *biasesArrSize) +{ + // create the ReturnVector + vec biasesReturnVector = perceptronGlobal.Biases(); + + // return the Vector lenght + *biasesArrSize = biasesReturnVector.n_elem; + + // return the Vector as Array + *biasesArr = convertToArray(biasesReturnVector); +} + +// TODO: +// input: const MatType & test, +// arma::Row< size_t > & predictedLabels <- +// output: +// description: +void classify(float *testMatArr, SP_integer testMatSize, SP_integer testMatRowNum, float **predicLabeslsArr, SP_integer *predicLabeslsArrSize) +{ + // convert the Prolog arrays to arma::mat + mat test = convertArrayToMat(testMatArr, testMatSize, testMatRowNum); + + // create the ReturnVector + Row< size_t > predicLabeslsReturnVector; + + perceptronGlobal.Classify(test, predicLabeslsReturnVector); + + // return the Vector lenght + *predicLabeslsArrSize = predicLabeslsReturnVector.n_elem; + + // return the Vector as Array + *predicLabeslsArr = convertToArray(predicLabeslsReturnVector); +} + +// TODO: +// input: const MatType & data, +// const arma::Row< size_t > & labels, +// const size_t numClasses, +// const arma::rowvec & instanceWeights = arma::rowvec() +// output: +// description: +void train(float *dataMatArr, SP_integer dataMatSize, SP_integer dataMatRowNum, float *labelsArr, SP_integer labelsArrSize, SP_integer numClasses, float *instanceWeightsArr, SP_integer instanceWeightsArrSize) +{ + // convert the Prolog arrays to arma::mat + mat data = convertArrayToMat(dataMatArr, dataMatSize, dataMatRowNum); + + // convert the Prolog arrays to arma::rowvec + Row< size_t > labelsVector = convertArrayToVec(labelsArr, labelsArrSize); + + // convert the Prolog arrays to arma::rowvec + rowvec instanceWeightsVector = convertArrayToRowvec(instanceWeightsArr, instanceWeightsArrSize); + + // use the model function + perceptronGlobal.Train(data, labelsVector, numClasses, instanceWeightsVector); +} + +// TODO: +// input: +// output: const arma::mat& weights +// description: +void weights(float **weightsMatArr, SP_integer *weightsMatColNum, SP_integer *weightsMatRowNum) +{ + // create the ReturnMat + mat weightsReturnMat = perceptronGlobal.Weights(); + + // return the Matrix dimensions + *weightsMatColNum = weightsReturnMat.n_cols; + *weightsMatRowNum = weightsReturnMat.n_rows; + + // return the Matrix as one long Array + *weightsMatArr = convertToArray(weightsReturnMat); +} diff --git a/src/methods/perceptron/perceptron.pl b/src/methods/perceptron/perceptron.pl new file mode 100644 index 0000000000000000000000000000000000000000..5e119794091bccfda93b4c004c9a1aafad41bc5a --- /dev/null +++ b/src/methods/perceptron/perceptron.pl @@ -0,0 +1,87 @@ +:- module(perceptron, [ initModelNoTrain/3, + initModelWithTrain/7, + biases/2, + classify/5, + train/8, + weights/3]). + +%% requirements of library(struct) +:- load_files(library(str_decl), + [when(compile_time), if(changed)]). + +%% needed for using the array type +:- use_module(library(structs)). +:- use_module('../../helper_files/helper.pl'). + +%% type definitions for the float array +:- foreign_type + float32 = float_32, + float_array = array(float32). + +%% definitions for the connected function + +%% --Input-- +%% int numClasses => 0, +%% int dimensionality => 0, +%% int maxIterations => 1000 +%% +%% --Output--: +%% --Description-- +foreign(initModelNoTrain, c, initModelNoTrain(+integer, +integer, +integer)). + +%% --Input-- +%% mat data => data(float_array), dataSize, dataRowNum, +%% vec labels => labels(float_array), labelsSize, +%% int numClasses, +%% int maxIterations => 1000 +%% +%% --Output-- +%% --Description-- +foreign(initModelWithTrain, c, initModelWithTrain(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +integer)). + +%% --Input-- +%% +%% --Output-- +%% vec biases => biases(float_array), biasesSize +%% +%% --Description-- +foreign(biases, c, biases(-pointer(float_array), -integer)). + +%% --Input-- +%% mat test => test(float_array), testSize, testRowNum, +%% +%% --Output-- +%% vec predicLabels => predicLabels(float_array), predicLabelsSize +%% +%% --Description-- +foreign(classify, c, classify(+pointer(float_array), +integer, +integer, -pointer(float_array), -integer)). + +%% TODO: +%% --Input-- +%% mat data => data(float_array), dataSize, dataRowNum, +%% vec labels => labels(float_array), labelsSize, +%% int numClasses, +%% vec instWeights => instWeights(float_array), instWeightsSize = arma::rowvec() +%% +%% --Output-- +%% --Description-- +foreign(train, c, train(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +pointer(float_array), +integer)). + +%% --Input-- +%% +%% --Output-- +%% mat weights => weights(float_array), weightsColNum, weightsRowNum, +%% +%% --Description-- +foreign(weights, c, weights(-pointer(float_array), -integer, -integer)). + + +%% Defines the functions that get connected from main.cpp +foreign_resource(perceptron, [ initModelNoTrain, + initModelWithTrain, + biases, + classify, + train, + weights]). + +:- load_foreign_resource(perceptron). \ No newline at end of file diff --git a/src/methods/perceptron/perceptron_test.pl b/src/methods/perceptron/perceptron_test.pl new file mode 100644 index 0000000000000000000000000000000000000000..5562eaee7b879bb400701829fcf6a3ee9cea2339 --- /dev/null +++ b/src/methods/perceptron/perceptron_test.pl @@ -0,0 +1,56 @@ +:- use_module(library(plunit)). + +:- use_module(perceptron). +:- 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