diff --git a/Makefile b/Makefile index c30870e721d02aabad080811182b0f98ad4485af..715305665b3ff981ea3e351cc3ca0d30fc3973ce 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,8 @@ SPLFR_PATH=/usr/local/sicstus4.7.1/bin/splfr all: make -C src/methods/bayesian_linear_regression splfr=$(SPLFR_PATH) + make -C src/methods/linear_regression splfr=$(SPLFR_PATH) clean: - make -C src/methods/bayesian_linear_regression clean \ No newline at end of file + make -C src/methods/bayesian_linear_regression clean + make -C src/methods/linear_regression clean diff --git a/src/methods/linear_regression/linear_regression.cpp b/src/methods/linear_regression/linear_regression.cpp index 57a231b8430c0b972ac57ce65818317a9a48e0eb..7dd7bbd2b2f6d9a2e4b7787baff6af1df5ee36a4 100644 --- a/src/methods/linear_regression/linear_regression.cpp +++ b/src/methods/linear_regression/linear_regression.cpp @@ -17,61 +17,116 @@ using namespace mlpack::regression; // Global Variable of the LinearRegression object so it can be accessed from all functions LinearRegression regressor; -// input: const bool , const bool , const size_t , const double -// output: double -void initModel(SP_integer centerData, SP_integer scaleData, SP_integer nIterMax, double tol) +// input: const arma::mat &data, const arma::rowvec &responses, const double lambda, const bool intercept +// output: +void initModel(float *matrix, SP_integer matSize, SP_integer matRowNum, float *responses_arr, SP_integer vecSize, SP_integer lambda, SP_integer bool_intercept) { - regressor = new LinearRegression((centerData == 1), (scaleData == 1), nIterMax, tol); + if(matSize / matRowNum != vecSize) + { + cout << "Target dim doesnt fit to the Data dim" << endl; + return; + } + // convert the Prolog arrays to arma::rowvec and arma::mat + mat data = convertArrayToMat(matrix, matSize, matRowNum); + rowvec responses = convertArrayToRowvec(responses_arr, vecSize); + + regressor = LinearRegression(data, responses, lambda, bool_intercept); +} + +// input: const arma::mat &data, const arma::rowvec &responses, const arma::rowvec &weights, const double lambda, const bool intercept +// output: +void initModelWithWeights(float *matrix, SP_integer matSize, SP_integer matRowNum, float *responses_arr, SP_integer vecSize, float *weights_arr, SP_integer weightsSize, SP_integer lambda, SP_integer bool_intercept) +{ + if(matSize / matRowNum != vecSize) + { + cout << "Target dim doesnt fit to the Data dim" << endl; + return; + } + // convert the Prolog arrays to arma::rowvec and arma::mat + mat data = convertArrayToMat(matrix, matSize, matRowNum); + rowvec responses = convertArrayToRowvec(responses_arr, vecSize); + rowvec weights = convertArrayToRowvec(weights_arr, weightsSize); + + regressor = LinearRegression(data, responses, weights, lambda, bool_intercept); } // input: -// output: double -SP_integer alpha() +// output: +void initModelEmpty(SP_integer) +{ + regressor = LinearRegression(); +} + +// input: const arma::mat &points, const arma::rowvec &responses +// output: double L2SquardError +SP_integer computeError(float *points_mat_arr, SP_integer matSize, SP_integer matRowNum, float *responses_arr, SP_integer vecSize) { - return regressor.Alpha(); + if(matSize / matRowNum != vecSize) + { + cout << "Target dim doesnt fit to the Data dim" << endl; + return 0; + } + // convert the Prolog arrays to arma::rowvec and arma::mat + mat data = convertArrayToMat(points_mat_arr, matSize, matRowNum); + rowvec responses = convertArrayToRowvec(responses_arr, vecSize); + + // run the model function + return regressor.ComputeError(data, responses); } // input: // output: double -SP_integer beta() +SP_integer intercept() { - return regressor.Beta(); + if(regressor.Intercept()) {return 1;} + else {return 0;} } // input: -// output: const arma::colvec & -float * dataOffset(SP_integer *arraySize) +// output: double Tikhonov regularization parameter +SP_integer lambda() { - // save the DataOffset output in colvec - colvec armaDataOffset = regressor.DataOffset(); - - *arraySize = armaDataOffset.n_elem; + return regressor.Lambda();; +} - return convertArmaToArray(armaDataOffset); +// input: double new Tikhonov regularization parameter +// output: +void modifyLambda(SP_integer new_lambda) +{ + double& lambda_ref = regressor.Lambda(); + lambda_ref = new_lambda; } + // input: -// output: const arma::colvec & -float * dataScale(SP_integer *arraySize) +// output: const arma::vec & parameters b vector +float * parameters(SP_integer *arraySize) { - // save the DataScale output in colvec - colvec armaDataScale = regressor.DataScale(); + // get b vector + colvec armaDataOffset = regressor.Parameters(); + + cout << regressor.Parameters() << endl; + cout << armaDataOffset << endl; - *arraySize = armaDataScale.n_elem; + // set the b vector length + *arraySize = armaDataOffset.n_elem; - return convertArmaToArray(armaDataScale); + // convert b vector to array and return + return convertArmaToArray(armaDataOffset); } -// input: -// output: const arma::colvec & -float * omega(SP_integer *arraySize) +// input: arma::vec & new b vector +// output: +void modifyParameters(float *paramArr, SP_integer paramSize) { - // save the Omega output in colvec - colvec armaOmega = regressor.Omega(); + // convert array to arma:: vec + rowvec new_B_Vector = convertArrayToRowvec(paramArr, paramSize); - *arraySize = armaOmega.n_elem; + // get parameter b vector ref + vec& bVector = regressor.Parameters(); - return convertArmaToArray(armaOmega); + // set new b vector + bVector = new_B_Vector; } // input: const arma::mat &points, arma::rowvec &predictions @@ -92,104 +147,37 @@ void predict(float *pointsArr, SP_integer pointsSize, SP_integer pointsRowNum, f *predicArr = convertArmaToArray(predictions); } -// input: const arma::mat &points, arma::rowvec &predictions, arma::rowvec &std +// input: const arma::mat &data, const arma::rowvec &responses, const bool intercept // output: -void predictWithStd(float *pointsArr, SP_integer pointsSize, SP_integer pointsRowNum, float **predicArr, SP_integer *predicSize, float **stdArr, SP_integer *stdSize) -{ - // convert the Prolog arrays to std::vec for easy conversion to arma::mat - mat data = convertArrayToMat(pointsArr, pointsSize, pointsRowNum); - - // run the prediction and save the results in arma::rowvecs - rowvec predictions; - rowvec std; - regressor.Predict(data, predictions, std); - - // give back the sizes and the converted results as arrays - *predicSize = predictions.n_elem; - *stdSize = std.n_elem; - - *predicArr = convertArmaToArray(predictions); - *stdArr = convertArmaToArray(std); -} - - -// input: -// output: double -SP_integer responsesOffset() -{ - return regressor.ResponsesOffset(); -} - -// input: const arma::mat &data, const arma::rowvec &responses -// output: double -SP_integer rmse(float *matrix, SP_integer matSize, SP_integer matRowNum, float *arr, SP_integer vecSize) +SP_integer train(float *matrix, SP_integer matSize, SP_integer matRowNum, float *responses_arr, SP_integer vecSize, SP_integer bool_intercept) { + if(matSize / matRowNum != vecSize) + { + cout << "Target dim doesnt fit to the Data dim" << endl; + return 0; + } // convert the Prolog arrays to arma::rowvec and arma::mat - rowvec responses = convertArrayToRowvec(arr, vecSize); + rowvec responses = convertArrayToRowvec(responses_arr, vecSize); mat data = convertArrayToMat(matrix, matSize, matRowNum); - // run the model function and return the error - return regressor.RMSE(data, responses); + // run the model train function + return regressor.Train(data, responses, (bool_intercept == 1)); } -// input: const arma::mat &data, const arma::rowvec &responses +// input: const arma::mat &data, const arma::rowvec &responses, const arma::rowvec &weights, const bool intercept // output: -void train(float *matrix, SP_integer matSize, SP_integer matRowNum, float *arr, SP_integer vecSize) +SP_integer trainWithWeights(float *matrix, SP_integer matSize, SP_integer matRowNum, float *responses_arr, SP_integer vecSize, float *weights_arr, SP_integer weightsSize, SP_integer bool_intercept) { if(matSize / matRowNum != vecSize) { cout << "Target dim doesnt fit to the Data dim" << endl; - return; + return 0; } // convert the Prolog arrays to arma::rowvec and arma::mat - rowvec responses = convertArrayToRowvec(arr, vecSize); mat data = convertArrayToMat(matrix, matSize, matRowNum); + rowvec responses = convertArrayToRowvec(responses_arr, vecSize); + rowvec weights = convertArrayToRowvec(weights_arr, weightsSize); - // run the model function - regressor.Train(data, responses); -} - -// input: -// output: double -SP_integer variance() -{ - return regressor.Variance(); -} - -/* -void testing() -{ - // load the iris data - mat dataset; - bool loaded = mlpack::data::Load("iris.csv", dataset); - - // split the data into train and test - mat trainData = dataset.cols(1, 4); - trainData.shed_row(trainData.n_rows - 1); - rowvec trainTarget = trainData.row(trainData.n_rows - 1); - trainData.shed_row(trainData.n_rows - 1); - - mat testData = dataset.col(dataset.n_cols - 1); - testData.shed_row(testData.n_rows - 1); - rowvec testTarget = testData.row(testData.n_rows - 1); - testData.shed_row(testData.n_rows - 1); - - - // init the bayesian linear regressor model - - - // train the model - regressor.Train(trainData, trainTarget); - - // predict with the test data - rowvec prediction; - regressor.Predict(testData, prediction); - - - // compare test target and prediction - cout << "Train Data: " << trainData << endl; - cout << "Train Target: " << trainTarget << endl; - cout << "Alpha" << alpha() << endl; - cout << "Beta" << beta() << endl; + // run the model train function + return regressor.Train(data, responses, weights, (bool_intercept == 1)); } -*/ diff --git a/src/methods/linear_regression/linear_regression.pl b/src/methods/linear_regression/linear_regression.pl index dc54a17cc826c691afe03cc232b7420c04269c5f..a62fbb480b1646ecb498fa40875477d1f3f6936a 100644 --- a/src/methods/linear_regression/linear_regression.pl +++ b/src/methods/linear_regression/linear_regression.pl @@ -1,4 +1,4 @@ -:- module(linear_regression, [initModel/4, alpha/1, beta/1, dataOffset/2, dataScale/2, omega/2, predict/5, predictWithStd/7, rmse/6, train/5, variance/1]). +:- module(linear_regression, [initModel/7, initModelWithWeights/9, initModelEmpty/1, computeError/6, intercept/1, lambda/1, modifyLambda/1, parameters/2, modifyParameters/2, predict/5, train/7, trainWithWeights/9]). :- load_files(library(str_decl), [when(compile_time), if(changed)]). @@ -13,37 +13,21 @@ float_array = array(float32). %% definitions for the connected function and what there inputs and output arguments are -foreign(initModel, c, initModel(+integer, +integer, +integer, +float32)). -foreign(alpha, c, alpha([-integer])). -foreign(beta, c, beta([-integer])). -foreign(dataOffset, c, dataOffset(-integer, [-pointer(float_array)])). -foreign(dataScale, c, dataScale(-integer, [-pointer(float_array)])). -foreign(omega, c, omega(-integer, [-pointer(float_array)])). +foreign(initModel, c, initModel(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, +integer)). +foreign(initModelWithWeights, c, initModelWithWeights(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +pointer(float_array), +integer, +integer, +integer)). +foreign(initModelEmpty, c, initModelEmpty(+integer)). +foreign(computeError, c, computeError(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, [-integer])). +foreign(intercept, c, intercept([-integer])). +foreign(lambda, c, lambda([-integer])). +foreign(modifyLambda, c, modifyLambda(+integer)). +foreign(parameters, c, parameters([-pointer(float_array)], -integer)). +foreign(modifyParameters, c, modifyParameters(+pointer(float_array), +integer)). foreign(predict, c, predict(+pointer(float_array), +integer, +integer, -pointer(float_array), -integer)). -foreign(predictWithStd, c, predictWithStd(+pointer(float_array), +integer, +integer, -pointer(float_array), -integer, -pointer(float_array), -integer)). -foreign(rmse, c, rmse(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, [-integer])). -foreign(train, c, train(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer)). -foreign(variance, c, variance([-integer])). - -%% Defines what functions should be connected from main.cpp -foreign_resource(linear_regression, [initModel, alpha, beta, dataOffset, dataScale, omega, predict, predictWithStd, rmse, train, variance]). - -:- load_foreign_resource(linear_regression). +foreign(train, c, train(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +integer, [-integer])). +foreign(trainWithWeights, c, trainWithWeights(+pointer(float_array), +integer, +integer, +pointer(float_array), +integer, +pointer(float_array), +integer, +integer, [-integer])). +%% Defines what functions should be connected from main.cpp +foreign_resource(linear_regression, [initModel, initModelWithWeights, initModelEmpty, computeError, intercept, lambda, modifyLambda, parameters, modifyParameters, predict, train, trainWithWeights]). -%% Some funktions that use the new Method - -%% First trains the model and then tries to predict the targets and the std for the given data -predict(PredictList, StdList) :- - train, - 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)), - predictWithStd(X, Xsize,Xrownum, Predic, PredicSize, Std, StdSize), - convert_float_array_to_list(Predic, PredicSize, PredictList), - convert_float_array_to_list(Std, StdSize, StdList). - -%% Trains the model with the given data and targets -train :- - 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). +:- load_foreign_resource(linear_regression). \ No newline at end of file diff --git a/src/methods/linear_regression/test.pl b/src/methods/linear_regression/test.pl index be28fdc62705f334fc01360bf380f50207333277..8223f1c9929e95e63f5f1d8c4660d102b64e3be6 100644 --- a/src/methods/linear_regression/test.pl +++ b/src/methods/linear_regression/test.pl @@ -4,53 +4,49 @@ :- use_module('../../helper_files/helper.pl'). reset_Model :- - initModel(1,0,50,0.0001). + initModelEmpty(1). :- 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). + train(X,Xsize, Xrownum,Y, Ysize,1 ,0). 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). + train(X,Xsize, Xrownum,Y, Ysize, 1, 0). 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). + train(X,Xsize, Xrownum,Y, Ysize, 1, 0). 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). + train(X,Xsize, Xrownum,Y, Ysize, 1, 0). 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). + train(X,Xsize, Xrownum,Y, Ysize, 1, 0). 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). + train(X,Xsize, Xrownum,Y, Ysize, 1, 0). + +test(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, 1, 0), + 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