Belle II Software  release-08-01-10
PIDNeuralNetwork.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <analysis/utility/PIDNeuralNetwork.h>
10 
11 #include <cmath>
12 
13 
14 using namespace Belle2;
15 
16 
18 {
19  m_pidNeuralNetworkParametersDB = std::make_unique<DBObjPtr<PIDNeuralNetworkParameters>>(m_pidNeuralNetworkParametersName);
20 
22  B2FATAL("The dbobject PIDNeuralNetworkParameters, " << m_pidNeuralNetworkParametersName <<
23  ", could not be found! It is necessary for the neural network based PID variables.");
24 
25  m_model = std::make_unique<fdeep::model>(fdeep::read_model_from_string((*m_pidNeuralNetworkParametersDB)->getModelDefinition(),
26  false,
27  [](const std::string&) {} // disable logger
28  ));
29 }
30 
31 
32 std::map<int, double> PIDNeuralNetwork::predict(std::vector<float> input) const
33 {
34 
35  // apply cuts, ie. overwrite certain input values with index `inputSetIndex` with the value `setValue`
36  // if the input with index `inputCutIndex` is in the range (`rangeStart`, `rangeEnd`)
37  for (auto const& inputToCut : (*m_pidNeuralNetworkParametersDB)->getInputsToCut()) {
38  const auto [inputSetIndex, inputCutIndex, rangeStart, rangeEnd, setValue] = inputToCut;
39  if (!std::isnan(rangeStart) and !std::isnan(rangeEnd)) {
40  if (input[inputCutIndex] >= rangeStart and input[inputCutIndex] <= rangeEnd)
41  input[inputSetIndex] = setValue;
42  } else if (!std::isnan(rangeStart)) {
43  if (input[inputCutIndex] >= rangeStart)
44  input[inputSetIndex] = setValue;
45  } else if (!std::isnan(rangeEnd)) {
46  if (input[inputCutIndex] <= rangeEnd)
47  input[inputSetIndex] = setValue;
48  }
49  }
50 
51  // Normalize inputs
52  // By definition, this has to be done after applying the cuts and before handling missing information
53  for (size_t i = 0; i < input.size(); ++i) {
54  input[i] = (input[i] - (*m_pidNeuralNetworkParametersDB)->getMeanValues()[i]) /
55  (*m_pidNeuralNetworkParametersDB)->getStandardDeviations()[i];
56  }
57 
58  // handle missing information
59  for (auto const& index_value : (*m_pidNeuralNetworkParametersDB)->getHandleMissingInputs()) {
60  const auto [index, value] = index_value;
61  if (std::isnan(input[index])) input[index] = value;
62  }
63 
64  // apply neural network
65  const auto inputFdeep = fdeep::tensor(fdeep::tensor_shape(input.size()), input);
66  const auto result = m_model->predict({inputFdeep});
67 
68  std::map<int, double> probabilities;
69  for (const auto pdgCode : getOutputSpeciesPdg()) {
70  const int outputIndex = (*m_pidNeuralNetworkParametersDB)->pdg2OutputIndex(pdgCode);
71  probabilities[pdgCode] = result.front().get(fdeep::tensor_pos(outputIndex));
72  }
73  return probabilities;
74 }
std::string m_pidNeuralNetworkParametersName
name of the parameter set
void loadParametersFromDB()
Load neural-network parameters with name m_pidNeuralNetworkParametersName from the conditions data ba...
std::map< int, double > predict(std::vector< float > inputs) const
Predict neural-network output for all implemented hypotheses using the given inputs.
const std::vector< int > & getOutputSpeciesPdg() const
Get the list of pdg codes of species hypotheses, for which the network predicts the probability in th...
std::unique_ptr< const fdeep::model > m_model
frugally-deep neural network
std::unique_ptr< DBObjPtr< PIDNeuralNetworkParameters > > m_pidNeuralNetworkParametersDB
db object for the parameter set
Abstract base class for different kinds of events.