Commit a36d4a7c authored by Konstantinos Chatzilygeroudis's avatar Konstantinos Chatzilygeroudis
Browse files

All kernel and mean functions can be tuned (if they have params)

parent 03762f34
......@@ -123,7 +123,7 @@ protected:
};
template <typename Params>
struct MeanOffset {
struct MeanOffset : public mean::BaseMean<Params> {
MeanOffset(size_t dim_out = 1) {}
template <typename GP>
......@@ -142,7 +142,7 @@ struct MeanOffset {
};
template <typename Params>
struct MeanRotation {
struct MeanRotation : public mean::BaseMean<Params> {
MeanRotation(size_t dim_out = 1) {}
template <typename GP>
......@@ -166,7 +166,7 @@ struct MeanRotation {
};
template <typename Params>
struct MeanComplet {
struct MeanComplet : public mean::BaseMean<Params> {
MeanComplet(size_t dim_out = 1) {}
template <typename GP>
......
......@@ -55,7 +55,7 @@ namespace limbo {
BO_PARAM(double, sigma_sq, 1);
BO_PARAM(double, l, 1);
};
}
} // namespace defaults
namespace kernel {
/**
@ingroup kernel
......@@ -72,16 +72,50 @@ namespace limbo {
*/
template <typename Params>
struct Exp : public BaseKernel<Params, Exp<Params>> {
Exp(size_t dim = 1) {}
Exp(size_t dim = 1) : _sf2(Params::kernel_exp::sigma_sq()), _l(Params::kernel_exp::l())
{
_h_params = Eigen::VectorXd(2);
_h_params << std::log(_l), std::log(std::sqrt(_sf2));
}
size_t params_size() const { return 2; }
// Return the hyper parameters in log-space
Eigen::VectorXd params() const { return _h_params; }
// We expect the input parameters to be in log-space
void set_params(const Eigen::VectorXd& p)
{
_h_params = p;
_l = std::exp(p(0));
_sf2 = std::exp(2.0 * p(1));
}
double kernel(const Eigen::VectorXd& v1, const Eigen::VectorXd& v2) const
{
double l_sq = Params::kernel_exp::l() * Params::kernel_exp::l();
double r = (v1 - v2).squaredNorm();
return Params::kernel_exp::sigma_sq() * (std::exp(-0.5 * r / l_sq));
double l_sq = _l * _l;
double r = (v1 - v2).squaredNorm() / l_sq;
return _sf2 * std::exp(-0.5 * r);
}
Eigen::VectorXd gradient(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2) const
{
Eigen::VectorXd grad(this->params_size());
double l_sq = _l * _l;
double r = (x1 - x2).squaredNorm() / l_sq;
double k = _sf2 * std::exp(-0.5 * r);
grad(0) = r * k;
grad(1) = 2 * k;
return grad;
}
protected:
double _sf2, _l;
Eigen::VectorXd _h_params;
};
}
}
} // namespace kernel
} // namespace limbo
#endif
......@@ -129,17 +129,19 @@ namespace limbo {
double _noise;
double _noise_p;
size_t params_size() const
{
return 0;
}
// Functions for compilation issues
// They should never be called like this
size_t params_size() const { return 0; }
Eigen::VectorXd params() const { return Eigen::VectorXd(); }
Eigen::VectorXd params() const
void set_params(const Eigen::VectorXd& p) {}
Eigen::VectorXd gradient(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2) const
{
return Eigen::VectorXd();
// This should never be called!
assert(false);
}
void set_params(const Eigen::VectorXd&) {}
};
} // namespace kernel
} // namespace limbo
......
......@@ -56,7 +56,7 @@ namespace limbo {
/// @ingroup kernel_defaults
BO_PARAM(double, l, 1);
};
}
} // namespace defaults
namespace kernel {
/**
@ingroup kernel
......@@ -82,21 +82,42 @@ namespace limbo {
*/
template <typename Params>
struct MaternFiveHalves : public BaseKernel<Params, MaternFiveHalves<Params>> {
MaternFiveHalves(size_t dim = 1) {}
MaternFiveHalves(size_t dim = 1) : _sf2(Params::kernel_maternfivehalves::sigma_sq()), _l(Params::kernel_maternfivehalves::l())
{
_h_params = Eigen::VectorXd(2);
_h_params << std::log(_l), std::log(std::sqrt(_sf2));
}
size_t params_size() const { return 2; }
// Return the hyper parameters in log-space
Eigen::VectorXd params() const { return _h_params; }
// We expect the input parameters to be in log-space
void set_params(const Eigen::VectorXd& p)
{
_h_params = p;
_l = std::exp(p(0));
_sf2 = std::exp(2.0 * p(1));
}
double kernel(const Eigen::VectorXd& v1, const Eigen::VectorXd& v2) const
{
double d = (v1 - v2).norm();
double d_sq = d * d;
double l = Params::kernel_maternfivehalves::l();
double l_sq = l * l;
double term1 = std::sqrt(5) * d / l;
double l_sq = _l * _l;
double term1 = std::sqrt(5) * d / _l;
double term2 = 5. * d_sq / (3. * l_sq);
return Params::kernel_maternfivehalves::sigma_sq() * (1 + term1 + term2) * std::exp(-term1);
return _sf2 * (1 + term1 + term2) * std::exp(-term1);
}
protected:
double _sf2, _l;
Eigen::VectorXd _h_params;
};
}
}
} // namespace kernel
} // namespace limbo
#endif
......@@ -56,7 +56,7 @@ namespace limbo {
/// @ingroup kernel_defaults
BO_PARAM(double, l, 1);
};
}
} // namespace defaults
namespace kernel {
/**
@ingroup kernel
......@@ -80,17 +80,39 @@ namespace limbo {
*/
template <typename Params>
struct MaternThreeHalves : public BaseKernel<Params, MaternThreeHalves<Params>> {
MaternThreeHalves(size_t dim = 1) {}
MaternThreeHalves(size_t dim = 1) : _sf2(Params::kernel_maternthreehalves::sigma_sq()), _l(Params::kernel_maternthreehalves::l())
{
_h_params = Eigen::VectorXd(2);
_h_params << std::log(_l), std::log(std::sqrt(_sf2));
}
size_t params_size() const { return 2; }
// Return the hyper parameters in log-space
Eigen::VectorXd params() const { return _h_params; }
// We expect the input parameters to be in log-space
void set_params(const Eigen::VectorXd& p)
{
_h_params = p;
_l = std::exp(p(0));
_sf2 = std::exp(2.0 * p(1));
}
double kernel(const Eigen::VectorXd& v1, const Eigen::VectorXd& v2) const
{
double d = (v1 - v2).norm();
double term = std::sqrt(3) * d / Params::kernel_maternthreehalves::l();
double term = std::sqrt(3) * d / _l;
return Params::kernel_maternthreehalves::sigma_sq() * (1 + term) * std::exp(-term);
return _sf2 * (1 + term) * std::exp(-term);
}
protected:
double _sf2, _l;
Eigen::VectorXd _h_params;
};
}
}
} // namespace kernel
} // namespace limbo
#endif
......@@ -65,16 +65,37 @@ namespace limbo {
*/
template <typename Params>
struct Constant : public BaseMean<Params> {
Constant(size_t dim_out = 1) : _dim_out(dim_out) {}
Constant(size_t dim_out = 1) : _dim_out(dim_out), _constant(Params::mean_constant::constant()) {}
template <typename GP>
Eigen::VectorXd operator()(const Eigen::VectorXd& v, const GP&) const
{
return Eigen::VectorXd::Constant(_dim_out, Params::mean_constant::constant());
return Eigen::VectorXd::Constant(_dim_out, _constant);
}
template <typename GP>
Eigen::MatrixXd grad(const Eigen::VectorXd& x, const GP& gp) const
{
return Eigen::MatrixXd::Ones(_dim_out, 1);
}
size_t h_params_size() const { return 1; }
Eigen::VectorXd h_params() const
{
Eigen::VectorXd p(1);
p << _constant;
return p;
}
void set_h_params(const Eigen::VectorXd& p)
{
_constant = p(0);
}
protected:
size_t _dim_out;
double _constant;
};
} // namespace mean
} // namespace limbo
......
......@@ -53,6 +53,7 @@ namespace limbo {
/// Functor used to optimize the mean function using the maximum likelihood principle
///
/// For the moment, it ignores the hyperparameters of the underlying mean function, if any
/// @see limbo::model::gp::KernelMeanLFOpt, limbo::model::gp::MeanLFOpt
template <typename Params, typename MeanFunction>
struct FunctionARD : public BaseMean<Params> {
......@@ -104,7 +105,7 @@ namespace limbo {
Eigen::MatrixXd _tr;
Eigen::VectorXd _h_params;
};
}
}
} // namespace mean
} // namespace limbo
#endif
......@@ -443,6 +443,8 @@ namespace limbo {
}
/// load the parameters and the data for the GP from the archive (text or binary)
/// if recompute is true, we do not read the kernel matrix
/// but we recompute it given the data and the hyperparameters
template <typename A>
void load(const std::string& directory, bool recompute = true)
{
......@@ -451,6 +453,8 @@ namespace limbo {
}
/// load the parameters and the data for the GP from the archive (text or binary)
/// if recompute is true, we do not read the kernel matrix
/// but we recompute it given the data and the hyperparameters
template <typename A>
void load(const A& archive, bool recompute = true)
{
......
......@@ -82,7 +82,33 @@ struct Params {
};
};
template <typename GP, typename Archive>
// Different parameters in load to test
struct LoadParams {
struct kernel_exp {
BO_PARAM(double, sigma_sq, 10.0);
BO_PARAM(double, l, 1.);
};
struct kernel : public limbo::defaults::kernel {
};
struct kernel_squared_exp_ard : public limbo::defaults::kernel_squared_exp_ard {
BO_PARAM(double, sigma_sq, 10.0);
};
struct opt_rprop : public limbo::defaults::opt_rprop {
};
struct opt_parallelrepeater : public limbo::defaults::opt_parallelrepeater {
};
struct kernel_maternfivehalves {
BO_PARAM(double, sigma_sq, 2.);
BO_PARAM(double, l, 0.1);
};
struct mean_constant {
BO_PARAM(double, constant, -1);
};
};
template <typename GP, typename GPLoad, typename Archive>
void test_gp(const std::string& name, bool optimize_hp = true)
{
using namespace limbo;
......@@ -110,7 +136,7 @@ void test_gp(const std::string& name, bool optimize_hp = true)
// gp.template save<Archive>(name);
// attempt to load -- use only the name
GP gp2(3, 1);
GPLoad gp2(3, 1);
gp2.template load<Archive>(name);
BOOST_CHECK_EQUAL(gp.nb_samples(), gp2.nb_samples());
......@@ -126,7 +152,7 @@ void test_gp(const std::string& name, bool optimize_hp = true)
}
// attempt to load without recomputing
GP gp3(3, 1);
GPLoad gp3(3, 1);
Archive a3(name);
gp3.load(a3, false);
......@@ -144,18 +170,20 @@ void test_gp(const std::string& name, bool optimize_hp = true)
BOOST_AUTO_TEST_CASE(test_text_archive)
{
test_gp<limbo::model::GPOpt<Params>, limbo::serialize::TextArchive>("/tmp/gp_opt_text");
test_gp<limbo::model::GPBasic<Params>, limbo::serialize::TextArchive>("/tmp/gp_basic_text", false);
test_gp<limbo::model::GPOpt<Params>, limbo::model::GPOpt<LoadParams>, limbo::serialize::TextArchive>("/tmp/gp_opt_text");
test_gp<limbo::model::GPBasic<Params>, limbo::model::GPBasic<LoadParams>, limbo::serialize::TextArchive>("/tmp/gp_basic_text", false);
using GPMean = limbo::model::GP<Params, limbo::kernel::MaternFiveHalves<Params>, limbo::mean::FunctionARD<Params, limbo::mean::Constant<Params>>, limbo::model::gp::MeanLFOpt<Params>>;
test_gp<GPMean, limbo::serialize::TextArchive>("/tmp/gp_mean_text");
using GPMean = limbo::model::GP<Params, limbo::kernel::MaternFiveHalves<Params>, limbo::mean::Constant<Params>, limbo::model::gp::MeanLFOpt<Params>>;
using GPMeanLoad = limbo::model::GP<LoadParams, limbo::kernel::MaternFiveHalves<LoadParams>, limbo::mean::Constant<LoadParams>, limbo::model::gp::MeanLFOpt<LoadParams>>;
test_gp<GPMean, GPMeanLoad, limbo::serialize::TextArchive>("/tmp/gp_mean_text");
}
BOOST_AUTO_TEST_CASE(test_bin_archive)
{
test_gp<limbo::model::GPOpt<Params>, limbo::serialize::BinaryArchive>("/tmp/gp_opt_bin");
test_gp<limbo::model::GPBasic<Params>, limbo::serialize::BinaryArchive>("/tmp/gp_basic_bin", false);
test_gp<limbo::model::GPOpt<Params>, limbo::model::GPOpt<LoadParams>, limbo::serialize::BinaryArchive>("/tmp/gp_opt_bin");
test_gp<limbo::model::GPBasic<Params>, limbo::model::GPBasic<LoadParams>, limbo::serialize::BinaryArchive>("/tmp/gp_basic_bin", false);
using GPMean = limbo::model::GP<Params, limbo::kernel::MaternFiveHalves<Params>, limbo::mean::FunctionARD<Params, limbo::mean::Constant<Params>>, limbo::model::gp::MeanLFOpt<Params>>;
test_gp<GPMean, limbo::serialize::BinaryArchive>("/tmp/gp_mean_bin");
using GPMean = limbo::model::GP<Params, limbo::kernel::MaternFiveHalves<Params>, limbo::mean::Constant<Params>, limbo::model::gp::MeanLFOpt<Params>>;
using GPMeanLoad = limbo::model::GP<LoadParams, limbo::kernel::MaternFiveHalves<LoadParams>, limbo::mean::Constant<LoadParams>, limbo::model::gp::MeanLFOpt<LoadParams>>;
test_gp<GPMean, GPMeanLoad, limbo::serialize::BinaryArchive>("/tmp/gp_mean_bin");
}
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