DenoisingAutoEncoderãå®è£ ãã¦ã¿ã(C++)
çããããã«ã¡ã¯
ãå
æ°ã§ãããç§ã¯å
æ°ã§ãã
ãã¦ãä»æ¥ã¯AutoEncoderã®ä¸ç¨®ã§ããDenoisingAutoEncoderãå®è£
ãã¦ã¿ã¾ããã
ublasã®æ©è½ã¨è£å©æ©è½ã©ã¤ãã©ãªã使ã£ã¦ã¾ããä½ã£ãã®ã¯ããã®ã§ãããã¶ã£ã¡ãããã¡ã¤ã«å¤ãã¦å°ã£ã¦ãã¾ãã
çè«ã¯ãã¡ããåèã«ããã¦é ãã¾ããã
Denoising Autoencodersにおける確率的勾配降下法(数式の導出) - Yusuke Sugomori's Blog
ã¨ãããã¨ã§ã½ã¼ã¹ã³ã¼ãã¨ããããã¨ãããªã®ã§ãããè¨è¿°éãåã¾ããã®ã§æå¾ã«æ²è¼ãã¾ãã
åºæ¬çã«ãã©ã¡ã¼ã¿ãDenoisingAutoEncoderã®ã³ã³ã¹ãã©ã¯ã¿ã«ã»ãããã¦ãfitã使ã£ã¦å¦ç¿ãè¡ãã¾ãã
ééããªã©ããããããªã®ã§ãããè¦ã¤ãã£ãããé£çµ¡ãã¦ãã ããã¾ãã
ç身ã®ã³ã¼ããä¸å¿è¼ãã¦ãããâ¦èå³ãæã人ã¯ç¶ããèªãããã
以ä¸ã®ã½ã¼ã¹ã³ã¼ããããªã«åå²ããªãã¦ããããªãï¼ã¨æã£ã¦ãã人ã¯æ²¢å±±ããã£ãããã¨æãã¾ããã
ä»å¾æ¡å¼µãã¦ããæ¹éãªã®ã§ãããã¦ãããªå½¢ã§ããã¦ãã¾ãããã£ã¨æ¡å¼µããã¤ããã§ãã
ã½ã¼ã¹ã³ã¼ããã覧ããã ããã¨ãããã¨æãã¾ããè¦é£ãã§ããå¤ågithubã«ããã¾ãã
注æäºé
Dataset.cpp
é©å½ã§ãããã ãã é©å½ã§ãã
test.cpp
ãã¡ã¤ã«ãã¹ã¯èªåã®ã使ã£ã¦ãã ããã
ä»ã¯é©å½ã«èªåã®ãã¹ï¼ç§ã®ï¼ãè¨å®ãã¦ãã¾ãã
çåç¹
CrossEntropy誤差é¢æ°ã®é¨å 1-1ããæ¥ããnanã¨ã©ã¼ãé£çºãããã®ã§ããããã解決æ¹æ³ãªãã§ããããâ¦ã
ï¼ä»ç¡çï¼0.00001ã¨ããã£ã¦ãã®ã§â¦ï¼å¼ã¯ãã£ã¦ãããããªæ°ã¯ãããã ãã©ãªã
ç°¡åãªè§£èª¬
DenoisingAutoEncoderã®åä½ã®ä¸»ä½ã¯
DenoisingAutoEncoderã®æã¤fitã¡ã³ãé¢æ°ã§ãã
forã«ã¼ãå
ã§è¡ã£ã¦ãããã¨ã¯ãªã³ã³ã¹ãã©ã¯ãã¾ã§ãå®è¡ãããããå
ã«ãã¦
ãã©ã¡ã¼ã¿ã®æ´æ°ãè¡ã£ã¦ãã¾ãã
ã¤ã¾ãããªã³ã³ã¹ãã©ã¯ãâå¾®åâæ´æ°ãã²ãããç¹°ãè¿ã
ã¯ã£ãããã£ã¦ã³ã¬ä»¥å¤è¦ãå¿ è¦ããªããããªâ¦ã
void DenoisingAutoEncoder::fit(const ublas::matrix<double> &train_input,const ublas::matrix<double> &train_label,double learning_rate,int training_time){ ublas::matrix<double> x(train_input); for(int i = 0; i < training_time; i++){ cout << i << "åç®" << endl; ublas::matrix<double> tilde_x = corruption_input(x, 0.3); ublas::matrix<double> y = hidden_value(tilde_x); ublas::matrix<double> z = reconstractMatrix(y); //ãªã³ã³ã¹ãã©ã¯ãå´ã®ã®ãã¤ã¢ã¹ã®å¾®å ublas::matrix<double> h_bias_grad = x - z; //é ã層ãã¤ã¢ã¹å¾®å ublas::scalar_matrix<double> s_matrix(y.size1(),y.size2(),1.0); ublas::matrix<double> right = s_matrix - y; ublas::matrix<double> a = prod(h_bias_grad, weight); ublas::matrix<double> left = ublas_func::multiMatrixElement(a,y); ublas::matrix<double> bias_grad = ublas_func::multiMatrixElement(left, right); //weightã®å¾®å ublas::matrix<double> matrix_grad_1 = prod(trans(tilde_x),bias_grad); ublas::matrix<double> matrix_grad_2 = prod(trans(h_bias_grad),y); ublas::matrix<double> matrix_grad = matrix_grad_1 + matrix_grad_2; //ãã©ã¡ã¼ã¿ã®æ´æ° h_bias += learning_rate * ublas_func::mean_by_column(h_bias_grad); bias += learning_rate * ublas_func::mean_by_column(bias_grad); weight += learning_rate * matrix_grad; CrossEntropy *ce = new CrossEntropy(); cout << "誤差" << ce->execute(x,z) << endl; } }
ã¯ã©ã¹é層表
ç°¡åãªè§£èª¬ï¼ã¯ã©ã¹ã®ï¼
Function:sigmoidãsoftmaxã®æ´»æ§åé¢æ°(ActiveFunction)ã®å®è£
ãCrossEntropyãªã©ã®å®è£
ãè¡ãLossFunction
Layer:é ã層ã®å®è£
ãæ³å®
Dataset:Mnistã®ãã¼ã¿è§£æ
UblasLibrary:便å©å±
Util:Ublas以å¤ã®ä¾¿å©å±
ã½ã¼ã¹ã³ã¼ã
ActiveFunction.hpp
#include <iostream> #include "Function.hpp" #include "UblasLibrary.hpp" #define NDEBUG enum ActiveFunctionType{ Sigmoid, Softmax }; class ActiveFunction:public Function{ public: virtual ublas::matrix<double> execute(const ublas::matrix<double> &ublas_object) = 0; }; class SigmoidFunction:public ActiveFunction{ public: virtual ublas::matrix<double> execute(const ublas::matrix<double> &ublas_object); }; class SoftmaxFunction:public ActiveFunction{ public: virtual ublas::matrix<double> execute(const ublas::matrix<double> &ublas_object); }; class ActiveFunctionFuctory{ public: ActiveFunction* create(int number); };
ActiveFunction.cpp
#include <iostream> #include "ActiveFunction.hpp" ublas::matrix<double> SigmoidFunction::execute(const ublas::matrix<double> &ublas_object){ return ublas_func::sigmoid(ublas_object); } ublas::matrix<double> SoftmaxFunction::execute(const ublas::matrix<double> &ublas_object){ return ublas_func::softmax(ublas_object); } ActiveFunction* ActiveFunctionFuctory::create(int number){ if(Sigmoid == number){ return new SigmoidFunction(); } else{ return new SoftmaxFunction(); } }
Layer.hpp
#pragma once #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/io.hpp> #include <boost/numeric/ublas/triangular.hpp> #include <boost/numeric/ublas/lu.hpp> #include <time.h> #include "UblasLibrary.hpp" #include "ActiveFunction.hpp" #include "LossFunction.hpp" #define NDEBUG using namespace boost::numeric; using namespace std; class Layer{ public: Layer(int input_n,int input_l); protected: ublas::matrix<double> weight; ublas::vector<double> bias; //é ã層ã¸ã®ãã¤ã¢ã¹ ublas::matrix<double> hidden_value(const ublas::matrix<double> &train_input); };
Layer.cpp
#include "Layer.hpp" Layer::Layer(const int input_n,const int input_l){ //æã¿åæåå¦ç //å ¥åãã¯ãã«ã»å±¤æ° cout << input_n << " " << input_l << endl; double a = -4 * sqrt(6. / (input_n + input_l)); //cout << a << endl; weight = ublas_func::generateMatrixRandom(input_n,input_l,-4 * sqrt(6. / (input_n + input_l)),4 * sqrt(6. / (input_n + input_l))); bias = ublas_func::generateVectorScalar(input_l, 0.0); } ublas::matrix<double> Layer::hidden_value(const ublas::matrix<double> &train_input){ ActiveFunctionFuctory *acf = new ActiveFunctionFuctory(); ActiveFunction *af = acf->create(0); ublas::matrix<double> result = prod(train_input,weight); ublas::matrix<double> result2 = ublas_func::sumMatrixAndVector(result,bias); return af->execute(result2); }
AutoEncoder.hpp
#pragma once #include "Layer.hpp" #define NDEBUG class AutoEncoder:public Layer{ public: AutoEncoder(int input_n,int input_l); };
LossFunction.hpp
#include "Function.hpp" #define NDEBUG using namespace std; class LossFunction:public Function{ public: virtual double execute(ublas::matrix<double> &t,ublas::matrix<double> &y) = 0; }; class CrossEntropy:public LossFunction{ public: double execute(ublas::matrix<double> &t,ublas::matrix<double> &y); };
LossFunction.cpp
#include "LossFunction.hpp" double CrossEntropy::execute(ublas::matrix<double> &t,ublas::matrix<double> &y){ ublas::scalar_matrix<double> one_matrix(t.size1(),t.size2(),1.0001); ublas::scalar_matrix<double> double_one_matrix(t.size1(),t.size2(),0.0001); ublas::matrix<double> one_matrix_minus_t = one_matrix - t; ublas::matrix<double> one_matrix_minus_y = one_matrix - y; ublas::matrix<double> log_one_matrix_minus_y = ublas_func::log(one_matrix_minus_y); ublas::matrix<double> up_y = y + double_one_matrix; ublas::matrix<double> left_value = ublas_func::multiMatrixElement(t,ublas_func::log(up_y)); ublas::matrix<double> right_value = ublas_func::multiMatrixElementCheck(one_matrix_minus_t,log_one_matrix_minus_y); ublas::matrix<double> result = left_value + right_value; ublas::vector<double> total_vect = ublas_func::sum_by_rows(result); double result_number = - (sum(total_vect) / total_vect.size()); return result_number; }
DenoisingAutoEncoder.hpp
#pragma once #include "AutoEncoder.hpp" #define NDEBUG using namespace boost::numeric; class DenoisingAutoEncoder: public AutoEncoder{ public: ublas::vector<double> h_bias; //é ã層ãã¤ã¢ã¹ DenoisingAutoEncoder(int input_n,int input_l); ublas::matrix<double> corruption_input(const ublas::matrix<double> input,const double corruption_per); ublas::matrix<double> reconstractMatrix(const ublas::matrix<double> &input); void fit(const ublas::matrix<double> &train_input,double learning_rate,int training_time); ublas::matrix<double> reconstract(const ublas::matrix<double> &test_input); };
DenoisingAutoEncoder.cpp
#include "DenoisingAutoEncoder.hpp" DenoisingAutoEncoder::DenoisingAutoEncoder(int input_n,int input_l):AutoEncoder(input_n,input_l){ h_bias = ublas_func::generateVectorScalar(input_n, 0.0); } //å ¥åãã¼ã¿ãæ¬ æããã ublas::matrix<double> DenoisingAutoEncoder::corruption_input(const ublas::matrix<double> input,const double corruption_per){ ublas::matrix<double> corrupted_matrix(input); for(int i = 0; i < corrupted_matrix.size1(); i++){ for(int j = 0; j < corrupted_matrix.size2(); j++){ double d = (double)rand() / RAND_MAX; if(d < corruption_per){ corrupted_matrix(i,j) = 0.0; } } } return corrupted_matrix; } ublas::matrix<double> DenoisingAutoEncoder::reconstractMatrix(const ublas::matrix<double> &input){ ActiveFunctionFuctory *acf = new ActiveFunctionFuctory(); ActiveFunction *af = acf->create(0); ublas::matrix<double> result = prod(input,trans(weight)); ublas::matrix<double> result2 = ublas_func::sumMatrixAndVector(result,h_bias); return af->execute(result2); } void DenoisingAutoEncoder::fit(const ublas::matrix<double> &train_input,double learning_rate,int training_time){ ublas::matrix<double> x(train_input); for(int i = 0; i < training_time; i++){ clock_t start = clock(); cout << i << "åç®" << endl; ublas::matrix<double> tilde_x = corruption_input(x, 0.3); ublas::matrix<double> y = hidden_value(tilde_x,0); ublas::matrix<double> z = reconstractMatrix(y); //ããããã¨ããã¨ã®ãã¤ã¢ã¹ã®å¾®å ublas::matrix<double> h_bias_grad = x - z; //é ããããã¤ã¢ã¹å¾®å ublas::scalar_matrix<double> s_matrix(y.size1(),y.size2(),1.0); ublas::matrix<double> right = s_matrix - y; ublas::matrix<double> a = prod(h_bias_grad, weight); ublas::matrix<double> left = ublas_func::multiMatrixElement(a,y); ublas::matrix<double> bias_grad = ublas_func::multiMatrixElement(left, right); ublas::matrix<double> matrix_grad_1 = prod(trans(tilde_x),bias_grad); ublas::matrix<double> matrix_grad_2 = prod(trans(h_bias_grad),y); ublas::matrix<double> matrix_grad = matrix_grad_1 + matrix_grad_2; //ãã©ã¡ã¼ã¿ã®æ´æ° h_bias += learning_rate * ublas_func::mean_by_column(h_bias_grad); bias += learning_rate * ublas_func::mean_by_column(bias_grad); weight += learning_rate * matrix_grad; clock_t loss_calc_start = clock(); CrossEntropy *ce = new CrossEntropy(); cout << "誤差" << ce->execute(x,z) << endl; //cout << "誤差è¨ç®æé " << (clock() - loss_calc_start) / CLOCKS_PER_SEC << endl; } } ublas::matrix<double> DenoisingAutoEncoder::reconstract(const ublas::matrix<double> &test_input){ ublas::matrix<double> y = hidden_value(test_input,0); ublas::matrix<double> z = reconstractMatrix(y); return z; }
UblasLibrary.hpp
#pragma once #include <iostream> #include <vector> #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/io.hpp> #include <boost/numeric/ublas/triangular.hpp> // ä¸è§è¡åç¨ã®ãããï¼åé²æ¶å»ï¼å¾éä»£å ¥ã«å¿ è¦ #include <boost/numeric/ublas/lu.hpp> // LUå解ï¼åé²æ¶å»ï¼å¾éä»£å ¥ç¨ã®ããã #include "Util.hpp" #define NDEBUG using namespace boost::numeric; namespace ublas_func{ /** åè¦ç´ ä¸ã¤ä¸ã¤ã«å¯¾ãã¦ãé©ç¨ãã é¢æ°ã§ãã */ class Function{ protected: double number; //çªå· public: virtual double calc(const double element) = 0; void setNumber(const double num){ number = num; } }; class AbsFunction:public Function{ public: virtual double calc(const double element){ return std::abs(element); } }; class LogFunction:public Function{ public: virtual double calc(const double element){ double result = std::log(element); return result; } }; class Log10Function:public Function{ public: virtual double calc(const double element){ return std::log10(element); } }; class SqrtFunction:public Function{ public: virtual double calc(const double element){ return std::sqrt(element); } }; class PowerFunction:public Function{ public: virtual double calc(const double element){ return std::pow(element, number); } }; class ExpFunction:public Function{ public: virtual double calc(const double element){ return std::exp(element); } }; class SigmoidFunction:public Function{ public: virtual double calc(const double element){ return 1.0 / (1.0 + exp(-element)); } }; class SoftmaxFunction{ public: boost::numeric::ublas::vector<double> calc(const boost::numeric::ublas::vector<double> &ublas_vector){ double maximum = 0.0; for(int i = 0; i < ublas_vector.size(); i++){ if(ublas_vector[i] > maximum){ maximum = ublas_vector[i]; } } double total = 0.0; for(int i = 0; i < ublas_vector.size(); i++){ total += exp(ublas_vector[i] - maximum); } boost::numeric::ublas::vector<double> result(ublas_vector.size()); for(int i = 0; i < ublas_vector.size(); i++){ result[i] = exp(ublas_vector[i] - maximum) / total; } return result; } }; /** é¢æ°ãä½ã */ template<typename T> BOOST_UBLAS_INLINE T abs(const T &ublas_class){ Function *fc= new AbsFunction(); T copy; apply_function_to_element(ublas_class,copy,fc); return copy; } template<typename T> BOOST_UBLAS_INLINE T log(const T &ublas_class){ Function *fc = new LogFunction(); T copy; apply_function_to_element(ublas_class,copy,fc); return copy; } template<typename T> BOOST_UBLAS_INLINE T log10(const T &ublas_class){ Function *fc = new Log10Function(); T copy; apply_function_to_element(ublas_class, copy, fc); return copy; } template<typename T> BOOST_UBLAS_INLINE T sqrt(const T &ublas_class){ Function *fc = new SqrtFunction(); T copy; apply_function_to_element(ublas_class,copy, fc); return copy; } template<typename T> BOOST_UBLAS_INLINE T pow(const T &ublas_class,double number){ Function *fc = new PowerFunction(); fc->setNumber(number); T copy; apply_function_to_element(ublas_class,copy, fc); return copy; } template<typename T> BOOST_UBLAS_INLINE T exp(const T &ublas_class){ Function *fc = new ExpFunction(); T copy; apply_function_to_element(ublas_class, copy,fc); return copy; } template<typename T> BOOST_UBLAS_INLINE T sigmoid(const T &ublas_class){ Function *fc = new SigmoidFunction(); T copy; apply_function_to_element(ublas_class, copy,fc); return copy; } template<typename T> boost::numeric::ublas::matrix<T> softmax(const boost::numeric::ublas::matrix<T> &ublas_class){ boost::numeric::ublas::matrix<double> result(ublas_class.size1(),ublas_class.size2()); SoftmaxFunction sf; for(int i = 0; i < result.size1(); i++){ row(result,i) = sf.calc(row(ublas_class,i)); } return result; } /** vectorå ¨ã¦ã«é©ç¨ */ template<typename T> void apply_function_to_element(const boost::numeric::ublas::vector<T> &ublas_vector,boost::numeric::ublas::vector<T> &result_vector,Function *fc){ int size = ublas_vector.size(); boost::numeric::ublas::vector<T> result(size); for(int i = 0; i < size; i++){ result[i] = fc->calc(ublas_vector[i]); } } /** matrixå ¨ã¦ã«é©ç¨ */ template<typename T,typename T2> void apply_function_to_element(const boost::numeric::ublas::matrix<T> &ublas_matrix,boost::numeric::ublas::matrix<T2> &result_matrix,Function *fc){ result_matrix.resize(ublas_matrix.size1(),ublas_matrix.size2()); for(int i = 0; i < ublas_matrix.size1(); i++){ for(int j = 0; j < ublas_matrix.size2(); j++){ result_matrix(i,j) = fc->calc(ublas_matrix(i,j)); } } } template<typename T,typename T2> boost::numeric::ublas::matrix<T> multiMatrixElement(const boost::numeric::ublas::matrix<T> &ublas_matrix1,const boost::numeric::ublas::matrix<T2> &ublas_matrix2){ boost::numeric::ublas::matrix<T> result(ublas_matrix1.size1(),ublas_matrix1.size2()); for(int i = 0; i < ublas_matrix1.size1(); i++){ for(int j = 0; j < ublas_matrix2.size2(); j++){ result(i,j) = ublas_matrix1(i,j) * ublas_matrix2(i,j); } } return result; } template<typename T,typename T2> boost::numeric::ublas::matrix<T> multiMatrixElementCheck(const boost::numeric::ublas::matrix<T> &ublas_matrix1,const boost::numeric::ublas::matrix<T2> &ublas_matrix2){ boost::numeric::ublas::matrix<T> result(ublas_matrix1.size1(),ublas_matrix1.size2()); for(int i = 0; i < ublas_matrix1.size1(); i++){ for(int j = 0; j < ublas_matrix2.size2(); j++){ result(i,j) = ublas_matrix1(i,j) * ublas_matrix2(i,j); if(std::isnan(result(i,j))){ cout << result(i,j) << " " << ublas_matrix1(i,j) << " " << ublas_matrix2(i,j) << endl; } if(std::isinf(result(i,j))){ cout << result(i,j) << " " << ublas_matrix1(i,j) << " " << ublas_matrix2(i,j) << endl; } } } return result; } /** *ãããã以ä¸ã¯ *éè¦ãããªé¢æ°ã並ã¹ã¦ãã¾ããï¼éè¡åã¨ãï¼ */ /** éè¡å */ template<typename T> boost::numeric::ublas::matrix<T> inverse(const boost::numeric::ublas::matrix<T> &ublas_matrix){ boost::numeric::ublas::matrix<T> copy_matrix(ublas_matrix); boost::numeric::ublas::permutation_matrix<> pm(ublas_matrix.size1()); lu_factorize(copy_matrix,pm); boost::numeric::ublas::identity_matrix<double> iden_mat(ublas_matrix.size1()); lu_substitute(copy_matrix,pm,iden_mat); return iden_mat; } /** è¡åå¼ */ template<typename T> double determinant(const boost::numeric::ublas::matrix<T> &ublas_matrix){ boost::numeric::ublas::matrix<T> copy_matrix(ublas_matrix); boost::numeric::ublas::permutation_matrix<> pm(ublas_matrix.size1()); lu_factorize(copy_matrix,pm); double det = 1.0; for(int i = 0; i < pm.size(); i++){ if(pm(i) != i){ det *= -1.0; } det *= copy_matrix(i,i); } return det; } /** æ¬ä¼¼éè¡å */ template<typename T> boost::numeric::ublas::matrix<T> psudo(const boost::numeric::ublas::matrix<T> &ublas_matrix){ return prod(inverse(prod(trace(ublas_matrix),ublas_matrix)),ublas_matrix); } /** ãããã以ä¸ã¯ãåãã¨è¡ãã¨ã«å®è¡ããããã°ã©ã ã§ãã Ex:åãã¨ã«å¹³åãåã£ããã¯ãã«ãè¿ãã */ class FunctionPerVector{ public: virtual double calc(const boost::numeric::ublas::vector<double> &ublas_vector) = 0; }; class MeanFunctionPerVector : public FunctionPerVector{ public: virtual double calc(const boost::numeric::ublas::vector<double> &ublas_vector){ return sum(ublas_vector) / (double)ublas_vector.size(); }; }; class SumFunctionPerVector : public FunctionPerVector{ public: virtual double calc(const boost::numeric::ublas::vector<double> &ublas_vector){ return sum(ublas_vector); }; }; /** çµ±è¨ axisã¯åãè¡ã 0:è¡ 1:åã*/ template<typename T> void apply_to_function_per_vector(const boost::numeric::ublas::matrix<T> &ublas_matrix,boost::numeric::ublas::vector<T> &result_vector,FunctionPerVector *fcpv,int axis){ if (axis == 0){ int n_rows = ublas_matrix.size1(); result_vector.resize(n_rows); for(int i = 0; i < n_rows; i++){ double r = fcpv->calc(row(ublas_matrix,i)); result_vector[i] = r; } }else{ int n_cols = ublas_matrix.size2(); result_vector.resize(n_cols); for(int i = 0; i < n_cols; i++){ double r = fcpv->calc(column(ublas_matrix,i)); result_vector[i] = r; } } } template<typename T> boost::numeric::ublas::vector<T> mean_by_rows(boost::numeric::ublas::matrix<T> &ublas_matrix){ FunctionPerVector *fcpv = new MeanFunctionPerVector(); boost::numeric::ublas::vector<T> copy; apply_to_function_per_vector(ublas_matrix, copy,fcpv, 0); return copy; } template<typename T> boost::numeric::ublas::vector<T> mean_by_column(boost::numeric::ublas::matrix<T> &ublas_matrix){ FunctionPerVector *fcpv = new MeanFunctionPerVector(); boost::numeric::ublas::vector<T> copy; apply_to_function_per_vector(ublas_matrix, copy,fcpv, 1); return copy; } template<typename T> boost::numeric::ublas::vector<T> sum_by_rows(boost::numeric::ublas::matrix<T> &ublas_matrix){ FunctionPerVector *fcpv = new SumFunctionPerVector(); boost::numeric::ublas::vector<T> copy; apply_to_function_per_vector(ublas_matrix, copy,fcpv, 0); return copy; } template<typename T> boost::numeric::ublas::vector<T> sum_by_column(boost::numeric::ublas::matrix<T> &ublas_matrix){ FunctionPerVector *fcpv = new SumFunctionPerVector(); boost::numeric::ublas::vector<T> copy; apply_to_function_per_vector(ublas_matrix,copy ,fcpv, 1); return copy; } /** ãã¾ãã¾ã¨ããè¨ç® */ template<typename T> boost::numeric::ublas::matrix<T> sumMatrixAndVector(const boost::numeric::ublas::matrix<T> &ublas_matrix,const boost::numeric::ublas::vector<T> &ublas_vector){ boost::numeric::ublas::matrix<T> result(ublas_matrix); int n_rows = ublas_matrix.size1(); for(int i = 0; i < n_rows; i++){ row(result,i) += ublas_vector; } return result; } /** 以ä¸ã¨ã©ã¼ãªã©ã®ãã§ã㯠*/ template<typename T> bool checkSquareMatrix(boost::numeric::ublas::matrix<T> &ublas_matrix){ if(ublas_matrix.size1() == ublas_matrix.size2()){ return true; }else{ std::cout << "æ£æ¹è¡åã§ã¯ããã¾ããã" << std::endl; return false; } } template<typename T> bool checkVectorSize(const boost::numeric::ublas::vector<T> &ublas_vect1,const boost::numeric::ublas::vector<T> &ublas_vect2){ if(ublas_vect1.size() == ublas_vect2){ return true; }else{ std::cout << "ãã¯ãã«ã®é·ããä¸è´ãã¦ãã¾ãã" << std::endl; return false; } } /** std::vectorâublas::vectorã¸ã®convert */ template<typename T> boost::numeric::ublas::vector<T> convertToUblasVector(const std::vector<T> &vect1){ ublas::vector<T> ublas_vect(vect1.size()); for(int i = 0; i < vect1.size(); i++){ ublas_vect[i] = vect1[i]; } return ublas_vect; } template<typename T> boost::numeric::ublas::matrix<T> convertToUblasMatrix(const std::vector<std::vector<T> > &vect1){ boost::numeric::ublas::matrix<double> ublas_matrix(vect1.size(),vect1[0].size()); for(int i = 0; i < vect1.size(); i++){ for(int j = 0; j < vect1[i].size(); j++){ ublas_matrix(i,j) = vect1[i][j]; } } return ublas_matrix; } /** -1 ~ 1ã¾ã§ã§ä½æããmatrixã*/ static boost::numeric::ublas::matrix<double> generateMatrixRandom(int n_row, int n_col,double min = -1.0,double max = 1.0){ boost::numeric::ublas::matrix<double> result(n_row,n_col); for(int i = 0; i < n_row; i++){ for(int j = 0; j < n_col; j++){ result(i,j) = rand_area(min, max); } } return result; } /** -1 ~ 1ã¾ã§ã§ä½æããvectorã*/ static boost::numeric::ublas::vector<double> generateVectorRandom(int size,double min = 1,double max = 0){ boost::numeric::ublas::vector<double> result(size); for(int i = 0; i < result.size(); i++){ result[i] = (double)rand() / (RAND_MAX * 20.0); } return result; } /** scalarçãªmatrix */ static boost::numeric::ublas::matrix<double> generateMatrixScalar(int n_row, int n_col,double number){ boost::numeric::ublas::matrix<double> result(n_row,n_col); for(int i = 0; i < n_row; i++){ for(int j = 0; j < n_col; j++){ result(i,j) = number; } } return result; } template<typename T> static boost::numeric::ublas::vector<T> generateVectorScalar(int size,T num){ boost::numeric::ublas::vector<T> result(size); for(int i = 0; i < result.size(); i++){ result[i] = num; } return result; } template<typename T> int maxIndex(boost::numeric::ublas::vector<T> &ublas_vector){ int maximumIndex = 0.0; double maximum = 0.0; for(int i = 0; i < ublas_vector.size(); i++){ if(ublas_vector[i] > maximum){ maximumIndex = i; } } return maximumIndex; } /** åºå */ template<typename T> void outputSize(boost::numeric::ublas::matrix<T> &ublas_matrix){ std::cout << ublas_matrix.size1() << " " << ublas_matrix.size2() << std::endl; } //Vectorã«Matrixãæ··ãã£ã¦ãããã©ãã template<typename T> bool isNanMatrix(boost::numeric::ublas::matrix<T> &ublas_matrix){ for(int i = 0; i < ublas_matrix.size1(); i++){ for(int j = 0; j < ublas_matrix.size2(); j++){ if(std::isnan(ublas_matrix(i,j)) == true){ return true; } } } return false; } //Matrixã«infãæ··ãã£ã¦ããã template<typename T> bool isInfMatrix(boost::numeric::ublas::matrix<T> &ublas_matrix){ for(int i = 0; i < ublas_matrix.size1(); i++){ for(int j = 0; j < ublas_matrix.size2(); j++){ if(std::isinf(ublas_matrix(i,j)) == true){ return true; } } } return false; } //Vectorã«nanãæ··ãã£ã¦ããã template<typename T> bool isNanVector(boost::numeric::ublas::vector<T> &ublas_vector){ for(int i = 0; i < ublas_vector.size(); i++){ if(std::isnan(ublas_vector[i]) == true){ return true; } } return false; } };
Util.hpp
#include <iostream> #include <math.h> #include <random> using namespace std; extern double rand_area(double min,double max);
Util.cpp
#include "Util.hpp" double rand_area(double min,double max){ random_device rd; mt19937 gen(rd()); std::uniform_real_distribution<double> dis(min, max); return dis(gen); }
test.cpp(mainé¢æ°)
#include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/io.hpp> #include <boost/numeric/ublas/lu.hpp> #include <boost/numeric/ublas/triangular.hpp> #include "DenoisingAutoEncoder.hpp" #include "UblasLibrary.hpp" #define NDEBUG using namespace boost::numeric; using namespace std; vector<vector<double> > generateTestData(int data_size,int data_length){ vector<vector<double> > result; for(int i = 0; i < data_size; i++){ vector<double> vect; double number = 0.0; for(int j = 0; j < data_length; j++){ if(j % (i + 1) == 0){ if(number == 0.0){ number = 1.0; }else{ number = 0.0; } } vect.push_back(number); } result.push_back(vect); } return result; } void testDenoisingAutoEncoder(){ int data_length = 60; int data_size = 30; vector<vector<double> > vect_data = generateTestData(data_size, data_length); ublas::matrix<double> input_matrix = ublas_func::convertToUblasMatrix(vect_data); DenoisingAutoEncoder da(data_length,30); da.fit(input_matrix, label_matrix, 0.1, 100); ublas::matrix<double> output = da.reconstract(input_matrix); for(int i = 0; i < data_size; i++){ cout << "å ¥å" << endl; cout << row(input_matrix,i) << endl; cout << "復å " << endl; cout << row(output,i) << endl; } } int main (void) { //testLogistic(); testDenoisingAutoEncoder(); //testStackedDenoisingAutoEncoder(); //testUblas(); }
Makefile
CXX = g++ CFLAGS = -O3 -Wall CXXFLAGS = -O3 -Wall SOURCE := $(shell ls *.cpp) HEADER := $(shell ls *.hpp) OBJS := $(SOURCE:.cpp=.o) TARGET = test all: clean $(TARGET) $(TARGET):$(OBJS) $(CXX) -o $@ $(OBJS) .c.o: $(CC) $(CFLAGS) -c $^ .cpp.o: $(CXX) $(CXXFLAGS) -c $^ clean: rm -f *.o