LevenbergMarquardtOptimizer in progress
parent
e7e64e945b
commit
67564d043b
|
@ -47,6 +47,95 @@ NonlinearOptimizer::auto_ptr LevenbergMarquardtOptimizer::iterate() const {
|
||||||
else
|
else
|
||||||
throw runtime_error("Optimization parameter is invalid: LevenbergMarquardtParams::elimination");
|
throw runtime_error("Optimization parameter is invalid: LevenbergMarquardtParams::elimination");
|
||||||
|
|
||||||
|
|
||||||
|
const NonlinearOptimizerParams::Verbosity verbosity = params_->verbosity;
|
||||||
|
const double lambdaFactor = parameters_->lambdaFactor_ ;
|
||||||
|
double lambda = params_->lambda;
|
||||||
|
|
||||||
|
double next_error = error_;
|
||||||
|
SharedValues next_values = values_;
|
||||||
|
|
||||||
|
// Keep increasing lambda until we make make progress
|
||||||
|
while(true) {
|
||||||
|
if (verbosity >= Parameters::TRYLAMBDA) cout << "trying lambda = " << lambda << endl;
|
||||||
|
|
||||||
|
// add prior-factors
|
||||||
|
// TODO: replace this dampening with a backsubstitution approach
|
||||||
|
typename L::shared_ptr dampedSystem(new L(linearSystem));
|
||||||
|
{
|
||||||
|
double sigma = 1.0 / sqrt(lambda);
|
||||||
|
dampedSystem->reserve(dampedSystem->size() + dimensions_->size());
|
||||||
|
// for each of the variables, add a prior
|
||||||
|
for(Index j=0; j<dimensions_->size(); ++j) {
|
||||||
|
size_t dim = (*dimensions_)[j];
|
||||||
|
Matrix A = eye(dim);
|
||||||
|
Vector b = zero(dim);
|
||||||
|
SharedDiagonal model = noiseModel::Isotropic::Sigma(dim,sigma);
|
||||||
|
typename L::sharedFactor prior(new JacobianFactor(j, A, b, model));
|
||||||
|
dampedSystem->push_back(prior);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verbosity >= Parameters::DAMPED) dampedSystem->print("damped");
|
||||||
|
|
||||||
|
// Create a new solver using the damped linear system
|
||||||
|
// FIXME: remove spcg specific code
|
||||||
|
if (spcg_solver_) spcg_solver_->replaceFactors(dampedSystem);
|
||||||
|
shared_solver solver = (spcg_solver_) ? spcg_solver_ : shared_solver(
|
||||||
|
new S(dampedSystem, structure_, parameters_->useQR_));
|
||||||
|
|
||||||
|
// Try solving
|
||||||
|
try {
|
||||||
|
VectorValues delta = *solver->optimize();
|
||||||
|
if (verbosity >= Parameters::TRYLAMBDA) cout << "linear delta norm = " << delta.vector().norm() << endl;
|
||||||
|
if (verbosity >= Parameters::TRYDELTA) delta.print("delta");
|
||||||
|
|
||||||
|
// update values
|
||||||
|
shared_values newValues(new Values(values_->retract(delta, *ordering_)));
|
||||||
|
|
||||||
|
// create new optimization state with more adventurous lambda
|
||||||
|
double error = graph_->error(*newValues);
|
||||||
|
|
||||||
|
if (verbosity >= Parameters::TRYLAMBDA) cout << "next error = " << error << endl;
|
||||||
|
|
||||||
|
if( error <= error_ ) {
|
||||||
|
next_values = newValues;
|
||||||
|
next_error = error;
|
||||||
|
lambda /= lambdaFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Either we're not cautious, or the same lambda was worse than the current error.
|
||||||
|
// The more adventurous lambda was worse too, so make lambda more conservative
|
||||||
|
// and keep the same values.
|
||||||
|
if(lambdaMode >= Parameters::BOUNDED && lambda >= 1.0e5) {
|
||||||
|
if(verbosity >= Parameters::ERROR)
|
||||||
|
cout << "Warning: Levenberg-Marquardt giving up because cannot decrease error with maximum lambda" << endl;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
lambda *= factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(const NegativeMatrixException& e) {
|
||||||
|
if(verbosity >= Parameters::LAMBDA)
|
||||||
|
cout << "Negative matrix, increasing lambda" << endl;
|
||||||
|
// Either we're not cautious, or the same lambda was worse than the current error.
|
||||||
|
// The more adventurous lambda was worse too, so make lambda more conservative
|
||||||
|
// and keep the same values.
|
||||||
|
if(lambdaMode >= Parameters::BOUNDED && lambda >= 1.0e5) {
|
||||||
|
if(verbosity >= Parameters::ERROR)
|
||||||
|
cout << "Warning: Levenberg-Marquardt giving up because cannot decrease error with maximum lambda" << endl;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
lambda *= factor;
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
} // end while
|
||||||
|
|
||||||
|
return newValuesErrorLambda_(next_values, next_error, lambda);
|
||||||
|
|
||||||
|
|
||||||
// Maybe show output
|
// Maybe show output
|
||||||
if(params_->verbosity >= NonlinearOptimizerParams::DELTA) delta->print("delta");
|
if(params_->verbosity >= NonlinearOptimizerParams::DELTA) delta->print("delta");
|
||||||
|
|
||||||
|
|
|
@ -39,11 +39,17 @@ public:
|
||||||
QR,
|
QR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** See LevenbergMarquardtParams::lmVerbosity */
|
||||||
|
enum LMVerbosity {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
Elimination elimination; ///< The elimination algorithm to use (default: MULTIFRONTAL)
|
Elimination elimination; ///< The elimination algorithm to use (default: MULTIFRONTAL)
|
||||||
Factorization factorization; ///< The numerical factorization (default: LDL)
|
Factorization factorization; ///< The numerical factorization (default: LDL)
|
||||||
Ordering::shared_ptr ordering; ///< The variable elimination ordering (default: empty -> COLAMD)
|
Ordering::shared_ptr ordering; ///< The variable elimination ordering (default: empty -> COLAMD)
|
||||||
double lambda; ///< The initial (and current after each iteration) Levenberg-Marquardt damping term (default: 1e-5)
|
double lambda; ///< The initial (and current after each iteration) Levenberg-Marquardt damping term (default: 1e-5)
|
||||||
double lambdaFactor; ///< The amount by which to multiply or divide lambda when adjusting lambda (default: 10.0)
|
double lambdaFactor; ///< The amount by which to multiply or divide lambda when adjusting lambda (default: 10.0)
|
||||||
|
double lambdaUpperBound; ///< The maximum lambda to try before assuming the optimization has failed (default: 1e5)
|
||||||
|
|
||||||
LevenbergMarquardtParams() :
|
LevenbergMarquardtParams() :
|
||||||
elimination(MULTIFRONTAL), factorization(LDL), lambda(1e-5), lambdaFactor(10.0) {}
|
elimination(MULTIFRONTAL), factorization(LDL), lambda(1e-5), lambdaFactor(10.0) {}
|
||||||
|
|
Loading…
Reference in New Issue