elmTutorial.cpp
Go to the documentation of this file.
1 //headers needed for ELM
4 #include <shark/Models/FFNet.h>
5 #include <shark/Rng/Normal.h>
8 
9 //header needed for the problem
11 
12 //just for evaluation of the ELM
14 #include <iostream>
15 using namespace std;
16 using namespace shark;
17 
18 //In this example an extreme learning machine is constructed and
19 //trained. An ELM is a neural net with one single hidden layer. The
20 //weight of the hidden neurons are random and only the outputs are
21 //trained. This makes the learning problem much easier since the
22 //remaining linear weights form a convex problem. in principle, the
23 //ELM can be constructed using a simple FFNet. But this would mean
24 //that we had to calculate the weight vector for the FFNet - which is
25 //not trivial. Instead we will construct the ELM out of one FFNet and
26 //two linear networks. That's a bit slower but usually not a problem
27 
28 ///Our problem:
29 ///z = sin(x)/x+y+noise
30 /// @cond EXAMPLE_SYMBOLS
31 class Problem:public LabeledDataDistribution<RealVector,RealVector>{
32 public:
33  void draw(RealVector& input, RealVector& label)const
34  {
35  input.resize(2);
36  label.resize(1);
37  input(0) = Rng::uni(-5, 5);
38  input(1) = Rng::uni(-5, 5);
39  if(input(0) != 0)
40  label(0) = sin(input(0)) / input(0) + input(1) + Rng::gauss(0.0, 0.1);
41  else
42  label(0) = 1 + input(1) + Rng::gauss(0.0, 0.1);
43  }
44 };
45 /// @endcond
46 
47 int main(){
48  //change these constants for your own problem
49  size_t hiddenNeurons = 17;
50  size_t numSamples = 1000;
51  unsigned int randomSeed = 42;
52 
53  //configure random number generator
54  Rng::seed(randomSeed);
55 
56  //create the regression problem
57  Problem problem;
58  RegressionDataset data = problem.generateDataset(numSamples);
59  size_t inputDim = inputDimension(data);
60 
61  //usually an elm uses zero mean unit variance inputs. so we should
62  //normalize the data first
63  Normalizer<> normalizer;
64  NormalizeComponentsUnitVariance<> normalizingTrainer(true);
65  normalizingTrainer.train(normalizer,data.inputs());
66 
67  // now we construct the hidden layer of the elm
68  // we create a two layer network and initialize it randomly. By keeping the random
69  // hidden weights and only learning the visible later, we will create the elm
71  elmNetwork.setStructure(inputDim,hiddenNeurons,labelDimension(data));
72  initRandomNormal(elmNetwork,1);
73 
74  //We need to train the linear part. in this simple example we use the elm standard
75  //technique: linear regression. For this we need to propagate the data first
76  // through the normalization and the hidden layer of the elm
77  RegressionDataset transformedData = transformInputs(data,normalizer);
78  transformedData.inputs() = elmNetwork.evalLayer(0,transformedData.inputs());
79  LinearModel<> elmOutput;
80  LinearRegression trainer;
81  trainer.train(elmOutput,transformedData);
82 
83  //we need to set the learned weights of the hidden layer of the elm
84  elmNetwork.setLayer(1,elmOutput.matrix(),elmOutput.offset());
85 
86 
87  ConcatenatedModel<RealVector,RealVector> elm = normalizer >> elmNetwork;
88  //to test whether everything works, we will evaluate the elm and the elmOutput layer separately
89  //both results should be identical
90  SquaredLoss<> loss;
91  double outputResult = loss(transformedData.labels(),elmOutput(transformedData.inputs()));
92  double elmResult = loss(transformedData.labels(),elm(data.inputs()));
93 
94  cout<<"Results"<<std::endl;
95  cout<<"============"<<std::endl;
96  cout<<"output Layer: "<< outputResult<<std::endl;
97  cout<<"ELM: "<< elmResult<<std::endl;
98 }