added verbosity
parent
9e3263f2b1
commit
dab00907b9
|
@ -38,8 +38,12 @@ static double tol = 1e-7;
|
||||||
template <class BaseOptimizerParameters>
|
template <class BaseOptimizerParameters>
|
||||||
class GncParams {
|
class GncParams {
|
||||||
public:
|
public:
|
||||||
|
/** Verbosity levels */
|
||||||
|
enum VerbosityGNC {
|
||||||
|
SILENT = 0, SUMMARY, VALUES
|
||||||
|
};
|
||||||
|
|
||||||
/** See NonlinearOptimizerParams::verbosity */
|
/** Choice of robust loss function for GNC */
|
||||||
enum RobustLossType {
|
enum RobustLossType {
|
||||||
GM /*Geman McClure*/, TLS /*Truncated least squares*/
|
GM /*Geman McClure*/, TLS /*Truncated least squares*/
|
||||||
};
|
};
|
||||||
|
@ -51,7 +55,8 @@ public:
|
||||||
lossType(GM), /* default loss*/
|
lossType(GM), /* default loss*/
|
||||||
maxIterations(100), /* maximum number of iterations*/
|
maxIterations(100), /* maximum number of iterations*/
|
||||||
barcSq(1.0), /* a factor is considered an inlier if factor.error() < barcSq. Note that factor.error() whitens by the covariance*/
|
barcSq(1.0), /* a factor is considered an inlier if factor.error() < barcSq. Note that factor.error() whitens by the covariance*/
|
||||||
muStep(1.4){}/* multiplicative factor to reduce/increase the mu in gnc */
|
muStep(1.4), /* multiplicative factor to reduce/increase the mu in gnc */
|
||||||
|
verbosityGNC(SILENT){}/* verbosity level */
|
||||||
|
|
||||||
// default constructor
|
// default constructor
|
||||||
GncParams(): baseOptimizerParams() {}
|
GncParams(): baseOptimizerParams() {}
|
||||||
|
@ -62,16 +67,18 @@ public:
|
||||||
size_t maxIterations;
|
size_t maxIterations;
|
||||||
double barcSq;
|
double barcSq;
|
||||||
double muStep;
|
double muStep;
|
||||||
|
VerbosityGNC verbosityGNC;
|
||||||
|
|
||||||
void setLossType(RobustLossType type){ lossType = type; }
|
void setLossType(const RobustLossType type){ lossType = type; }
|
||||||
void setMaxIterations(size_t maxIter){
|
void setMaxIterations(const size_t maxIter){
|
||||||
std::cout
|
std::cout
|
||||||
<< "setMaxIterations: changing the max number of iterations might lead to less accurate solutions and is not recommended! "
|
<< "setMaxIterations: changing the max number of iterations might lead to less accurate solutions and is not recommended! "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
maxIterations = maxIter;
|
maxIterations = maxIter;
|
||||||
}
|
}
|
||||||
void setInlierThreshold(double inth){ barcSq = inth; }
|
void setInlierThreshold(const double inth){ barcSq = inth; }
|
||||||
void setMuStep(double step){ muStep = step; }
|
void setMuStep(const double step){ muStep = step; }
|
||||||
|
void setVerbosityGNC(const VerbosityGNC verbosity) { verbosityGNC = verbosity; }
|
||||||
|
|
||||||
/// equals
|
/// equals
|
||||||
bool equals(const GncParams& other, double tol = 1e-9) const {
|
bool equals(const GncParams& other, double tol = 1e-9) const {
|
||||||
|
@ -79,7 +86,8 @@ public:
|
||||||
&& lossType == other.lossType
|
&& lossType == other.lossType
|
||||||
&& maxIterations == other.maxIterations
|
&& maxIterations == other.maxIterations
|
||||||
&& std::fabs(barcSq - other.barcSq) <= tol
|
&& std::fabs(barcSq - other.barcSq) <= tol
|
||||||
&& std::fabs(muStep - other.muStep) <= tol;
|
&& std::fabs(muStep - other.muStep) <= tol
|
||||||
|
&& verbosityGNC == other.verbosityGNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// print function
|
/// print function
|
||||||
|
@ -94,6 +102,7 @@ public:
|
||||||
std::cout << "maxIterations: " << maxIterations << "\n";
|
std::cout << "maxIterations: " << maxIterations << "\n";
|
||||||
std::cout << "barcSq: " << barcSq << "\n";
|
std::cout << "barcSq: " << barcSq << "\n";
|
||||||
std::cout << "muStep: " << muStep << "\n";
|
std::cout << "muStep: " << muStep << "\n";
|
||||||
|
std::cout << "verbosityGNC: " << verbosityGNC << "\n";
|
||||||
baseOptimizerParams.print(str);
|
baseOptimizerParams.print(str);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -143,16 +152,31 @@ public:
|
||||||
Values result = baseOptimizer.optimize();
|
Values result = baseOptimizer.optimize();
|
||||||
double mu = initializeMu();
|
double mu = initializeMu();
|
||||||
for(size_t iter=0; iter < params_.maxIterations; iter++){
|
for(size_t iter=0; iter < params_.maxIterations; iter++){
|
||||||
|
|
||||||
|
// display info
|
||||||
|
if (params_.verbosityGNC >= GncParameters::VerbosityGNC::VALUES){
|
||||||
|
result.print("result\n");
|
||||||
|
std::cout << "mu: " << mu << std::endl;
|
||||||
|
std::cout << "weights: " << weights << std::endl;
|
||||||
|
}
|
||||||
// weights update
|
// weights update
|
||||||
weights = calculateWeights(result, mu);
|
weights = calculateWeights(result, mu);
|
||||||
|
|
||||||
// variable/values update
|
// variable/values update
|
||||||
NonlinearFactorGraph graph_iter = this->makeWeightedGraph(weights);
|
NonlinearFactorGraph graph_iter = this->makeWeightedGraph(weights);
|
||||||
GaussNewtonOptimizer baseOptimizer_iter(graph_iter, state_);
|
GaussNewtonOptimizer baseOptimizer_iter(graph_iter, state_);
|
||||||
Values result = baseOptimizer.optimize();
|
result = baseOptimizer.optimize();
|
||||||
|
|
||||||
// stopping condition
|
// stopping condition
|
||||||
if( checkMuConvergence(mu) ) { break; }
|
if( checkMuConvergence(mu) ) {
|
||||||
|
// display info
|
||||||
|
if (params_.verbosityGNC >= GncParameters::VerbosityGNC::SUMMARY){
|
||||||
|
std::cout << "final iterations: " << iter << std::endl;
|
||||||
|
std::cout << "final mu: " << mu << std::endl;
|
||||||
|
std::cout << "final weights: " << weights << std::endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise update mu
|
// otherwise update mu
|
||||||
mu = updateMu(mu);
|
mu = updateMu(mu);
|
||||||
|
@ -160,7 +184,7 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// initialize the gnc parameter mu such that loss is approximately convex
|
/// initialize the gnc parameter mu such that loss is approximately convex (remark 5 in GNC paper)
|
||||||
double initializeMu() const {
|
double initializeMu() const {
|
||||||
// compute largest error across all factors
|
// compute largest error across all factors
|
||||||
double rmax_sq = 0.0;
|
double rmax_sq = 0.0;
|
||||||
|
@ -305,9 +329,7 @@ TEST(GncOptimizer, gncConstructorWithRobustGraphAsInput) {
|
||||||
LevenbergMarquardtParams lmParams;
|
LevenbergMarquardtParams lmParams;
|
||||||
GncParams<LevenbergMarquardtParams> gncParams(lmParams);
|
GncParams<LevenbergMarquardtParams> gncParams(lmParams);
|
||||||
auto gnc = GncOptimizer<GncParams<LevenbergMarquardtParams>>(fg_robust, initial, gncParams);
|
auto gnc = GncOptimizer<GncParams<LevenbergMarquardtParams>>(fg_robust, initial, gncParams);
|
||||||
// fg.print("fg\n");
|
|
||||||
// fg_robust.print("fg_robust\n");
|
|
||||||
// gnc.getFactors().print("gnc\n");
|
|
||||||
// make sure that when parsing the graph is transformed into one without robust loss
|
// make sure that when parsing the graph is transformed into one without robust loss
|
||||||
CHECK( fg.equals(gnc.getFactors()) );
|
CHECK( fg.equals(gnc.getFactors()) );
|
||||||
}
|
}
|
||||||
|
@ -470,6 +492,7 @@ TEST(GncOptimizer, optimize) {
|
||||||
|
|
||||||
// .. but graduated nonconvexity ensures both robustness and convergence in the face of nonconvexity
|
// .. but graduated nonconvexity ensures both robustness and convergence in the face of nonconvexity
|
||||||
GncParams<GaussNewtonParams> gncParams(gnParams);
|
GncParams<GaussNewtonParams> gncParams(gnParams);
|
||||||
|
gncParams.setVerbosityGNC(GncParams<GaussNewtonParams>::VerbosityGNC::VALUES);
|
||||||
auto gnc = GncOptimizer<GncParams<GaussNewtonParams>>(fg, initial, gncParams);
|
auto gnc = GncOptimizer<GncParams<GaussNewtonParams>>(fg, initial, gncParams);
|
||||||
Values gnc_result = gnc.optimize();
|
Values gnc_result = gnc.optimize();
|
||||||
CHECK(assert_equal(Point2(0.0,0.0), gnc_result.at<Point2>(X(1)), 1e-3));
|
CHECK(assert_equal(Point2(0.0,0.0), gnc_result.at<Point2>(X(1)), 1e-3));
|
||||||
|
|
Loading…
Reference in New Issue