Commit cf68fda5 authored by Jean-Baptiste Mouret's avatar Jean-Baptiste Mouret
Browse files

first version of ns_ego

parent 14dc004f
...@@ -8,12 +8,12 @@ struct Params { ...@@ -8,12 +8,12 @@ struct Params {
BO_PARAM(int, dump_period, -1); BO_PARAM(int, dump_period, -1);
}; };
struct init { struct init {
BO_PARAM(int, nb_samples, 10); BO_PARAM(int, nb_samples, 21);
// calandra: number of dimensions * 5 // calandra: number of dimensions * 5
// knowles : 11 * dim - 1 // knowles : 11 * dim - 1
}; };
struct maxiterations { struct maxiterations {
BO_PARAM(int, n_iterations, 20); BO_PARAM(int, n_iterations, 30);
}; };
struct ucb : public defaults::ucb {}; struct ucb : public defaults::ucb {};
struct gp_ucb : public defaults::gp_ucb {}; struct gp_ucb : public defaults::gp_ucb {};
...@@ -58,7 +58,28 @@ struct mop2 { ...@@ -58,7 +58,28 @@ struct mop2 {
} }
}; };
// note UCB ne marche pas si fonction positive _ou_ negative? struct Pareto {
template<typename BO>
void operator()(const BO& opt) {
if (opt.iteration() % 10 != 0)
return;
auto p_model = opt.model_pareto_front(0, 1.0, 0.005);
auto p_data = opt.data_pareto_front();
std::string it = std::to_string(opt.iteration());
std::string model = it + "_pareto_model.dat";
std::string data = it + "_pareto_data.dat";
std::ofstream pareto_model(model.c_str()),
pareto_data(data.c_str());
for (auto x : p_model)
pareto_model << std::get<1>(x).transpose() << " "
<< (std::get<1>(x).array() + std::get<2>(x)).transpose() << " "
<< (std::get<1>(x).array() - std::get<2>(x)).transpose() << " "
<< std::endl;
for (auto x : p_data)
pareto_data << std::get<1>(x).transpose() << std::endl;
}
};
int main() { int main() {
...@@ -68,8 +89,7 @@ int main() { ...@@ -68,8 +89,7 @@ int main() {
// typedef model::GP<Params, kernel_t, mean_t> gp_t; // typedef model::GP<Params, kernel_t, mean_t> gp_t;
// typedef acquisition_functions::UCB<Params, gp_t> ucb_t; // typedef acquisition_functions::UCB<Params, gp_t> ucb_t;
//Parego<Params, model_fun<gp_t>, acq_fun<ucb_t> > opt; //Parego<Params, model_fun<gp_t>, acq_fun<ucb_t> > opt;
{ Parego<Params, stat_fun<Pareto> > opt;
Parego<Params> opt;
opt.optimize(mop2()); opt.optimize(mop2());
auto p_model = opt.model_pareto_front(0, 1.0, 0.001); auto p_model = opt.model_pareto_front(0, 1.0, 0.001);
...@@ -84,7 +104,6 @@ int main() { ...@@ -84,7 +104,6 @@ int main() {
<< std::endl; << std::endl;
for (auto x : p_data) for (auto x : p_data)
pareto_data << std::get<1>(x).transpose() << std::endl; pareto_data << std::get<1>(x).transpose() << std::endl;
}
return 0; return 0;
} }
...@@ -15,3 +15,9 @@ def build(bld): ...@@ -15,3 +15,9 @@ def build(bld):
target = 'parego', target = 'parego',
uselib = 'BOOST EIGEN TBB', uselib = 'BOOST EIGEN TBB',
use = 'limbo') use = 'limbo')
obj = bld.program(features = 'cxx',
source = 'ns_ego.cpp',
includes = '. .. ../../',
target = 'ns_ego',
uselib = 'BOOST EIGEN TBB SFERES',
use = 'limbo')
...@@ -18,11 +18,13 @@ namespace limbo { ...@@ -18,11 +18,13 @@ namespace limbo {
namespace defaults { namespace defaults {
struct gp_auto { struct gp_auto {
BO_PARAM(int, n_rprop, 100); BO_PARAM(int, n_rprop, 100);
BO_PARAM(int, rprop_restart, 20); BO_PARAM(int, rprop_restart, 100);
}; };
} }
namespace model { namespace model {
namespace impl { namespace impl {
// launch nprop_restart instances of rprop in parallel
// to optimize the log-likelihood
#ifdef USE_TBB #ifdef USE_TBB
template<typename GP> template<typename GP>
struct RpropOpt { struct RpropOpt {
...@@ -48,8 +50,12 @@ namespace limbo { ...@@ -48,8 +50,12 @@ namespace limbo {
void join(const RpropOpt& y) { void join(const RpropOpt& y) {
_keep_best(y._best_score, y._best_v); _keep_best(y._best_score, y._best_v);
} }
const Eigen::VectorXd& best_v() const { return _best_v; } const Eigen::VectorXd& best_v() const {
double best_score() const { return _best_score; } return _best_v;
}
double best_score() const {
return _best_score;
}
protected: protected:
void _keep_best(float y, const Eigen::VectorXd& v) { void _keep_best(float y, const Eigen::VectorXd& v) {
if (y > _best_score) { if (y > _best_score) {
...@@ -115,7 +121,6 @@ namespace limbo { ...@@ -115,7 +121,6 @@ namespace limbo {
// Eigen::MatrixXd alpha = this->_inverted_kernel * this->_obs_mean; // Eigen::MatrixXd alpha = this->_inverted_kernel * this->_obs_mean;
// Eigen::MatrixXd w = alpha * alpha.transpose() - this->_inverted_kernel; // Eigen::MatrixXd w = alpha * alpha.transpose() - this->_inverted_kernel;
// alpha = K^{-1} * this->_obs_mean; // alpha = K^{-1} * this->_obs_mean;
Eigen::VectorXd alpha = this->_llt.solve(this->_obs_mean); Eigen::VectorXd alpha = this->_llt.solve(this->_obs_mean);
this->_llt.matrixL().adjoint().solveInPlace(alpha); this->_llt.matrixL().adjoint().solveInPlace(alpha);
...@@ -145,12 +150,12 @@ namespace limbo { ...@@ -145,12 +150,12 @@ namespace limbo {
} }
protected: protected:
#ifdef USE_TBB #ifdef USE_TBB
void _optimize_likelihood_tbb() { void _optimize_likelihood_tbb() {
par::init(); par::init();
impl::RpropOpt<GPAuto> r(*this, Params::gp_auto::n_rprop()); impl::RpropOpt<GPAuto> r(*this, Params::gp_auto::n_rprop());
tbb::parallel_reduce(tbb::blocked_range<size_t>(0, Params::gp_auto::rprop_restart()), r); tbb::parallel_reduce(tbb::blocked_range<size_t>(0, Params::gp_auto::rprop_restart()), r);
this->_kernel_function.set_h_params(r.best_v()); this->_kernel_function.set_h_params(r.best_v());
} }
#endif #endif
void _optimize_likelihood() { void _optimize_likelihood() {
double best_score = -std::numeric_limits<float>::max(); double best_score = -std::numeric_limits<float>::max();
......
#ifndef NSEGO_HPP_
#define NSEGO_HPP_
#include <algorithm>
#define VERSION "xxx"
#include <sferes/phen/parameters.hpp>
#include <sferes/gen/evo_float.hpp>
#include <sferes/eval/parallel.hpp>
#include <sferes/modif/dummy.hpp>
#include <sferes/ea/nsga2.hpp>
#include "parego.hpp"
namespace limbo {
namespace ns_ego {
struct SferesParams {
struct evo_float {
typedef sferes::gen::evo_float::mutation_t mutation_t;
typedef sferes::gen::evo_float::cross_over_t cross_over_t;
SFERES_CONST float cross_rate = 0.5f;
SFERES_CONST float mutation_rate = 0.1f;
SFERES_CONST float eta_m = 15.0f;
SFERES_CONST float eta_c = 10.0f;
SFERES_CONST mutation_t mutation_type =
sferes::gen::evo_float::polynomial;
SFERES_CONST cross_over_t cross_over_type =
sferes::gen::evo_float::sbx;
};
struct pop {
SFERES_CONST unsigned size = 100;
SFERES_CONST unsigned nb_gen = 1000;
SFERES_CONST int dump_period = -1;
SFERES_CONST int initial_aleat = 1;
};
struct parameters {
SFERES_CONST float min = 0.0f;
SFERES_CONST float max = 1.0f;
};
};
template<typename M>
class SferesFit {
public:
SferesFit(const std::vector<M>& models) : _models(models) {
}
SferesFit() {}
const std::vector<float>& objs() const {
return _objs;
}
float obj(size_t i) const {
return _objs[i];
}
template<typename Indiv>
void eval(const Indiv& indiv) {
this->_objs.resize(_models.size());
Eigen::VectorXd v(indiv.size());
for (size_t j = 0; j < indiv.size(); ++j)
v[j] = indiv.data(j);
for (size_t i = 0; i < _models.size(); ++i)
this->_objs[i] = _models[i].mu(v);
}
protected:
std::vector<M> _models;
std::vector<float> _objs;
};
}
template <
class Params
, class A2 = boost::parameter::void_
, class A3 = boost::parameter::void_
, class A4 = boost::parameter::void_
, class A5 = boost::parameter::void_
, class A6 = boost::parameter::void_
, class A7 = boost::parameter::void_
>
class NsEgo : public Parego<Params, A2, A3, A4, A5, A6, A7> {
public:
typedef BoBase<Params, obs_type<Eigen::VectorXd>, A2, A3, A4, A5, A6, A7> base_t;
typedef typename base_t::obs_t obs_t;
typedef typename base_t::model_t model_t;
typedef typename base_t::inner_optimization_t inner_optimization_t;
typedef typename base_t::acquisition_function_t acquisition_function_t;
typedef std::tuple<Eigen::VectorXd, Eigen::VectorXd, double> pareto_point_t;
typedef std::vector<pareto_point_t> pareto_t;
template<typename EvalFunction>
void optimize(const EvalFunction& feval, bool reset = true) {
this->_init(feval, reset);
size_t nb_objs = this->_observations[0].size();
using namespace ns_ego;
typedef sferes::gen::EvoFloat<EvalFunction::dim, SferesParams> gen_t;
typedef sferes::phen::Parameters<gen_t, SferesFit<model_t>, SferesParams> phen_t;
typedef sferes::eval::Parallel<SferesParams> eval_t;
typedef boost::fusion::vector<> stat_t;
typedef sferes::modif::Dummy<> modifier_t;
typedef sferes::ea::Nsga2<phen_t, eval_t, stat_t, modifier_t, SferesParams> nsga2_t;
while (this->_samples.size() == 0 || this->_pursue()) {
// compute a model for each dimension
std::vector<model_t> models(nb_objs, model_t(nb_objs));
std::vector<std::vector<double> > uni_obs(nb_objs);
for (size_t i = 0; i < this->_observations.size(); ++i)
for (size_t j = 0; j < this->_observations[i].size(); ++j)
uni_obs[j].push_back(this->_observations[i][j]);
for (size_t i = 0; i < uni_obs.size(); ++i) {
for (size_t j = 0; j < uni_obs[i].size(); ++j)
std::cout << uni_obs[i][j] << " ";
std::cout << std::endl;
models[i].compute(this->_samples, uni_obs[i], 0.0);
}
nsga2_t ea;
ea.set_fit_proto(SferesFit<model_t>(models));
ea.run();
auto pareto_front = ea.pareto_front();
std::sort(pareto_front.begin(), pareto_front.end(),
sferes::fit::compare_objs_lex());
std::ofstream ofs("pareto.dat");
Eigen::VectorXd best_v(EvalFunction::dim);
Eigen::VectorXd x(best_v.size());
double best_sigma = -1;
for (size_t i = 0; i < pareto_front.size(); ++i) {
double sigma = 0;
for (size_t j = 0; j < x.size(); ++j)
x[j] = pareto_front[i]->data(j);
for (size_t j = 0; j < models.size(); ++j)
sigma += models[j].sigma(x);
auto s = Eigen::VectorXd(2);
s << sqrt(2.0), sqrt(2.0);
Eigen::VectorXd p(2);
p << pareto_front[i]->fit().obj(0), pareto_front[i]->fit().obj(1);
ofs << p.transpose()
<< " " << (p + s * sigma).transpose()
<< " " << (p - s * sigma).transpose() << std::endl;
if (sigma > best_sigma) {
best_sigma = sigma;
best_v = x;
}
}
this->add_new_sample(best_v, feval(best_v));
this->_iteration++;
std::cout << this->_iteration << " | " << best_v.transpose() << std::endl;
}
}
protected:
void _update_stats() {
boost::fusion::for_each(this->_stat, RefreshStat_f<NsEgo>(*this));
}
};
}
#endif
#ifndef PARALLEL_HPP_ #ifndef LIMBO_PARALLEL_HPP_
#define PARALLEL_HPP_ #define LIMBO_PARALLEL_HPP_
#include <vector>
#ifdef USE_TBB #ifdef USE_TBB
#include <tbb/concurrent_vector.h> #include <tbb/concurrent_vector.h>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define PAREGO_HPP_ #define PAREGO_HPP_
#include <algorithm> #include <algorithm>
#include "limbo.hpp"
#include "bo_base.hpp" #include "bo_base.hpp"
#include "pareto.hpp" #include "pareto.hpp"
...@@ -98,7 +99,11 @@ namespace limbo { ...@@ -98,7 +99,11 @@ namespace limbo {
return pareto::pareto_set(_pack_data(points, objs, sigma)); return pareto::pareto_set(_pack_data(points, objs, sigma));
} }
protected: protected:
void _update_stats() {
boost::fusion::for_each(this->_stat, RefreshStat_f<Parego>(*this));
}
pareto_t _pack_data(const std::vector<Eigen::VectorXd>& points, pareto_t _pack_data(const std::vector<Eigen::VectorXd>& points,
const std::vector<Eigen::VectorXd>& objs, const std::vector<Eigen::VectorXd>& objs,
const std::vector<double>& sigma) const { const std::vector<double>& sigma) const {
......
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
#ifndef RAND_HPP_ #ifndef LIMBO_RAND_HPP_
#define RAND_HPP_ #define LIMBO_RAND_HPP_
#include <cstdlib> #include <cstdlib>
#include <cmath> #include <cmath>
......
#ifndef STAT_HPP_ #ifndef LIMBO_STAT_HPP_
#define STAT_HPP_ #define LIMBO_STAT_HPP_
#include <fstream> #include <fstream>
#include <string> #include <string>
......
...@@ -35,8 +35,8 @@ ...@@ -35,8 +35,8 @@
#ifndef SYS_HPP_ #ifndef LIMBO_SYS_HPP_
#define SYS_HPP_ #define LIMBO_SYS_HPP_
#include <ctime> #include <ctime>
#include <unistd.h> #include <unistd.h>
......
...@@ -15,6 +15,7 @@ def options(opt): ...@@ -15,6 +15,7 @@ def options(opt):
opt.load('compiler_c') opt.load('compiler_c')
opt.load('eigen') opt.load('eigen')
opt.load('tbb') opt.load('tbb')
opt.load('sferes')
def configure(conf): def configure(conf):
print("configuring b-optimize") print("configuring b-optimize")
...@@ -22,6 +23,7 @@ def configure(conf): ...@@ -22,6 +23,7 @@ def configure(conf):
conf.load('compiler_c') conf.load('compiler_c')
conf.load('eigen') conf.load('eigen')
conf.load('tbb') conf.load('tbb')
conf.load('sferes')
common_flags = "-Wall -std=c++11 -fcolor-diagnostics" common_flags = "-Wall -std=c++11 -fcolor-diagnostics"
...@@ -30,9 +32,13 @@ def configure(conf): ...@@ -30,9 +32,13 @@ def configure(conf):
min_version='1.35') min_version='1.35')
conf.check_eigen() conf.check_eigen()
conf.check_tbb() conf.check_tbb()
conf.check_sferes()
if conf.is_defined('USE_TBB'): if conf.is_defined('USE_TBB'):
common_flags += " -DUSE_TBB " common_flags += " -DUSE_TBB "
if conf.is_defined('USE_SFERES'):
common_flags += " -DUSE_SFERES "
# release # release
opt_flags = common_flags + ' -O3 -msse2 -ggdb3' opt_flags = common_flags + ' -O3 -msse2 -ggdb3'
conf.env['CXXFLAGS'] = cxxflags + opt_flags.split(' ') conf.env['CXXFLAGS'] = cxxflags + opt_flags.split(' ')
......
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