Commit 40d35c16 authored by Konstantinos Chatzilygeroudis's avatar Konstantinos Chatzilygeroudis Committed by GitHub
Browse files

Merge pull request #166 from resibots/acqui_opt_grad

Enable acquisition function optimization with gradients
parents ca836aeb d769f2d9
......@@ -114,7 +114,7 @@ Template
size_t dim_in() const { return _model.dim_in(); }
size_t dim_out() const { return _model.dim_out(); }
template <typename AggregatorFunction>
double operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun) const
limbo::opt::eval_t operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun, bool gradient) const
{
// code
}
......
......@@ -105,13 +105,14 @@ public:
size_t dim_out() const { return _model.dim_out(); }
template <typename AggregatorFunction>
double operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun) const
limbo::opt::eval_t operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun, bool gradient) const
{
assert(!gradient);
// double mu, sigma;
// std::tie(mu, sigma) = _model.query(v);
// return (mu + Params::ucb::alpha() * sqrt(sigma));
return (sqrt(_model.sigma(v)));
return limbo::opt::no_grad(std::sqrt(_model.sigma(v)));
}
protected:
......
......@@ -50,6 +50,7 @@
#include <Eigen/Core>
#include <limbo/tools/macros.hpp>
#include <limbo/opt/optimizer.hpp>
namespace limbo {
namespace defaults {
......@@ -80,8 +81,9 @@ namespace limbo {
size_t dim_out() const { return _model.dim_out(); }
template <typename AggregatorFunction>
double operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun) const
opt::eval_t operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun, bool gradient) const
{
assert(!gradient);
Eigen::VectorXd mu;
double sigma_sq;
std::tie(mu, sigma_sq) = _model.query(v);
......@@ -89,7 +91,7 @@ namespace limbo {
// If \sigma(x) = 0 or we do not have any observation yet we return 0
if (sigma < 1e-10 || _model.samples().size() < 1)
return 0.0;
return opt::no_grad(0.0);
// Compute EI(x)
// First find the best so far (predicted) observation
......@@ -104,7 +106,7 @@ namespace limbo {
double phi = std::exp(-0.5 * std::pow(Z, 2.0)) / std::sqrt(2.0 * M_PI);
double Phi = 0.5 * std::erfc(-Z / std::sqrt(2)); //0.5 * (1.0 + std::erf(Z / std::sqrt(2)));
return X * Phi + sigma * phi;
return opt::no_grad(X * Phi + sigma * phi);
}
protected:
......
......@@ -48,6 +48,7 @@
#include <Eigen/Core>
#include <limbo/tools/macros.hpp>
#include <limbo/opt/optimizer.hpp>
namespace limbo {
namespace defaults {
......@@ -91,12 +92,13 @@ namespace limbo {
size_t dim_out() const { return _model.dim_out(); }
template <typename AggregatorFunction>
double operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun) const
opt::eval_t operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun, bool gradient) const
{
assert(!gradient);
Eigen::VectorXd mu;
double sigma;
std::tie(mu, sigma) = _model.query(v);
return (afun(mu) + _beta * std::sqrt(sigma));
return opt::no_grad(afun(mu) + _beta * std::sqrt(sigma));
}
protected:
......
......@@ -48,6 +48,7 @@
#include <Eigen/Core>
#include <limbo/tools/macros.hpp>
#include <limbo/opt/optimizer.hpp>
namespace limbo {
namespace defaults {
......@@ -78,12 +79,13 @@ namespace limbo {
size_t dim_out() const { return _model.dim_out(); }
template <typename AggregatorFunction>
double operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun) const
opt::eval_t operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun, bool gradient) const
{
assert(!gradient);
Eigen::VectorXd mu;
double sigma;
std::tie(mu, sigma) = _model.query(v);
return (afun(mu) + Params::acqui_ucb::alpha() * sqrt(sigma));
return opt::no_grad(afun(mu) + Params::acqui_ucb::alpha() * sqrt(sigma));
}
protected:
......
......@@ -87,23 +87,23 @@ namespace limbo {
/**
The classic Bayesian optimization algorithm.
\\rst
\rst
References: :cite:`brochu2010tutorial,Mockus2013`
\\endrst
\endrst
This class takes the same template parameters as BoBase. It adds:
\\rst
\rst
+---------------------+------------+----------+---------------+
|type |typedef | argument | default |
+=====================+============+==========+===============+
|acqui. optimizer |acqui_opt_t | acquiopt | see below |
+---------------------+------------+----------+---------------+
\\endrst
\endrst
The default value of acqui_opt_t is:
- ``opt::Cmaes<Params>`` if libcmaes was found in `waf configure`
- ``opt::NLOptNoGrad<Params, nlopt::GN_DIRECT_L_RAND>`` if NLOpt was found but libcmaes was not found
- ``opt::GridSearch<Params>`` otherwise (please do not use this: the algorithm will not work at all!)
- ``opt::NLOptNoGrad<Params, nlopt::GN_DIRECT_L_RAND>`` if NLOpt was found in `waf configure`
- ``opt::Cmaes<Params>`` if libcmaes was found but NLOpt was not found
- ``opt::GridSearch<Params>`` otherwise (please do not use this: the algorithm will not work as expected!)
*/
template <class Params,
class A1 = boost::parameter::void_,
......@@ -151,9 +151,8 @@ namespace limbo {
while (!this->_stop(*this, afun)) {
acquisition_function_t acqui(_model, this->_current_iteration);
// we do not have gradient in our current acquisition function
auto acqui_optimization =
[&](const Eigen::VectorXd& x, bool g) { return opt::no_grad(acqui(x, afun)); };
[&](const Eigen::VectorXd& x, bool g) { return acqui(x,afun,g); };
Eigen::VectorXd starting_point = tools::random_vector(StateFunction::dim_in);
Eigen::VectorXd new_sample = acqui_optimizer(acqui_optimization, starting_point, true);
bool blacklisted = !this->eval_and_add(sfun, new_sample);
......
......@@ -80,7 +80,7 @@ namespace limbo {
point[dim_in] = x;
if (dim_in == current.size() - 1) {
auto q = bo.model().query(point);
double acqui = typename BO::acquisition_function_t(bo.model(), bo.current_iteration())(point, afun);
double acqui = opt::fun(typename BO::acquisition_function_t(bo.model(), bo.current_iteration())(point, afun, false));
ofs << point.transpose() << " "
<< std::get<0>(q).transpose() << " "
<< std::get<1>(q) << " "
......
......@@ -71,11 +71,11 @@ namespace limbo {
if (!blacklisted && !bo.samples().empty()) {
std::tie(mu, sigma) = bo.model().query(bo.samples().back());
acqui = typename BO::acquisition_function_t(bo.model(), bo.current_iteration())(bo.samples().back(), afun);
acqui = opt::fun(typename BO::acquisition_function_t(bo.model(), bo.current_iteration())(bo.samples().back(), afun, false));
}
else if (!bo.bl_samples().empty()) {
std::tie(mu, sigma) = bo.model().query(bo.bl_samples().back());
acqui = typename BO::acquisition_function_t(bo.model(), bo.current_iteration())(bo.bl_samples().back(), afun);
acqui = opt::fun(typename BO::acquisition_function_t(bo.model(), bo.current_iteration())(bo.bl_samples().back(), afun, false));
}
else
return;
......
......@@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE(test_gp_no_samples_acqui_opt)
// we do not have gradient in our current acquisition function
auto acqui_optimization =
[&](const Eigen::VectorXd& x, bool g) { return opt::no_grad(acqui(x, FirstElem())); };
[&](const Eigen::VectorXd& x, bool g) { return acqui(x, FirstElem(), g); };
Eigen::VectorXd starting_point = tools::random_vector(2);
Eigen::VectorXd test = acqui_optimizer(acqui_optimization, starting_point, true);
BOOST_CHECK(test(0) < 1e-5);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment