mi024

College project "Projet IAD" master 1
git clone https://esimon.eu/repos/mi024.git
Log | Files | Refs | README

model.cpp (4539B)


      1 #include <ctime>
      2 #include <cstddef>
      3 #include <string>
      4 #include <stdexcept>
      5 
      6 #include <boost/version.hpp>
      7 #include <boost/shared_ptr.hpp>
      8 #include <boost/make_shared.hpp>
      9 #include <boost/random/linear_congruential.hpp>
     10 #include <nmlp/Criterion.h>
     11 #include <nmlp/Matrix.h>
     12 #include <nmlp/Tensor.h>
     13 
     14 #include "data_set.hpp"
     15 #include "factory.hpp"
     16 #include "model.hpp"
     17 #include "view.hpp"
     18 
     19 #if BOOST_VERSION < 104700
     20 	#define uniform_int_distribution uniform_int
     21 	#include <boost/random/uniform_int.hpp>
     22 #else
     23 	#include <boost/random/uniform_int_distribution.hpp>
     24 #endif
     25 
     26 bool Model::add_view(boost::shared_ptr<View> v){
     27 	if(views.count(v->kind))
     28 		return false;
     29 	if(!views.empty() && views.begin()->second->concept_dimension!=v->concept_dimension)
     30 		throw std::runtime_error("Trying to aggregate views of different concept space dimensions in a single model.");
     31 	views.insert(std::make_pair(v->kind, v));
     32 	return true;
     33 }
     34 
     35 void Model::stochastic_learn(Data_set const &data_set, std::size_t number_of_step, float gradient_step, std::string const &criterion){
     36 	static boost::minstd_rand gen(std::time(0));
     37 	boost::uniform_int_distribution<> view_dist(0, data_set.number_of_views()-1);
     38 	boost::uniform_int_distribution<> data_dist(0, data_set.size()-1);
     39 
     40 	std::vector<boost::shared_ptr<View> > view_vector(data_set.number_of_views());
     41 	for(std::size_t i=0; i<data_set.number_of_views(); ++i){
     42 		std::string kind=data_set.kind(i);
     43 		std::map<std::string, boost::shared_ptr<View> >::iterator it=views.find(kind);
     44 		if(it==views.end())
     45 			throw std::runtime_error("Training a model with an unknown view.");
     46 		view_vector[i]=it->second;
     47 	}
     48 
     49 	std::vector<boost::shared_ptr<Criterion> > criteria(data_set.number_of_views());
     50 	for(std::size_t i=0; i<data_set.number_of_views(); ++i)
     51 		criteria[i]=criterion_factory(criterion, view_vector[i]->view_dimension);
     52 
     53 	boost::shared_ptr<Tensor> input=boost::make_shared<Tensor>(1), output=boost::make_shared<Tensor>(1);
     54 	/// @todo Optimise
     55 	for(std::size_t step=0; step<number_of_step*data_set.size(); ++step){
     56 		std::size_t element=data_dist(gen);
     57 		std::size_t from_id=view_dist(gen), to_id=view_dist(gen);
     58 
     59 		boost::shared_ptr<View> from=view_vector[from_id], to=view_vector[to_id];
     60 		input->setMatrix(0, data_set.get(element, from_id));
     61 		output->setMatrix(0, data_set.get(element, to_id));
     62 
     63 		SequentialModule trainer;
     64 		trainer.addModule(from->encoder);
     65 		trainer.addModule(to->decoder);
     66 		trainer.init_gradient();
     67 		trainer.forward(input);
     68 		criteria[to_id]->backward(trainer.getOutput(), output);
     69 		trainer.backward(input, criteria[to_id]->getDelta());
     70 		trainer.updateParameters(gradient_step);
     71 	}
     72 }
     73 
     74 double Model::error(Data_set const &data_set, std::string const &criterion, std::size_t from_view, std::size_t to_view) const {
     75 	// nmlp is const-inconsistent
     76 	Model *ncthis=const_cast<Model*>(this);
     77 
     78 	std::vector<boost::shared_ptr<View> > view_vector(data_set.number_of_views());
     79 	for(std::size_t i=0; i<data_set.number_of_views(); ++i){
     80 		std::string kind=data_set.kind(i);
     81 		std::map<std::string, boost::shared_ptr<View> >::const_iterator it=views.find(kind);
     82 		if(it==views.end())
     83 			throw std::runtime_error("Training a model with an unknown view.");
     84 		view_vector[i]=it->second;
     85 	}
     86 
     87 	std::vector<boost::shared_ptr<Criterion> > criteria(data_set.number_of_views());
     88 	for(std::size_t i=0; i<data_set.number_of_views(); ++i)
     89 		criteria[i]=criterion_factory(criterion, view_vector[i]->view_dimension);
     90 
     91 	std::map<std::string, boost::shared_ptr<View> >::const_iterator it;
     92 	it=views.find(data_set.kind(from_view));
     93 	if(it==views.end())
     94 		throw std::runtime_error("Testing a model with an unknown view.");
     95 	boost::shared_ptr<View> from=it->second;
     96 	it=views.find(data_set.kind(to_view));
     97 	if(it==views.end())
     98 		throw std::runtime_error("Testing a model with an unknown view.");
     99 	boost::shared_ptr<View> to=it->second;
    100 
    101 	boost::shared_ptr<Tensor> input=boost::make_shared<Tensor>(data_set.get(from_view));
    102 	boost::shared_ptr<Tensor> output=boost::make_shared<Tensor>(data_set.get(to_view));
    103 	boost::shared_ptr<Criterion> criter=criterion_factory(criterion, to->view_dimension);
    104 
    105 	SequentialModule tester;
    106 	tester.addModule(from->encoder);
    107 	tester.addModule(to->decoder);
    108 	tester.init_gradient();
    109 	tester.forward(input);
    110 	criter->computeValue(tester.getOutput(), output);
    111 	boost::shared_ptr<Tensor> diff=criter->getValue();
    112 
    113 	float err=0;
    114 	for(int i=0; i<diff->getMatrix(0)->getNumberOfRows(); ++i)
    115 		err+=diff->getMatrix(0)->getValue(i,0);
    116 	err/=diff->getMatrix(0)->getNumberOfRows();
    117 
    118 	return err;
    119 }
    120