CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ProcMLP.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: MVAComputer
4 // Class : ProcMLP
5 //
6 
7 // Implementation:
8 // An evaluator for a feed-forward neural net (multi-layer perceptron).
9 // Each layer has (n + 1) x m weights for n input neurons, 1 bias
10 // and m neurons. Also each layer can select between linear and logistic
11 // activation function. The output from the last layer is returned.
12 //
13 // Author: Christophe Saout
14 // Created: Sat Apr 24 15:18 CEST 2007
15 // $Id: ProcMLP.cc,v 1.4 2009/06/03 09:50:14 saout Exp $
16 //
17 
18 #include <stdlib.h>
19 #include <algorithm>
20 #include <iterator>
21 #include <vector>
22 #include <cmath>
23 
25 
28 
29 using namespace PhysicsTools;
30 
31 namespace { // anonymous
32 
33 class ProcMLP : public VarProcessor {
34  public:
35  typedef VarProcessor::Registry::Registry<ProcMLP,
37 
38  ProcMLP(const char *name,
40  const MVAComputer *computer);
41  virtual ~ProcMLP() {}
42 
43  virtual void configure(ConfIterator iter, unsigned int n);
44  virtual void eval(ValueIterator iter, unsigned int n) const;
45  virtual std::vector<double> deriv(
46  ValueIterator iter, unsigned int n) const;
47 
48  private:
49  struct Layer {
50  Layer(const Calibration::ProcMLP::Layer &calib);
51  Layer(const Layer &orig) :
52  inputs(orig.inputs), neurons(orig.neurons),
53  coeffs(orig.coeffs), sigmoid(orig.sigmoid) {}
54 
55  unsigned int inputs;
56  unsigned int neurons;
57  std::vector<double> coeffs;
58  bool sigmoid;
59  };
60 
61  std::vector<Layer> layers;
62  unsigned int maxTmp;
63 };
64 
65 static ProcMLP::Registry registry("ProcMLP");
66 
67 ProcMLP::Layer::Layer(const Calibration::ProcMLP::Layer &calib) :
68  inputs(calib.first.front().second.size()),
69  neurons(calib.first.size()),
70  sigmoid(calib.second)
71 {
72  typedef Calibration::ProcMLP::Neuron Neuron;
73 
74  coeffs.resize(neurons * (inputs + 1));
75  std::vector<double>::iterator inserter = coeffs.begin();
76 
77  for(std::vector<Neuron>::const_iterator iter = calib.first.begin();
78  iter != calib.first.end(); iter++) {
79  *inserter++ = iter->first;
80 
81  if (iter->second.size() != inputs)
82  throw cms::Exception("ProcMLPInput")
83  << "ProcMLP neuron layer inconsistent."
84  << std::endl;
85 
86  inserter = std::copy(iter->second.begin(), iter->second.end(),
87  inserter);
88  }
89 }
90 
91 ProcMLP::ProcMLP(const char *name,
92  const Calibration::ProcMLP *calib,
93  const MVAComputer *computer) :
94  VarProcessor(name, calib, computer),
95  maxTmp(0)
96 {
97  std::copy(calib->layers.begin(), calib->layers.end(),
98  std::back_inserter(layers));
99 
100  for(size_t i = 0; i < layers.size(); i++) {
101  maxTmp = std::max<unsigned int>(maxTmp, layers[i].neurons);
102  if (i > 0 && layers[i - 1].neurons != layers[i].inputs)
103  throw cms::Exception("ProcMLPInput")
104  << "ProcMLP neuron layers do not connect "
105  "properly." << std::endl;
106  }
107 }
108 
109 void ProcMLP::configure(ConfIterator iter, unsigned int n)
110 {
111  if (n != layers.front().inputs)
112  return;
113 
114  for(unsigned int i = 0; i < n; i++)
115  iter++(Variable::FLAG_NONE);
116 
117  for(unsigned int i = 0; i < layers.back().neurons; i++)
118  iter << Variable::FLAG_NONE;
119 }
120 
121 void ProcMLP::eval(ValueIterator iter, unsigned int n) const
122 {
123  double *tmp = (double*)alloca(2 * maxTmp * sizeof(double));
124  bool flip = false;
125 
126  for(double *pos = tmp; iter; iter++, pos++)
127  *pos = *iter;
128 
129  double *output = 0;
130  for(std::vector<Layer>::const_iterator layer = layers.begin();
131  layer != layers.end(); layer++, flip = !flip) {
132  const double *input = &tmp[flip ? maxTmp : 0];
133  output = &tmp[flip ? 0 : maxTmp];
134  std::vector<double>::const_iterator coeff =
135  layer->coeffs.begin();
136  for(unsigned int i = 0; i < layer->neurons; i++) {
137  double sum = *coeff++;
138  for(unsigned int j = 0; j < layer->inputs; j++)
139  sum += input[j] * *coeff++;
140  if (layer->sigmoid)
141  sum = 1.0 / (std::exp(-sum) + 1.0);
142  *output++ = sum;
143  }
144  }
145 
146  for(const double *pos = &tmp[flip ? maxTmp : 0]; pos < output; pos++)
147  iter(*pos);
148 }
149 
150 std::vector<double> ProcMLP::deriv(ValueIterator iter, unsigned int n) const
151 {
152  std::vector<double> prevValues, nextValues;
153  std::vector<double> prevMatrix, nextMatrix;
154 
155  while(iter)
156  nextValues.push_back(*iter++);
157 
158  unsigned int size = nextValues.size();
159  nextMatrix.resize(size * size);
160  for(unsigned int i = 0; i < size; i++)
161  nextMatrix[i * size + i] = 1.;
162 
163  for(std::vector<Layer>::const_iterator layer = layers.begin();
164  layer != layers.end(); layer++) {
165  prevValues.clear();
166  std::swap(prevValues, nextValues);
167  prevMatrix.clear();
168  std::swap(prevMatrix, nextMatrix);
169 
170  std::vector<double>::const_iterator coeff =
171  layer->coeffs.begin();
172  for(unsigned int i = 0; i < layer->neurons; i++) {
173  double sum = *coeff++;
174  for(unsigned int j = 0; j < layer->inputs; j++)
175  sum += prevValues[j] * *coeff++;
176 
177  double deriv;
178  if (layer->sigmoid) {
179  double e = std::exp(-sum);
180  sum = 1.0 / (e + 1.0);
181  deriv = 1.0 / (e + 1.0/e + 2.0);
182  } else
183  deriv = 1.0;
184 
185  nextValues.push_back(sum);
186 
187  for(unsigned int k = 0; k < size; k++) {
188  sum = 0.0;
189  coeff -= layer->inputs;
190  for(unsigned int j = 0; j < layer->inputs; j++)
191  sum += prevMatrix[j * size + k] *
192  *coeff++;
193  nextMatrix.push_back(sum * deriv);
194  }
195  }
196  }
197 
198  return nextMatrix;
199 }
200 
201 } // anonymous namespace
int i
Definition: DBlmapReader.cc:9
std::pair< std::vector< Neuron >, bool > Layer
Definition: MVAComputer.h:154
detail::ThreadSafeRegistry< ParameterSetID, ParameterSet, ProcessParameterSetIDCache > Registry
Definition: Registry.h:37
U second(std::pair< T, U > const &p)
MVATrainerComputer * calib
Definition: MVATrainer.cc:64
std::pair< double, std::vector< double > > Neuron
Definition: MVAComputer.h:153
Main interface class to the generic discriminator computer framework.
Definition: MVAComputer.h:40
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
int j
Definition: DBlmapReader.cc:9
bool first
Definition: L1TdeRCT.cc:94
int k[5][pyjets_maxn]
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
template to generate a registry singleton for a type.
static Interceptor::Registry registry("Interceptor")
tuple size
Write out results.
Common base class for variable processors.
Definition: VarProcessor.h:39