1 #ifndef NPSTAT_LORPE1DVARIABLEDEGREECVPICKER_HH_
2 #define NPSTAT_LORPE1DVARIABLEDEGREECVPICKER_HH_
20 class LOrPE1DVariableDegreeCVPicker;
27 typedef std::map<double,LOrPE1DCVResult> StatusMap;
37 virtual double operator()(
const double& degree)
const;
42 const auto it = statusMap_.find(degree);
43 if (it == statusMap_.end())
52 mutable StatusMap statusMap_;
115 const std::vector<double>& minBwFactors,
116 const std::vector<double>& maxBwFactors,
117 const std::vector<double>& startingBwFactors,
118 const unsigned nBwFactors,
119 const unsigned initialStepSizeInFactorCells,
120 const double initialDeg,
121 const unsigned initialStepSizeInDegreeCells)
122 : degAxis_(
UniformAxis(minBwFactors.size(), 0.0, i_maxDeg)),
123 minBwFactorForEachDeg_(minBwFactors),
124 maxBwFactorForEachDeg_(maxBwFactors),
125 startingBwFactorForEachDeg_(startingBwFactors),
126 nBwFactors_(nBwFactors),
127 initialStepSizeInFactorsGridCells_(initialStepSizeInFactorCells),
128 initialStepSizeInDegreeGridCells_(initialStepSizeInDegreeCells)
130 const unsigned nDegsInTheGrid = minBwFactorForEachDeg_.size();
132 assert(i_maxDeg > 0.0);
133 assert(nDegsInTheGrid > 1U);
134 assert(maxBwFactorForEachDeg_.size() == nDegsInTheGrid);
135 assert(startingBwFactorForEachDeg_.size() == nDegsInTheGrid);
137 for (
unsigned i=0; i<nDegsInTheGrid; ++i)
139 assert(minBwFactorForEachDeg_[i] > 0.0);
140 assert(maxBwFactorForEachDeg_[i] > minBwFactorForEachDeg_[i]);
141 assert(startingBwFactorForEachDeg_[i] > 0.0);
143 assert(nBwFactors_ > 1U);
145 if (initialDeg <= 0.0)
146 initialDegCell_ = 0U;
147 else if (initialDeg >= i_maxDeg)
148 initialDegCell_ = nDegsInTheGrid - 1U;
151 const std::pair<unsigned,double>& cell = degAxis_.getInterval(initialDeg);
152 initialDegCell_ = cell.first;
153 if (cell.second < 0.5)
157 if (!initialStepSizeInDegreeGridCells_)
158 initialStepSizeInDegreeGridCells_ = 1U;
159 if (!initialStepSizeInFactorsGridCells_)
160 initialStepSizeInFactorsGridCells_ = 1U;
163 template<
class Lorpe>
169 const unsigned nscan = degAxis_.nCoords();
170 const Helper helper(lorpe, *
this);
171 unsigned imin = UINT_MAX;
172 double fMinusOne, fmin, fPlusOne;
175 helper, degAxis_, initialDegCell_, initialStepSizeInDegreeGridCells_,
176 &imin, &fMinusOne, &fmin, &fPlusOne);
178 if (status == MIN_SEARCH_FAILED)
180 std::vector<double> buffer(2*nscan);
181 double* degrees = &buffer[0];
182 double* cvValues = degrees + nscan;
184 for (
unsigned i=0; i<nscan; ++i)
186 const double deg = degAxis_.coordinate(i);
189 if (searched.isValid())
190 cvValues[i] = searched.cvFunction();
192 cvValues[i] = -helper(deg);
195 const ScanExtremum1D& scanMax = findScanMaximum1D(degrees, nscan,
197 LOrPE1DCVResult searched = helper.getMemoized(scanMax.location());
198 if (scanMax.isOnTheBoundary())
199 assert(searched.isValid());
200 else if (searched.isValid())
201 searched.setDegreeBoundaryFlag(
false);
204 searched = cvArbitraryDegree(lorpe, scanMax.location());
207 else if (status == MIN_SEARCH_OK)
210 assert(imin + 1U < nscan);
212 const double degGuess = degAxis_.coordinate(imin);
213 Result resGuess = helper.getMemoized(degGuess);
214 assert(resGuess.isValid());
215 resGuess.setDegreeBoundaryFlag(
false);
218 double bestDegree, extremumValue;
220 degAxis_.coordinate(imin - 1U), fMinusOne,
222 degAxis_.coordinate(imin + 1U), fPlusOne,
223 &bestDegree, &extremumValue);
227 const Result bestGuess = cvArbitraryDegree(lorpe, bestDegree);
228 return bestGuess.cvFunction() > resGuess.cvFunction() ?
229 bestGuess : resGuess;
234 assert(imin < nscan);
235 const double deg = degAxis_.coordinate(imin);
236 const LOrPE1DCVResult& searched = helper.getMemoized(deg);
237 assert(searched.isValid());
243 template<
class Lorpe>
244 friend class Private::LOrPE1DVariableDegreeCVPickerHelper;
246 template<
class Lorpe>
247 inline LOrPE1DCVResult cvArbitraryDegree(Lorpe& lorpe,
const double bestDegree)
const
249 const unsigned nscan = degAxis_.nCoords();
251 double minBwFactor, maxBwFactor, firstBwFactorToTry;
252 const unsigned ibest = degAxis_.getInterval(bestDegree).first;
253 const unsigned inext = ibest + 1U;
256 const double xbest = degAxis_.coordinate(ibest);
257 const double xnext = degAxis_.coordinate(inext);
262 const LinearMapper1d m0(xbest, std::log(minBwFactorForEachDeg_[ibest]),
263 xnext, std::log(minBwFactorForEachDeg_[inext]));
264 minBwFactor = std::exp(m0(bestDegree));
266 const LinearMapper1d m1(xbest, std::log(maxBwFactorForEachDeg_[ibest]),
267 xnext, std::log(maxBwFactorForEachDeg_[inext]));
268 maxBwFactor = std::exp(m1(bestDegree));
270 const LinearMapper1d m2(xbest, std::log(startingBwFactorForEachDeg_[ibest]),
271 xnext, std::log(startingBwFactorForEachDeg_[inext]));
272 firstBwFactorToTry = std::exp(m2(bestDegree));
276 minBwFactor = minBwFactorForEachDeg_[ibest];
277 maxBwFactor = maxBwFactorForEachDeg_[ibest];
278 firstBwFactorToTry = startingBwFactorForEachDeg_[ibest];
281 const LOrPE1DFixedDegreeCVPicker r2(bestDegree,
282 minBwFactor, maxBwFactor, nBwFactors_,
283 firstBwFactorToTry, initialStepSizeInFactorsGridCells_);
284 LOrPE1DCVResult cv = r2.crossValidate(lorpe);
285 assert(cv.isValid());
286 cv.setDegreeBoundaryFlag(
false);
291 std::vector<double> minBwFactorForEachDeg_;
292 std::vector<double> maxBwFactorForEachDeg_;
293 std::vector<double> startingBwFactorForEachDeg_;
294 unsigned nBwFactors_;
295 unsigned initialStepSizeInFactorsGridCells_;
296 unsigned initialDegCell_;
297 unsigned initialStepSizeInDegreeGridCells_;
301 template<
class Lorpe>
303 LOrPE1DVariableDegreeCVPickerHelper<Lorpe>::operator()(
const double& degree)
const
308 const double eps = 1.e-5;
309 const std::pair<unsigned,double>& cell = picker_.degAxis_.getInterval(degree);
310 assert(cell.second < eps || cell.second > 1.0 - eps);
311 unsigned ideg = cell.first;
312 if (cell.second < eps)
314 assert(ideg < picker_.degAxis_.nCoords());
316 const double minBwFactor = picker_.minBwFactorForEachDeg_[ideg];
317 const double maxBwFactor = picker_.maxBwFactorForEachDeg_[ideg];
318 const double firstBwFactorToTry = picker_.startingBwFactorForEachDeg_[ideg];
321 const LOrPE1DFixedDegreeCVPicker r(
322 degree, minBwFactor, maxBwFactor, picker_.nBwFactors_,
323 firstBwFactorToTry, picker_.initialStepSizeInFactorsGridCells_);
324 const LOrPE1DCVResult& status = r.crossValidate(lorpe_);
325 assert(status.isValid());
328 const auto insertResult = statusMap_.insert(std::make_pair(degree,status));
329 assert(insertResult.second);
330 return -status.cvFunction();
Optimization of LOrPE bandwidth choice by cross-validation with a hybrid algorithm combining golden s...
Linear transformation functor.
Definition: LOrPE1DCVResult.hh:19
Definition: LOrPE1DVariableDegreeCVPicker.hh:57
LOrPE1DVariableDegreeCVPicker(const double i_maxDeg, const std::vector< double > &minBwFactors, const std::vector< double > &maxBwFactors, const std::vector< double > &startingBwFactors, const unsigned nBwFactors, const unsigned initialStepSizeInFactorCells, const double initialDeg, const unsigned initialStepSizeInDegreeCells)
Definition: LOrPE1DVariableDegreeCVPicker.hh:114
Definition: LOrPE1DVariableDegreeCVPicker.hh:25
Definition: AbsArrayProjector.hh:14
MinSearchStatus1D goldenSectionSearchOnAGrid(const Functor1< double, double > &f, const DualAxis &axis, unsigned i0, unsigned initialStep, unsigned *imin, double *fMinusOne, double *fmin, double *fPlusOne)
LinearMapper1dTmpl< double > LinearMapper1d
Definition: LinearMapper1d.hh:75
bool parabolicExtremum(double x0, double y0, double x1, double y1, double x2, double y2, double *extremumCoordinate, double *extremumValue)
Definition: SimpleFunctors.hh:58