Я хочу использовать Ceres для оптимизации функции n параметров. Как найти градиент этой функции неясно, хотя у меня есть четко определенная стоимость. До сих пор я использовал GSL с числовым дифференцированием, но думал, что попробую использовать Ceres с автоматической разницей.
Я взглянул на игрушечный пример helloworld_analytic_diff.cc в котором они используют AutoDiff, чтобы минимизировать функцию f (x) = 0.5 (10 — x) ^ 2 и прочитать учебник, поэтому я подумал, что я попытаюсь расширить это до двумерной функции f (x, y) = (10 -x) ^ 2 + (20-y) ^ 2, глобальный минимум которого равен x, y = 10, 20. Но я немного застрял в этом:
#include "ceres/ceres.h"#include "glog/logging.h"
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve;struct CostFunctor {
template <typename T> bool operator()(const T* const x, T* residual) const {
const T x1 = x[0];
const T y1 = x[1];
residual[0] = (10.0-x[0]) + (20.0-x[1]);
return true;
}
};
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
double x[2] = {0.5, -3.0};
const double initial_x[2] = {0.5, -3.0};
Problem problem;
CostFunction* cost_function = new AutoDiffCostFunction<CostFunctor, 1, 2>(new CostFunctor);
problem.AddResidualBlock(cost_function, NULL, &x[0]);
// Run the solver!
Solver::Options options;
options.minimizer_progress_to_stdout = true;
Solver::Summary summary;
Solve(options, &problem, &summary);
std::cout << summary.BriefReport() << "\n";
std::cout << "x : " << initial_x[0] << ", " << initial_x[0]
<< " -> " << x[0] << ", " << x[1]<< "\n";
return 0;
}
Однако, если я запустлю это, то получится что-то неправильное, в зависимости от первоначального предположения:
Ceres Solver Report: Iterations: 3, Initial cost: 5.281250e+02, Final cost: 3.667046e-16, Termination: CONVERGENCE
x : 0.5, 0.5 -> 16.75, 13.25
Есть идеи о том, что я здесь сделал неправильно?
Большое спасибо!
Ваш функтор стоимости неверен.
проблема оптимизации, которую вы решаете
и не
(10-х) ^ 2 + (20-ий) ^ 2,
то, что вы должны сделать здесь, это иметь два функтора стоимости, что-то вроде следующего:
struct CostFunctor1 {
template <typename T> bool operator()(const T* const x, T* residual) const {
residual[0] = 10.0-x[0];
return true;
}
};
struct CostFunctor2 {
template <typename T> bool operator()(const T* const x, T* residual) const {
residual[0] = 20.0-x[1];
return true;
}
};
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
double x[2] = {0.5, -3.0};
const double initial_x[2] = {0.5, -3.0};
Problem problem;
problem.AddResidualBlock(new AutoDiffCostFunction<CostFunctor1, 1, 2>(new
CostFunctor1), NULL, &x[0]);
problem.AddResidualBlock(new AutoDiffCostFunction<CostFunctor2, 1, 2>(new
CostFunctor2), NULL, &x[0]);
// Run the solver!
Solver::Options options;
options.minimizer_progress_to_stdout = true;
Solver::Summary summary;
Solve(options, &problem, &summary);
std::cout << summary.BriefReport() << "\n";
std::cout << "x : " << initial_x[0] << ", " << initial_x[0]
<< " -> " << x[0] << ", " << x[1]<< "\n";
return 0;
}
Других решений пока нет …