Commit 3fbe5b20 authored by Konstantinos Chatzilygeroudis's avatar Konstantinos Chatzilygeroudis
Browse files

Adding binary archive and small fixes

parent 41f8f166
......@@ -244,6 +244,7 @@ namespace limbo {
if (update_obs_mean)
this->_compute_obs_mean();
if (update_full_kernel)
this->_compute_full_kernel();
else
......@@ -422,10 +423,12 @@ namespace limbo {
void save(A& archive)
{
archive.save(_kernel_function.h_params(), "kernel_params");
// should we save parameters of the mean function as well?
// archive.save(_mean_function.h_params(), "mean_params");
archive.save(_samples, "samples");
archive.save(_observations, "observations");
}
/// load the parameters and the data for the GP from the archive (text or binary)
template <typename A>
void load(A& archive)
......@@ -436,13 +439,20 @@ namespace limbo {
_kernel_function.set_h_params(h_params);
// should we save parameters of the mean function as well?
std::vector<Eigen::VectorXd> samples;
archive.load(samples, "samples");
_samples.clear();
archive.load(_samples, "samples");
archive.load(_observations, "observations");
std::vector<Eigen::VectorXd> observations;
archive.load(observations, "observations");
_dim_in = _samples[0].size();
_kernel_function = KernelFunction(_dim_in);
_dim_out = _observations.cols();
_mean_function = MeanFunction(_dim_out);
_mean_observation = _observations.colwise().mean();
compute(samples, observations);
recompute(true, true);
}
protected:
......
#include <cassert>
#include <iostream>
#include <sstream>
#include <string>
// Quick hack for definition of 'I' in <complex.h>
#undef I
#include <boost/filesystem.hpp>
#include <Eigen/Core>
namespace limbo {
namespace serialize {
class BinaryArchive {
public:
BinaryArchive(const std::string& dir_name) : _dir_name(dir_name) {}
/// write an Eigen::Matrix*
void save(const Eigen::MatrixXd& v, const std::string& object_name)
{
_create_directory();
std::ofstream out(fname(object_name).c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
_write_binary(out, v);
out.close();
}
/// write a vector of Eigen::Vector*
template <typename T>
void save(const std::vector<T>& v, const std::string& object_name)
{
_create_directory();
std::stringstream s;
int size = v.size();
s.write((char*)(&size), sizeof(int));
for (auto& x : v) {
_write_binary(s, x);
}
std::ofstream out(fname(object_name).c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
out << s.rdbuf();
out.close();
}
/// load an Eigen matrix (or vector)
template <typename M>
void load(M& m, const std::string& object_name)
{
std::ifstream in(fname(object_name).c_str(), std::ios::in | std::ios::binary);
_read_binary(in, m);
in.close();
}
/// load a vector of Eigen::Vector*
template <typename V>
void load(std::vector<V>& m_list, const std::string& object_name)
{
m_list.clear();
std::ifstream in(fname(object_name).c_str(), std::ios::in | std::ios::binary);
int size;
in.read((char*)(&size), sizeof(int));
for (int i = 0; i < size; i++) {
V v;
_read_binary(in, v);
m_list.push_back(v);
}
in.close();
assert(!m_list.empty());
}
std::string fname(const std::string& object_name) const
{
return _dir_name + "/" + object_name + ".bin";
}
protected:
std::string _dir_name;
Eigen::IOFormat _fmt;
void _create_directory()
{
boost::filesystem::path my_path(_dir_name);
boost::filesystem::create_directory(my_path);
}
template <class Matrix, class Stream>
void _write_binary(Stream& out, const Matrix& matrix)
{
typename Matrix::Index rows = matrix.rows(), cols = matrix.cols();
out.write((char*)(&rows), sizeof(typename Matrix::Index));
out.write((char*)(&cols), sizeof(typename Matrix::Index));
out.write((char*)matrix.data(), rows * cols * sizeof(typename Matrix::Scalar));
}
template <class Matrix, class Stream>
void _read_binary(Stream& in, Matrix& matrix)
{
typename Matrix::Index rows = 0, cols = 0;
in.read((char*)(&rows), sizeof(typename Matrix::Index));
in.read((char*)(&cols), sizeof(typename Matrix::Index));
matrix.resize(rows, cols);
in.read((char*)matrix.data(), rows * cols * sizeof(typename Matrix::Scalar));
}
};
} // namespace serialize
} // namespace limbo
\ No newline at end of file
......@@ -24,6 +24,7 @@ namespace limbo {
std::ofstream ofs(fname(object_name).c_str());
ofs << v.format(_fmt) << std::endl;
}
/// write a vector of Eigen::Vector*
template <typename T>
void save(const std::vector<T>& v, const std::string& object_name)
......@@ -76,6 +77,7 @@ namespace limbo {
boost::filesystem::path my_path(_dir_name);
boost::filesystem::create_directory(my_path);
}
std::vector<std::vector<double>> _load(const std::string& object_name)
{
std::ifstream ifs(fname(object_name).c_str());
......
......@@ -52,6 +52,7 @@
#include <boost/test/unit_test.hpp>
#include <limbo/model/gp.hpp>
#include <limbo/serialize/binary_archive.hpp>
#include <limbo/serialize/text_archive.hpp>
struct Params {
......@@ -89,18 +90,17 @@ BOOST_AUTO_TEST_CASE(test_text_archive)
gp.optimize_hyperparams();
// attempt to save
serialize::TextArchive a1("/tmp/test_model.dat");
serialize::TextArchive a1("/tmp/test_model_text");
gp.save(a1);
// attempt to read
// attempt to load
model::GPOpt<Params> gp2(3, 1);
serialize::TextArchive a2("/tmp/test_model.dat");
serialize::TextArchive a2("/tmp/test_model_text");
gp2.load(a2);
BOOST_CHECK_EQUAL(gp.nb_samples(), gp2.nb_samples());
// check that the two GP make the same predictions
// check that the two GPs make the same predictions
size_t k = 1000;
for (size_t i = 0; i < k; i++) {
Eigen::VectorXd s = tools::random_vector(3).array() * 4.0 - 2.0;
......@@ -113,4 +113,41 @@ BOOST_AUTO_TEST_CASE(test_text_archive)
BOOST_AUTO_TEST_CASE(test_bin_archive)
{
using namespace limbo;
// our data (3-D inputs, 1-D outputs)
std::vector<Eigen::VectorXd> samples;
std::vector<Eigen::VectorXd> observations;
size_t n = 8;
for (size_t i = 0; i < n; i++) {
Eigen::VectorXd s = tools::random_vector(3).array() * 4.0 - 2.0;
samples.push_back(s);
observations.push_back(tools::make_vector(std::cos(s(0) * s(1) * s(2))));
}
// 3-D inputs, 1-D outputs
model::GPOpt<Params> gp(3, 1);
gp.compute(samples, observations);
gp.optimize_hyperparams();
// attempt to save
serialize::BinaryArchive a1("/tmp/test_model_bin");
gp.save(a1);
// attempt to load
model::GPOpt<Params> gp2(3, 1);
serialize::BinaryArchive a2("/tmp/test_model_bin");
gp2.load(a2);
BOOST_CHECK_EQUAL(gp.nb_samples(), gp2.nb_samples());
// check that the two GPs make the same predictions
size_t k = 1000;
for (size_t i = 0; i < k; i++) {
Eigen::VectorXd s = tools::random_vector(3).array() * 4.0 - 2.0;
auto v1 = gp.query(s);
auto v2 = gp.query(s);
BOOST_CHECK_CLOSE(std::get<0>(v1)[0], std::get<0>(v2)[0], 1e-10);
BOOST_CHECK_CLOSE(std::get<1>(v1), std::get<1>(v2), 1e-10);
}
}
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