DenoisingAutoencoderTutorial.cpp
Go to the documentation of this file.
1 
2 #include <shark/Data/Pgm.h> //for exporting the learned filters
3 #include <shark/Data/SparseData.h>//for reading in the images as sparseData/Libsvm format
4 #include <shark/Models/Autoencoder.h>//normal autoencoder model
5 #include <shark/Models/TiedAutoencoder.h>//autoencoder with tied weights
6 #include <shark/Models/ConcatenatedModel.h>//to concatenate the noise with the model
8 #include <shark/Algorithms/GradientDescent/Rprop.h>// the Rprop optimization algorithm
9 #include <shark/ObjectiveFunctions/Loss/SquaredLoss.h> // squared loss used for regression
10 #include <shark/ObjectiveFunctions/Regularizer.h> //L2 regulariziation
11 
12 using namespace std;
13 using namespace shark;
14 
15 
16 /// \brief Model which corrupts the data by setting random inputs to 0
17 ///
18 /// Note that the model is not differentiable as we do not implement any of the required interface
19 class NoiseModel : public AbstractModel<RealVector,RealVector>
20 {
21 private:
22  double m_prob;//probability to corrupt the inċuts
23 public:
24 
25  NoiseModel(double prob)
26  : m_prob(prob){}
27 
28  /// \brief every model has a name
29  std::string name() const
30  { return "NoiseModel"; }
31 
32 
33  //The model does not have parameters, so the methods for setting and getting parameters are trivial
34  RealVector parameterVector() const{
35  return RealVector();
36  }
37  void setParameterVector(RealVector const& newParameters){}
38  size_t numberOfParameters() const{
39  return 0;
40  }
41 
42  /// \brief Add noise to the input
43  void eval(BatchInputType const& inputs, BatchOutputType& outputs, State& state)const{
44  //state is unused because we do not need to compute derivatives
45  //We only need to implement the batch version as the rest can be inferred from this one.
46  //beware that eval can be called in parallel from several threads each using a single rng
48  outputs = inputs;
49  for(std::size_t i = 0; i != outputs.size1(); ++i){
50  for(std::size_t j = 0; j != outputs.size2(); ++j){
52  outputs(i,j) = 0.0;
53  }
54  }
55  }
56  }
57  }
58 };
59 
60 //training of an auto encoder with one hidden layer
61 template<class AutoencoderModel>
63  UnlabeledData<RealVector> const& data,//the data to train with
64  std::size_t numHidden,//number of features in the autoencoder
65  std::size_t iterations, //number of iterations to optimize
66  double regularisation,//strength of the regularisation
67  double noiseStrength // strength of the added noise
68 ){
69  //create the model
70  std::size_t inputs = dataDimension(data);
71  AutoencoderModel baseModel;
72  baseModel.setStructure(inputs, numHidden);
73  initRandomUniform(baseModel,-0.1*std::sqrt(1.0/inputs),0.1*std::sqrt(1.0/inputs));
74  NoiseModel noise(noiseStrength);//set an input pixel with probability p to 0
75  ConcatenatedModel<RealVector,RealVector> model = noise>> baseModel;
76  //we have not implemented the derivatives of the noise model which turns the
77  //whole composite model to be not differentiable. we fix this by not optimizing the noise model
78  model.enableModelOptimization(0,false);
79  //create the objective function
80  LabeledData<RealVector,RealVector> trainSet(data,data);//labels identical to inputs
82  ErrorFunction error(trainSet, &model, &loss);
83  TwoNormRegularizer regularizer(error.numberOfVariables());
84  error.setRegularizer(regularisation,&regularizer);
85  //set up optimizer
86  IRpropPlusFull optimizer;
87  error.init();
88  optimizer.init(error);
89  std::cout<<"Optimizing model: "+model.name()<<std::endl;
90  for(std::size_t i = 0; i != iterations; ++i){
91  optimizer.step(error);
92  std::cout<<i<<" "<<optimizer.solution().value<<std::endl;
93  }
94  model.setParameterVector(optimizer.solution().point);
95  return baseModel;
96 }
97 int main(int argc, char **argv)
98 {
99  if(argc < 2) {
100  cerr << "usage: " << argv[0] << " path/to/mnist_subset.libsvm" << endl;
101  return 1;
102  }
103  std::size_t numHidden = 200;
104  std::size_t iterations = 200;
105  double regularisation = 0.01;
106  double noiseStrengt = 0.5;
107 
109  importSparseData( train, argv[1] );
110 
111  std::size_t numElems = train.numberOfElements();
112  for(std::size_t i = 0; i != numElems; ++i){
113  for(std::size_t j = 0; j != 784; ++j){
114  if(train.element(i).input(j) > 0.5){
115  train.element(i).input(j) = 1;
116  }else{
117  train.element(i).input(j) = 0;
118  }
119  }
120  }
121 
122  typedef Autoencoder<LogisticNeuron, LogisticNeuron> Autoencoder1;
123  typedef TiedAutoencoder<LogisticNeuron, LogisticNeuron> Autoencoder2;
124 
125  Autoencoder1 net1 = trainAutoencoderModel<Autoencoder1>(train.inputs(),numHidden,iterations,regularisation,noiseStrengt);
126  Autoencoder2 net2 = trainAutoencoderModel<Autoencoder2>(train.inputs(),numHidden,iterations,regularisation,noiseStrengt);
127 
128  exportFiltersToPGMGrid("features1",net1.encoderMatrix(),28,28);
129  exportFiltersToPGMGrid("features2",net2.encoderMatrix(),28,28);
130 }