diff --git a/SCsub b/SCsub index 97209a3..e662ce7 100644 --- a/SCsub +++ b/SCsub @@ -61,6 +61,7 @@ sources = [ "mlpp/probit_reg/probit_reg_old.cpp", "mlpp/svc/svc_old.cpp", "mlpp/softmax_reg/softmax_reg_old.cpp", + "mlpp/auto_encoder/auto_encoder_old.cpp", "test/mlpp_tests.cpp", ] diff --git a/mlpp/auto_encoder/auto_encoder_old.cpp b/mlpp/auto_encoder/auto_encoder_old.cpp new file mode 100644 index 0000000..2db06e8 --- /dev/null +++ b/mlpp/auto_encoder/auto_encoder_old.cpp @@ -0,0 +1,265 @@ +// +// AutoEncoder.cpp +// +// Created by Marc Melikyan on 11/4/20. +// + +#include "auto_encoder_old.h" + +#include "../activation/activation.h" +#include "../cost/cost.h" +#include "../lin_alg/lin_alg.h" +#include "../utilities/utilities.h" + +#include +#include + +std::vector> MLPPAutoEncoderOld::modelSetTest(std::vector> X) { + return Evaluate(X); +} + +std::vector MLPPAutoEncoderOld::modelTest(std::vector x) { + return Evaluate(x); +} + +void MLPPAutoEncoderOld::gradientDescent(real_t learning_rate, int max_epoch, bool UI) { + MLPPActivation avn; + MLPPLinAlg alg; + real_t cost_prev = 0; + int epoch = 1; + forwardPass(); + + while (true) { + cost_prev = Cost(y_hat, inputSet); + + // Calculating the errors + std::vector> error = alg.subtraction(y_hat, inputSet); + + // Calculating the weight/bias gradients for layer 2 + std::vector> D2_1 = alg.matmult(alg.transpose(a2), error); + + // weights and bias updation for layer 2 + weights2 = alg.subtraction(weights2, alg.scalarMultiply(learning_rate / n, D2_1)); + + // Calculating the bias gradients for layer 2 + bias2 = alg.subtractMatrixRows(bias2, alg.scalarMultiply(learning_rate, error)); + + //Calculating the weight/bias for layer 1 + + std::vector> D1_1 = alg.matmult(error, alg.transpose(weights2)); + + std::vector> D1_2 = alg.hadamard_product(D1_1, avn.sigmoid(z2, 1)); + + std::vector> D1_3 = alg.matmult(alg.transpose(inputSet), D1_2); + + // weight an bias updation for layer 1 + weights1 = alg.subtraction(weights1, alg.scalarMultiply(learning_rate / n, D1_3)); + + bias1 = alg.subtractMatrixRows(bias1, alg.scalarMultiply(learning_rate / n, D1_2)); + + forwardPass(); + + // UI PORTION + if (UI) { + MLPPUtilities::CostInfo(epoch, cost_prev, Cost(y_hat, inputSet)); + std::cout << "Layer 1:" << std::endl; + MLPPUtilities::UI(weights1, bias1); + std::cout << "Layer 2:" << std::endl; + MLPPUtilities::UI(weights2, bias2); + } + epoch++; + + if (epoch > max_epoch) { + break; + } + } +} + +void MLPPAutoEncoderOld::SGD(real_t learning_rate, int max_epoch, bool UI) { + MLPPActivation avn; + MLPPLinAlg alg; + real_t cost_prev = 0; + int epoch = 1; + + while (true) { + std::random_device rd; + std::default_random_engine generator(rd()); + std::uniform_int_distribution distribution(0, int(n - 1)); + int outputIndex = distribution(generator); + + std::vector y_hat = Evaluate(inputSet[outputIndex]); + auto prop_res = propagate(inputSet[outputIndex]); + auto z2 = std::get<0>(prop_res); + auto a2 = std::get<1>(prop_res); + + cost_prev = Cost({ y_hat }, { inputSet[outputIndex] }); + std::vector error = alg.subtraction(y_hat, inputSet[outputIndex]); + + // Weight updation for layer 2 + std::vector> D2_1 = alg.outerProduct(error, a2); + weights2 = alg.subtraction(weights2, alg.scalarMultiply(learning_rate, alg.transpose(D2_1))); + + // Bias updation for layer 2 + bias2 = alg.subtraction(bias2, alg.scalarMultiply(learning_rate, error)); + + // Weight updation for layer 1 + std::vector D1_1 = alg.mat_vec_mult(weights2, error); + std::vector D1_2 = alg.hadamard_product(D1_1, avn.sigmoid(z2, 1)); + std::vector> D1_3 = alg.outerProduct(inputSet[outputIndex], D1_2); + + weights1 = alg.subtraction(weights1, alg.scalarMultiply(learning_rate, D1_3)); + // Bias updation for layer 1 + + bias1 = alg.subtraction(bias1, alg.scalarMultiply(learning_rate, D1_2)); + + y_hat = Evaluate(inputSet[outputIndex]); + if (UI) { + MLPPUtilities::CostInfo(epoch, cost_prev, Cost({ y_hat }, { inputSet[outputIndex] })); + std::cout << "Layer 1:" << std::endl; + MLPPUtilities::UI(weights1, bias1); + std::cout << "Layer 2:" << std::endl; + MLPPUtilities::UI(weights2, bias2); + } + epoch++; + + if (epoch > max_epoch) { + break; + } + } + forwardPass(); +} + +void MLPPAutoEncoderOld::MBGD(real_t learning_rate, int max_epoch, int mini_batch_size, bool UI) { + MLPPActivation avn; + MLPPLinAlg alg; + real_t cost_prev = 0; + int epoch = 1; + + // Creating the mini-batches + int n_mini_batch = n / mini_batch_size; + std::vector>> inputMiniBatches = MLPPUtilities::createMiniBatches(inputSet, n_mini_batch); + + while (true) { + for (int i = 0; i < n_mini_batch; i++) { + std::vector> y_hat = Evaluate(inputMiniBatches[i]); + + auto prop_res = propagate(inputMiniBatches[i]); + auto z2 = std::get<0>(prop_res); + auto a2 = std::get<1>(prop_res); + + cost_prev = Cost(y_hat, inputMiniBatches[i]); + + // Calculating the errors + std::vector> error = alg.subtraction(y_hat, inputMiniBatches[i]); + + // Calculating the weight/bias gradients for layer 2 + + std::vector> D2_1 = alg.matmult(alg.transpose(a2), error); + + // weights and bias updation for layer 2 + weights2 = alg.subtraction(weights2, alg.scalarMultiply(learning_rate / inputMiniBatches[i].size(), D2_1)); + + // Bias Updation for layer 2 + bias2 = alg.subtractMatrixRows(bias2, alg.scalarMultiply(learning_rate, error)); + + //Calculating the weight/bias for layer 1 + + std::vector> D1_1 = alg.matmult(error, alg.transpose(weights2)); + + std::vector> D1_2 = alg.hadamard_product(D1_1, avn.sigmoid(z2, 1)); + + std::vector> D1_3 = alg.matmult(alg.transpose(inputMiniBatches[i]), D1_2); + + // weight an bias updation for layer 1 + weights1 = alg.subtraction(weights1, alg.scalarMultiply(learning_rate / inputMiniBatches[i].size(), D1_3)); + + bias1 = alg.subtractMatrixRows(bias1, alg.scalarMultiply(learning_rate / inputMiniBatches[i].size(), D1_2)); + + y_hat = Evaluate(inputMiniBatches[i]); + + if (UI) { + MLPPUtilities::CostInfo(epoch, cost_prev, Cost(y_hat, inputMiniBatches[i])); + std::cout << "Layer 1:" << std::endl; + MLPPUtilities::UI(weights1, bias1); + std::cout << "Layer 2:" << std::endl; + MLPPUtilities::UI(weights2, bias2); + } + } + epoch++; + if (epoch > max_epoch) { + break; + } + } + forwardPass(); +} + +real_t MLPPAutoEncoderOld::score() { + MLPPUtilities util; + return util.performance(y_hat, inputSet); +} + +void MLPPAutoEncoderOld::save(std::string fileName) { + MLPPUtilities util; + util.saveParameters(fileName, weights1, bias1, 0, 1); + util.saveParameters(fileName, weights2, bias2, 1, 2); +} + +MLPPAutoEncoderOld::MLPPAutoEncoderOld(std::vector> pinputSet, int pn_hidden) { + inputSet = pinputSet; + n_hidden = pn_hidden; + n = inputSet.size(); + k = inputSet[0].size(); + + MLPPActivation avn; + y_hat.resize(inputSet.size()); + + weights1 = MLPPUtilities::weightInitialization(k, n_hidden); + weights2 = MLPPUtilities::weightInitialization(n_hidden, k); + bias1 = MLPPUtilities::biasInitialization(n_hidden); + bias2 = MLPPUtilities::biasInitialization(k); +} + +real_t MLPPAutoEncoderOld::Cost(std::vector> y_hat, std::vector> y) { + class MLPPCost cost; + return cost.MSE(y_hat, inputSet); +} + +std::vector> MLPPAutoEncoderOld::Evaluate(std::vector> X) { + MLPPLinAlg alg; + MLPPActivation avn; + std::vector> z2 = alg.mat_vec_add(alg.matmult(X, weights1), bias1); + std::vector> a2 = avn.sigmoid(z2); + return alg.mat_vec_add(alg.matmult(a2, weights2), bias2); +} + +std::tuple>, std::vector>> MLPPAutoEncoderOld::propagate(std::vector> X) { + MLPPLinAlg alg; + MLPPActivation avn; + std::vector> z2 = alg.mat_vec_add(alg.matmult(X, weights1), bias1); + std::vector> a2 = avn.sigmoid(z2); + return { z2, a2 }; +} + +std::vector MLPPAutoEncoderOld::Evaluate(std::vector x) { + MLPPLinAlg alg; + MLPPActivation avn; + std::vector z2 = alg.addition(alg.mat_vec_mult(alg.transpose(weights1), x), bias1); + std::vector a2 = avn.sigmoid(z2); + return alg.addition(alg.mat_vec_mult(alg.transpose(weights2), a2), bias2); +} + +std::tuple, std::vector> MLPPAutoEncoderOld::propagate(std::vector x) { + MLPPLinAlg alg; + MLPPActivation avn; + std::vector z2 = alg.addition(alg.mat_vec_mult(alg.transpose(weights1), x), bias1); + std::vector a2 = avn.sigmoid(z2); + return { z2, a2 }; +} + +void MLPPAutoEncoderOld::forwardPass() { + MLPPLinAlg alg; + MLPPActivation avn; + z2 = alg.mat_vec_add(alg.matmult(inputSet, weights1), bias1); + a2 = avn.sigmoid(z2); + y_hat = alg.mat_vec_add(alg.matmult(a2, weights2), bias2); +} diff --git a/mlpp/auto_encoder/auto_encoder_old.h b/mlpp/auto_encoder/auto_encoder_old.h new file mode 100644 index 0000000..adb6bf4 --- /dev/null +++ b/mlpp/auto_encoder/auto_encoder_old.h @@ -0,0 +1,58 @@ + +#ifndef MLPP_AUTO_ENCODER_OLD_H +#define MLPP_AUTO_ENCODER_OLD_H + +// +// AutoEncoder.hpp +// +// Created by Marc Melikyan on 11/4/20. +// + +#include "core/math/math_defs.h" + +#include +#include +#include + +class MLPPAutoEncoderOld { +public: + std::vector> modelSetTest(std::vector> X); + std::vector modelTest(std::vector x); + + void gradientDescent(real_t learning_rate, int max_epoch, bool UI = false); + void SGD(real_t learning_rate, int max_epoch, bool UI = false); + void MBGD(real_t learning_rate, int max_epoch, int mini_batch_size, bool UI = false); + + real_t score(); + + void save(std::string fileName); + + MLPPAutoEncoderOld(std::vector> inputSet, int n_hidden); + +private: + real_t Cost(std::vector> y_hat, std::vector> y); + + std::vector> Evaluate(std::vector> X); + std::tuple>, std::vector>> propagate(std::vector> X); + std::vector Evaluate(std::vector x); + std::tuple, std::vector> propagate(std::vector x); + void forwardPass(); + + std::vector> inputSet; + std::vector> y_hat; + + std::vector> weights1; + std::vector> weights2; + + std::vector bias1; + std::vector bias2; + + std::vector> z2; + std::vector> a2; + + int n; + int k; + int n_hidden; +}; + +#endif /* AutoEncoder_hpp */ diff --git a/test/mlpp_tests.cpp b/test/mlpp_tests.cpp index 6ba3a08..30dbd4b 100644 --- a/test/mlpp_tests.cpp +++ b/test/mlpp_tests.cpp @@ -47,6 +47,7 @@ #include "../mlpp/uni_lin_reg/uni_lin_reg.h" #include "../mlpp/wgan/wgan.h" +#include "../mlpp/auto_encoder/auto_encoder_old.h" #include "../mlpp/mlp/mlp_old.h" #include "../mlpp/outlier_finder/outlier_finder_old.h" #include "../mlpp/pca/pca_old.h" @@ -495,12 +496,13 @@ void MLPPTests::test_soft_max_network(bool ui) { void MLPPTests::test_autoencoder(bool ui) { MLPPLinAlg alg; - // AUTOENCODER std::vector> inputSet = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, { 3, 5, 9, 12, 15, 18, 21, 24, 27, 30 } }; - MLPPAutoEncoder model(alg.transpose(inputSet), 5); - model.SGD(0.001, 300000, ui); - alg.printMatrix(model.modelSetTest(alg.transpose(inputSet))); - std::cout << "ACCURACY: " << 100 * model.score() << "%" << std::endl; + + // AUTOENCODER + MLPPAutoEncoderOld model_old(alg.transpose(inputSet), 5); + model_old.SGD(0.001, 300000, ui); + alg.printMatrix(model_old.modelSetTest(alg.transpose(inputSet))); + std::cout << "ACCURACY (Old): " << 100 * model_old.score() << "%" << std::endl; } void MLPPTests::test_dynamically_sized_ann(bool ui) { MLPPLinAlg alg;