1 #ifndef NPSTAT_DAMPEDNEWTONFORNEYMANOSDE1D_HH_
2 #define NPSTAT_DAMPEDNEWTONFORNEYMANOSDE1D_HH_
30 template<
class ConvergenceCalculator>
31 inline NeymanOSDE1DResult dampedNewtonForNeymanOSDE1D(
32 const NeymanOSDE1D& nosde,
33 const double* initialCoeffs,
const unsigned nCoeffs,
34 const double* shrinkages,
const unsigned nShrinkages,
35 const ConvergenceCalculator& conv,
const unsigned maxIterations,
36 const double dampingCoefficient = 1.0,
37 const bool useGradientDescent =
false)
39 assert(dampingCoefficient > 0.0);
41 std::vector<double> coeffs(initialCoeffs, initialCoeffs+nCoeffs);
42 std::vector<double> polyStats(nShrinkages);
43 std::vector<double> prevGradient(nCoeffs);
44 std::vector<double> currentGradient(nCoeffs);
45 std::vector<double> hessianEigenvalues(nCoeffs);
46 std::vector<double> step(nCoeffs);
47 Matrix<double> hessian(nCoeffs, nCoeffs);
48 Matrix<double> hessianEigenvectors(nCoeffs, nCoeffs);
50 double prevChisq = nosde.chiSquare(&coeffs[0], nCoeffs,
51 shrinkages, nShrinkages,
52 &polyStats[0], &prevGradient[0],
54 bool converged =
false, badHessian =
false;
56 for (; iter<maxIterations && !converged; ++iter)
58 hessian.symEigen(&hessianEigenvalues[0], nCoeffs, &hessianEigenvectors);
59 for (
unsigned i=0; i<nCoeffs && !badHessian; ++i)
61 if (hessianEigenvalues[i] <= 0.0)
64 hessianEigenvalues[i] = 1.0/hessianEigenvalues[i];
74 if (useGradientDescent)
76 HessianNeymanOSDE1DConvergenceCalc<ConvergenceCalculator> descentConv(conv);
77 const NeymanOSDE1DResult& r = gradientDescentForNeymanOSDE1D(
78 nosde, &coeffs[0], nCoeffs, shrinkages, nShrinkages,
79 descentConv, maxIterations);
82 if (descentConv.otherCalcConverged())
87 for (
unsigned i=0; i<nCoeffs; ++i)
88 coeffs[i] = r.coeffs()[i];
89 prevChisq = nosde.chiSquare(&coeffs[0], nCoeffs,
90 shrinkages, nShrinkages,
91 &polyStats[0], &prevGradient[0],
108 const Matrix<double>& invEigen =
diag(&hessianEigenvalues[0], nCoeffs);
109 const Matrix<double>& invHess = invEigen.bilinear(hessianEigenvectors);
110 invHess.timesVector(&prevGradient[0], nCoeffs, &step[0], nCoeffs);
111 for (
unsigned i=0; i<nCoeffs; ++i)
113 step[i] *= -dampingCoefficient;
114 coeffs[i] += step[i];
117 const double currentChisq = nosde.chiSquare(&coeffs[0], nCoeffs,
118 shrinkages, nShrinkages,
119 &polyStats[0], ¤tGradient[0],
121 converged = conv.converged(iter, prevChisq, prevGradient, step,
122 currentChisq, currentGradient, hessian);
124 prevChisq = currentChisq;
125 std::swap(prevGradient, currentGradient);
128 return NeymanOSDE1DResult(coeffs, polyStats, prevChisq,
129 maxAbsValue(&prevGradient[0], prevGradient.size()),
130 NOSDE_NEWTON, iter, converged, badHessian);
Classes for establishing convergence of the Neyman OSDE optimization algorithms.
Class for representing results of the Neyman OSDE optimization algorithms.
OSDE based on minimizing the expected ISE of the empirical comparison density.
Gradient descent method for the Neyman OSDE. Not very well thought out, so it is very slow.
Maximum absolute value in an array.
Definition: AbsArrayProjector.hh:14
Matrix< Numeric > diag(const Numeric *data, unsigned dataLen)