npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
MinuitLocalLogisticFcn.hh
Go to the documentation of this file.
1 #ifndef NPSI_MINUITLOCALLOGISTICFCN_HH_
2 #define NPSI_MINUITLOCALLOGISTICFCN_HH_
3 
4 /*!
5 // \file MinuitLocalLogisticFcn.hh
6 //
7 // \brief Minuit function to minimize for local logistic regression
8 //
9 // Author: I. Volobouev
10 //
11 // March 2010
12 */
13 
14 #include <cassert>
15 
16 #include "Minuit2/FCNGradientBase.h"
18 
19 namespace npsi {
20  /**
21  // Target minimization function adapter class for running local logistic
22  // regression fits by Minuit2
23  */
24  template <class Numeric>
25  class MinuitLocalLogisticFcn : public ROOT::Minuit2::FCNGradientBase
26  {
27  public:
28  /**
29  // Will not assume ownership the LogisticRegressionBase object
30  */
33  const unsigned maxdeg, const double up=0.05)
34  : reg_(reg), up_(up), force_(true)
35  {
36  assert(reg_);
37  assert(up_ > 0.0);
38  setMaxDeg(maxdeg);
39  }
40 
41  inline virtual ~MinuitLocalLogisticFcn() {}
42 
43  inline void setMaxDeg(const unsigned maxdeg)
44  {
45  switch (maxdeg)
46  {
47  case 0U:
48  npara_ = 1U;
49  break;
50  case 1U:
51  npara_ = reg_->dim() + 1U;
52  break;
53  case 2U:
54  npara_ = ((reg_->dim() + 1U)*(reg_->dim() + 2U))/2U;
55  break;
56  default:
57  assert(!"Invalid maximum polynomial degree");
58  }
59  }
60 
61  inline unsigned nParameters() const {return npara_;}
62 
63  // Make Minuit look for a better minimum by reducing
64  // the recommended "Up" value by an order of magnitude
65  inline double Up() const {return up_;}
66 
67  // Do not waste time checking gradient calculations. They are correct.
68  inline bool CheckGradient() const {return false;}
69 
70  inline virtual double operator()(const std::vector<double>& x) const
71  {
72  calculateMemoized(x);
73  return lastResult_;
74  }
75 
76  inline std::vector<double> Gradient(const std::vector<double>& x) const
77  {
78  // Returning std::vector<double> on the stack is
79  // a pretty inefficient thing to do. However,
80  // this is how Minuit2 interface is designed.
81  calculateMemoized(x);
82  std::vector<double> result(x.size(), 0.0);
83  reg_->getGradient(&result[0], npara_);
84  return result;
85  }
86 
87  private:
89 
90  // Minuit2 has separate interfaces for calculating the function
91  // value and the gradient. I have yet to see a non-trivial realistic
92  // problem in which the function value can not be easily obtained
93  // along with the gradient. It would be much better to have them
94  // calculated together. We will alleviate this design problem
95  // by memoizing the argument / result pairs so that we do not
96  // have to repeat the calculation when the gradient is wanted
97  // at the same point where the function was just evaluated.
98  void calculateMemoized(const std::vector<double>& x) const
99  {
100  assert(x.size() >= npara_);
101  bool recalculate =
102  reg_->lastCoeffs().size() != npara_ || force_;
103  if (!recalculate)
104  {
105  const double* lastX = &reg_->lastCoeffs()[0];
106  const double* px = &x[0];
107  for (unsigned i=0; i<npara_; ++i)
108  if (px[i] != lastX[i])
109  {
110  recalculate = true;
111  break;
112  }
113  }
114  if (recalculate)
115  {
116  force_ = false;
117  lastResult_ = reg_->calculateLogLikelihood(&x[0], npara_);
118  }
119  }
120 
122  double up_;
123  mutable double lastResult_;
124  unsigned npara_;
125  mutable bool force_;
126  };
127 }
128 
129 #endif // NPSI_MINUITLOCALLOGISTICFCN_HH_
Facilities for performing local linear and quadratic logistic regression.
Definition: MinuitLocalLogisticFcn.hh:26
MinuitLocalLogisticFcn(npstat::LogisticRegressionBase< Numeric > *reg, const unsigned maxdeg, const double up=0.05)
Definition: MinuitLocalLogisticFcn.hh:31
Definition: LocalLogisticRegression.hh:29
Definition: fitCompositeJohnson.hh:16