00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <algorithm>
00020 #include <iterator>
00021 #include <vector>
00022 #include <cmath>
00023
00024 #include "FWCore/Utilities/interface/Exception.h"
00025
00026 #include "PhysicsTools/MVAComputer/interface/VarProcessor.h"
00027 #include "PhysicsTools/MVAComputer/interface/Calibration.h"
00028
00029 using namespace PhysicsTools;
00030
00031 namespace {
00032
00033 class ProcMLP : public VarProcessor {
00034 public:
00035 typedef VarProcessor::Registry::Registry<ProcMLP,
00036 Calibration::ProcMLP> Registry;
00037
00038 ProcMLP(const char *name,
00039 const Calibration::ProcMLP *calib,
00040 const MVAComputer *computer);
00041 virtual ~ProcMLP() {}
00042
00043 virtual void configure(ConfIterator iter, unsigned int n);
00044 virtual void eval(ValueIterator iter, unsigned int n) const;
00045
00046 private:
00047 struct Layer {
00048 Layer(const Calibration::ProcMLP::Layer &calib);
00049 Layer(const Layer &orig) :
00050 inputs(orig.inputs), neurons(orig.neurons),
00051 coeffs(orig.coeffs), sigmoid(orig.sigmoid) {}
00052
00053 unsigned int inputs;
00054 unsigned int neurons;
00055 std::vector<double> coeffs;
00056 bool sigmoid;
00057 };
00058
00059 std::vector<Layer> layers;
00060 unsigned int maxTmp;
00061 };
00062
00063 static ProcMLP::Registry registry("ProcMLP");
00064
00065 ProcMLP::Layer::Layer(const Calibration::ProcMLP::Layer &calib) :
00066 inputs(calib.first.front().second.size()),
00067 neurons(calib.first.size()),
00068 sigmoid(calib.second)
00069 {
00070 typedef Calibration::ProcMLP::Neuron Neuron;
00071
00072 coeffs.resize(neurons * (inputs + 1));
00073 std::vector<double>::iterator inserter = coeffs.begin();
00074
00075 for(std::vector<Neuron>::const_iterator iter = calib.first.begin();
00076 iter != calib.first.end(); iter++) {
00077 *inserter++ = iter->first;
00078
00079 if (iter->second.size() != inputs)
00080 throw cms::Exception("ProcMLPInput")
00081 << "ProcMLP neuron layer inconsistent."
00082 << std::endl;
00083
00084 inserter = std::copy(iter->second.begin(), iter->second.end(),
00085 inserter);
00086 }
00087 }
00088
00089 ProcMLP::ProcMLP(const char *name,
00090 const Calibration::ProcMLP *calib,
00091 const MVAComputer *computer) :
00092 VarProcessor(name, calib, computer),
00093 maxTmp(0)
00094 {
00095 std::copy(calib->layers.begin(), calib->layers.end(),
00096 std::back_inserter(layers));
00097
00098 for(unsigned int i = 0; i < layers.size(); i++) {
00099 maxTmp = std::max<unsigned int>(maxTmp, layers[i].neurons);
00100 if (i > 0 && layers[i - 1].neurons != layers[i].inputs)
00101 throw cms::Exception("ProcMLPInput")
00102 << "ProcMLP neuron layers do not connect "
00103 "properly." << std::endl;
00104 }
00105 }
00106
00107 void ProcMLP::configure(ConfIterator iter, unsigned int n)
00108 {
00109 if (n != layers.front().inputs)
00110 return;
00111
00112 for(unsigned int i = 0; i < n; i++)
00113 iter++(Variable::FLAG_NONE);
00114
00115 for(unsigned int i = 0; i < layers.back().neurons; i++)
00116 iter << Variable::FLAG_NONE;
00117 }
00118
00119 void ProcMLP::eval(ValueIterator iter, unsigned int n) const
00120 {
00121 double *tmp = (double*)alloca(2 * maxTmp * sizeof(double));
00122 bool flip = false;
00123
00124 for(double *pos = tmp; iter; iter++, pos++)
00125 *pos = *iter;
00126
00127 double *output = 0;
00128 for(std::vector<Layer>::const_iterator layer = layers.begin();
00129 layer != layers.end(); layer++, flip = !flip) {
00130 const double *input = &tmp[flip ? maxTmp : 0];
00131 output = &tmp[flip ? 0 : maxTmp];
00132 std::vector<double>::const_iterator coeff =
00133 layer->coeffs.begin();
00134 for(unsigned int i = 0; i < layer->neurons; i++) {
00135 double sum = *coeff++;
00136 for(unsigned int j = 0; j < layer->inputs; j++)
00137 sum += input[j] * *coeff++;
00138 if (layer->sigmoid)
00139 sum = 1.0 / (std::exp(-sum) + 1.0);
00140 *output++ = sum;
00141 }
00142 }
00143
00144 for(const double *pos = &tmp[flip ? maxTmp : 0]; pos < output; pos++)
00145 iter(*pos);
00146 }
00147
00148 }