DMP_BBO library
ModelParametersGMR.cpp
Go to the documentation of this file.
1 
24 #include <boost/serialization/export.hpp>
25 #include <boost/serialization/vector.hpp>
26 #include <boost/archive/text_iarchive.hpp>
27 #include <boost/archive/text_oarchive.hpp>
28 #include <boost/archive/xml_iarchive.hpp>
29 #include <boost/archive/xml_oarchive.hpp>
32 
35 
37 
41 
42 #include <iostream>
43 #include <eigen3/Eigen/LU>
44 
45 using namespace Eigen;
46 using namespace std;
47 
48 namespace DmpBbo {
49 
50 ModelParametersGMR::ModelParametersGMR(std::vector<double> priors,
51  std::vector<Eigen::VectorXd> means,
52  std::vector<Eigen::MatrixXd> covars, int n_dims_out)
53 {
54  size_t n_gaussians = priors.size();
55  assert(n_gaussians>0);
56  int n_dims_gmm = means[0].size();
57  int n_dims_in = n_dims_gmm - n_dims_out;
58 
59 #ifndef NDEBUG // Check for NDEBUG to avoid 'unused variable' warnings
60  assert(n_dims_out>0);
61  assert(n_dims_in>0);
62  assert(means.size() == n_gaussians);
63  assert(covars.size() == n_gaussians);
64  for (size_t i = 0; i < n_gaussians; i++)
65  {
66  assert(means[i].size() == n_dims_gmm);
67  assert(covars[i].cols() == n_dims_gmm);
68  assert(covars[i].rows() == n_dims_gmm);
69  }
70 #endif
71 
72  priors_ = priors;
73 
74  means_x_.resize(n_gaussians);
75  means_y_.resize(n_gaussians);
76  covars_x_.resize(n_gaussians);
77  covars_y_.resize(n_gaussians);
78  covars_y_x_.resize(n_gaussians);
79 
80  for (size_t i = 0; i < n_gaussians; i++)
81  {
82  means_x_[i] = means[i].segment(0,n_dims_in);
83  means_y_[i] = means[i].segment(n_dims_in,n_dims_out);
84 
85  covars_x_[i] = covars[i].block(0,0,n_dims_in,n_dims_in);
86  covars_y_[i] = covars[i].block(n_dims_in,n_dims_in,n_dims_out,n_dims_out);
87  covars_y_x_[i] = covars[i].block(n_dims_in, 0, n_dims_out, n_dims_in);
88 
89  }
90 
91  updateCachedMembers();
92 
93  all_values_vector_size_ = 0;
94 
95  n_observations_ = 0;
96 }
97 
98 ModelParametersGMR::ModelParametersGMR(int n_observations, std::vector<double> priors,
99  std::vector<Eigen::VectorXd> means,
100  std::vector<Eigen::MatrixXd> covars,
101  int n_dims_out)
102 :ModelParametersGMR(priors,means,covars,n_dims_out)
103 {
104  assert(n_observations >= 0);
105 
106  n_observations_ = n_observations;
107 }
108 
109 ModelParametersGMR::ModelParametersGMR(std::vector<double> priors,
110  std::vector<Eigen::VectorXd> means_x, std::vector<Eigen::VectorXd> means_y,
111  std::vector<Eigen::MatrixXd> covars_x, std::vector<Eigen::MatrixXd> covars_y,
112  std::vector<Eigen::MatrixXd> covars_y_x)
113 :
114  priors_(priors),
115  means_x_(means_x),
116  means_y_(means_y),
117  covars_x_(covars_x),
118  covars_y_(covars_y),
119  covars_y_x_(covars_y_x)
120 {
121 
122  size_t n_gaussians = priors.size();
123 
124 #ifndef NDEBUG // Check for NDEBUG to avoid 'unused variable' warnings for n_dims_in and n_dims_out.
125  assert(n_gaussians>0);
126  assert(means_x_.size() == n_gaussians);
127  assert(means_y_.size() == n_gaussians);
128  assert(covars_x_.size() == n_gaussians);
129  assert(covars_y_.size() == n_gaussians);
130  assert(covars_y_x_.size() == n_gaussians);
131 
132  int n_dims_in = getExpectedInputDim();
133  for (size_t i = 0; i < n_gaussians; i++)
134  {
135  assert(means_x_[i].size() == n_dims_in);
136  assert(covars_x_[i].rows() == n_dims_in);
137  assert(covars_x_[i].cols() == n_dims_in);
138  assert(covars_y_x_[i].cols() == n_dims_in);
139  }
140 
141  int n_dims_out = getExpectedOutputDim();
142  for (size_t i = 0; i < n_gaussians; i++)
143  {
144  assert(covars_y_[i].rows() == n_dims_out);
145  assert(covars_y_[i].cols() == n_dims_out);
146  assert(covars_y_x_[i].rows() == n_dims_out);
147  }
148 #endif
149 
150  updateCachedMembers();
151 
152  all_values_vector_size_ = 0;
153 
154  n_observations_ = 0;
155 
156  // NEW REPRESENTATION
157  // all_values_vector_size_ += n_gaussians;
158 
159  // all_values_vector_size_ += n_gaussians * n_dims_in;
160  // all_values_vector_size_ += n_gaussians * n_dims_out;
161 
162  // all_values_vector_size_ += n_gaussians * n_dims_in * n_dims_in;
163  // all_values_vector_size_ += n_gaussians * n_dims_out * n_dims_out;
164  // all_values_vector_size_ += n_gaussians * n_dims_out * n_dims_in;
165 }
166 
167 ModelParametersGMR::ModelParametersGMR(int n_observations, std::vector<double> priors,
168  std::vector<Eigen::VectorXd> means_x, std::vector<Eigen::VectorXd> means_y,
169  std::vector<Eigen::MatrixXd> covars_x, std::vector<Eigen::MatrixXd> covars_y,
170  std::vector<Eigen::MatrixXd> covars_y_x)
171 :ModelParametersGMR(priors, means_x, means_y, covars_x,covars_y, covars_y_x)
172 {
173  assert(n_observations >= 0);
174 
175  n_observations_ = n_observations;
176 }
177 
178 
179 void ModelParametersGMR::updateCachedMembers(void)
180 {
181  int n_gaussians = getNumberOfGaussians();
182  int n_dims_in = getExpectedInputDim();
183 
184  covars_x_inv_.resize(n_gaussians);
185  mvgd_scale_.resize(n_gaussians);
186  for (int i=0; i<n_gaussians; i++)
187  {
188  covars_x_inv_[i] = covars_x_[i].inverse();
189 
190  // 1/sqrt((2*pi)^k*|Sigma|)
191  double in_sqrt = pow(2*M_PI,n_dims_in)*covars_x_[i].determinant();
192  mvgd_scale_[i] = pow(in_sqrt,-0.5);
193  }
194 }
195 
197 {
198  std::vector<double> priors;
199  std::vector<VectorXd> means_x;
200  std::vector<VectorXd> means_y;
201  std::vector<MatrixXd> covars_x;
202  std::vector<MatrixXd> covars_y;
203  std::vector<MatrixXd> covars_y_x;
204  int n_observations = n_observations_;
205 
206  for (size_t i = 0; i < priors_.size(); i++)
207  {
208  priors.push_back(priors_[i]);
209  means_x.push_back(VectorXd(means_x_[i]));
210  means_y.push_back(VectorXd(means_y_[i]));
211  covars_x.push_back(MatrixXd(covars_x_[i]));
212  covars_y.push_back(MatrixXd(covars_y_[i]));
213  covars_y_x.push_back(MatrixXd(covars_y_x_[i]));
214  }
215 
216  return new ModelParametersGMR(n_observations, priors, means_x, means_y, covars_x, covars_y, covars_y_x);
217 }
218 
219 template<class Archive>
220 void ModelParametersGMR::serialize(Archive & ar, const unsigned int version)
221 {
222  // serialize base class information
223  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ModelParameters);
224 
225  ar & BOOST_SERIALIZATION_NVP(priors_);
226  ar & BOOST_SERIALIZATION_NVP(means_x_);
227  ar & BOOST_SERIALIZATION_NVP(means_y_);
228  ar & BOOST_SERIALIZATION_NVP(covars_x_);
229  ar & BOOST_SERIALIZATION_NVP(covars_y_);
230  ar & BOOST_SERIALIZATION_NVP(covars_y_x_);
231  ar & BOOST_SERIALIZATION_NVP(covars_x_inv_);
232  ar & BOOST_SERIALIZATION_NVP(mvgd_scale_);
233 }
234 
235 
236 string ModelParametersGMR::toString(void) const
237 {
238  RETURN_STRING_FROM_BOOST_SERIALIZATION_XML("ModelParametersGMR");
239 };
240 
241 bool ModelParametersGMR::saveGMM(std::string directory, const std::vector<Eigen::VectorXd>& centers, const std::vector<Eigen::MatrixXd>& covars, bool overwrite, int iter)
242 {
243  for (size_t i_gau = 0; i_gau < centers.size(); i_gau++)
244  {
245  stringstream stream;
246  stream << "gmm";
247  if (iter>=0)
248  stream << "_iter" << setw(2) << setfill('0') << iter;
249  stream << "_mu" << setw(3) << setfill('0') << i_gau << ".txt";
250  string filename = stream.str();
251  if (!saveMatrix(directory, filename, centers[i_gau], overwrite))
252  return false;
253  //cout << " filename=" << filename << endl;
254 
255  stringstream stream2;
256  stream2 << "gmm";
257  if (iter>=0)
258  stream2 << "_iter" << setw(2) << setfill('0') << iter;
259  stream2 << "_covar" << setw(3) << setfill('0') << i_gau << ".txt";
260  filename = stream2.str();
261  //cout << " filename=" << filename << endl;
262  if (!saveMatrix(directory, filename, covars[i_gau], overwrite))
263  return false;
264  }
265  return true;
266 }
267 
268 bool ModelParametersGMR::saveGMM(std::string save_directory, bool overwrite) const
269 {
270  if (save_directory.empty())
271  return true;
272 
273  //MatrixXd inputs;
274  //FunctionApproximator::generateInputsGrid(min, max, n_samples_per_dim, inputs);
275  //saveMatrix(save_directory,"n_samples_per_dim.txt",n_samples_per_dim,overwrite);
276 
277  int n_gaussians = means_x_.size();
278  int n_dims_in = means_x_[0].size();
279  int n_dims_out = means_y_[0].size();
280  int n_dims_gmm = n_dims_in + n_dims_out;
281 
282 
283  std::vector<VectorXd> means(n_gaussians);
284  std::vector<MatrixXd> covars(n_gaussians);
285  for (int i_gau = 0; i_gau < n_gaussians; i_gau++)
286  {
287  means[i_gau] = VectorXd(n_dims_gmm);
288  means[i_gau].segment(0, n_dims_in) = means_x_[i_gau];
289  means[i_gau].segment(n_dims_in, n_dims_out) = means_y_[i_gau];
290 
291  covars[i_gau] = MatrixXd(n_dims_gmm,n_dims_gmm);
292  covars[i_gau].fill(0);
293  covars[i_gau].block(0, 0, n_dims_in, n_dims_in) = covars_x_[i_gau];
294  covars[i_gau].block(n_dims_in, n_dims_in, n_dims_out, n_dims_out) = covars_y_[i_gau];
295  covars[i_gau].block(n_dims_in, 0, n_dims_out, n_dims_in) = covars_y_x_[i_gau];
296  covars[i_gau].block(0, n_dims_in, n_dims_in, n_dims_out) = covars_y_x_[i_gau].transpose();
297  }
298 
299  saveGMM(save_directory,means,covars,overwrite);
300 
301 
302  return true;
303 }
304 
305 void ModelParametersGMR::toMatrix(Eigen::MatrixXd& gmm_as_matrix) const
306 {
307  int n_gaussians = means_x_.size();
308  assert(n_gaussians>0);
309  int n_dims_in = means_x_[0].size();
310  int n_dims_out = means_y_[0].size();
311  int n_dims_gmm = n_dims_in + n_dims_out;
312 
313  int n_rows = 2; // First row contains n_gaussians, n_output_dims, second row contains n_observations and responsability
314  for (int i_gau = 0; i_gau < n_gaussians; i_gau++)
315  {
316  n_rows += 1; // Add one row for the prior
317  n_rows += 1; // Add one row for the mean
318  n_rows += n_dims_gmm; // For the covariance matrix
319  }
320 
321  gmm_as_matrix = MatrixXd::Zero(n_rows,n_dims_gmm);
322 
323  gmm_as_matrix(0,0) = n_gaussians;
324  gmm_as_matrix(0,1) = n_dims_out;
325  gmm_as_matrix(1,0) = n_observations_;
326 
327  VectorXd mean = VectorXd(n_dims_gmm);
328  MatrixXd covar = MatrixXd(n_dims_gmm,n_dims_gmm);
329  int cur_row = 2;
330  for (int i_gau = 0; i_gau < n_gaussians; i_gau++)
331  {
332  mean.segment(0, n_dims_in) = means_x_[i_gau];
333  mean.segment(n_dims_in, n_dims_out) = means_y_[i_gau];
334 
335  covar.block(0, 0, n_dims_in, n_dims_in) = covars_x_[i_gau];
336  covar.block(n_dims_in, n_dims_in, n_dims_out, n_dims_out) = covars_y_[i_gau];
337  covar.block(n_dims_in, 0, n_dims_out, n_dims_in) = covars_y_x_[i_gau];
338  covar.block(0, n_dims_in, n_dims_in, n_dims_out) = covars_y_x_[i_gau].transpose();
339 
340  gmm_as_matrix(cur_row,0) = priors_[i_gau];
341  gmm_as_matrix.row(cur_row+1) = mean;
342  gmm_as_matrix.block(cur_row+2,0,n_dims_gmm,n_dims_gmm) = covar;
343 
344  cur_row += 1 + 1 + n_dims_gmm;
345  }
346 }
347 
349 {
350  int n_dims_gmm = gmm_matrix.cols();
351  int n_rows = gmm_matrix.rows();
352  assert(n_dims_gmm>1);
353  assert(n_rows>0);
354 
355  int n_gaussians = gmm_matrix(0,0);
356  int n_dims_out = gmm_matrix(0,1);
357  int n_observations = gmm_matrix(1,0);
358 
359  assert(n_rows == (2+ (n_gaussians*(1+1+n_dims_gmm))));
360 
361  vector<double> priors(n_gaussians);
362  vector<VectorXd> means(n_gaussians);
363  vector<MatrixXd> covars(n_gaussians);
364 
365  int cur_row = 2;
366  for (int i_gau = 0; i_gau < n_gaussians; i_gau++)
367  {
368  priors[i_gau] = gmm_matrix(cur_row,0);
369 
370  means[i_gau] = gmm_matrix.row(cur_row+1);
371 
372  covars[i_gau] = gmm_matrix.block(cur_row+2,0,n_dims_gmm,n_dims_gmm);
373 
374  cur_row += 1 + 1 + n_dims_gmm;
375  }
376 
377  return new ModelParametersGMR(n_observations,priors,means,covars,n_dims_out);
378 }
379 
380 bool ModelParametersGMR::saveGMMToMatrix(std::string filename, bool overwrite) const
381 {
382  if (filename.empty())
383  return true;
384 
385  MatrixXd gmm_as_matrix;
386  toMatrix(gmm_as_matrix);
387 
388  if (!saveMatrix(filename, gmm_as_matrix, overwrite))
389  return false;
390 
391  return true;
392 }
393 
395 {
396  MatrixXd gmm_matrix;
397  if (!loadMatrix(filename, gmm_matrix))
398  return NULL;
399 
400  return ModelParametersGMR::fromMatrix(gmm_matrix);
401 }
402 
403 void ModelParametersGMR::getSelectableParameters(set<string>& selected_values_labels) const
404 {
405  selected_values_labels = set<string>();
406  // selected_values_labels.insert("centers");
407  // selected_values_labels.insert("priors");
408  // selected_values_labels.insert("slopes");
409  // selected_values_labels.insert("biases");
410  // selected_values_labels.insert("inverse_covars_l");
411 }
412 
413 void ModelParametersGMR::getParameterVectorMask(const std::set<std::string> selected_values_labels, VectorXi& selected_mask) const
414 {
415  // selected_mask.resize(getParameterVectorAllSize());
416  // selected_mask.fill(0);
417 
418  // int offset = 0;
419  // int size;
420 
421  // size = centers_.size() * centers_[0].size();
422  // if (selected_values_labels.find("centers")!=selected_values_labels.end())
423  // selected_mask.segment(offset,size).fill(1);
424  // offset += size;
425 
426  // size = priors_.size();
427  // if (selected_values_labels.find("priors")!=selected_values_labels.end())
428  // selected_mask.segment(offset,size).fill(2);
429  // offset += size;
430 
431  // size = slopes_.size() * slopes_[0].rows() * slopes_[0].cols();
432  // if (selected_values_labels.find("slopes")!=selected_values_labels.end())
433  // selected_mask.segment(offset,size).fill(3);
434  // offset += size;
435 
436 
437  // size = biases_.size() * biases_[0].size();
438  // if (selected_values_labels.find("biases")!=selected_values_labels.end())
439  // selected_mask.segment(offset,size).fill(4);
440  // offset += size;
441 
442  // size = inverseCovarsL_.size() * (inverseCovarsL_[0].rows() * (inverseCovarsL_[0].cols() + 1))/2;
443  // if (selected_values_labels.find("inverse_covars_l")!=selected_values_labels.end())
444  // selected_mask.segment(offset,size).fill(5);
445  // offset += size;
446 
447  // assert(offset == getParameterVectorAllSize());
448 }
449 
450 
451 void ModelParametersGMR::getParameterVectorAll(VectorXd& values) const
452 {
453  // values.resize(getParameterVectorAllSize());
454  // int offset = 0;
455 
456  // for (size_t i = 0; i < centers_.size(); i++)
457  // {
458  // values.segment(offset, centers_[i].size()) = centers_[i];
459  // offset += centers_[i].size();
460  // }
461 
462  // for (size_t i = 0; i < centers_.size(); i++)
463  // {
464  // values[offset] = priors_[i];
465  // offset += 1;
466  // }
467 
468  // for (size_t i = 0; i < slopes_.size(); i++)
469  // {
470  // for (int col = 0; col < slopes_[i].cols(); col++)
471  // {
472  // values.segment(offset, slopes_[i].rows()) = slopes_[i].col(col);
473  // offset += slopes_[i].rows();
474  // }
475  // }
476 
477  // for (size_t i = 0; i < centers_.size(); i++)
478  // {
479  // values.segment(offset, biases_[i].size()) = biases_[i];
480  // offset += biases_[i].size();
481  // }
482 
483  // for (size_t i = 0; i < inverseCovarsL_.size(); i++)
484  // {
485  // for (int row = 0; row < inverseCovarsL_[i].rows(); row++)
486  // for (int col = 0; col < row + 1; col++)
487  // {
488  // values[offset] = inverseCovarsL_[i](row, col);
489  // offset += 1;
490  // }
491  // }
492 
493  // assert(offset == getParameterVectorAllSize());
494 
495 };
496 
497 void ModelParametersGMR::setParameterVectorAll(const VectorXd& values)
498 {
499  // if (all_values_vector_size_ != values.size())
500  // {
501  // cerr << __FILE__ << ":" << __LINE__ << ": values is of wrong size." << endl;
502  // return;
503  // }
504 
505  // int offset = 0;
506 
507  // for (size_t i = 0; i < centers_.size(); i++)
508  // {
509  // centers_[i] = values.segment(offset, centers_[i].size());
510  // offset += centers_[i].size();
511  // }
512  // for (size_t i = 0; i < centers_.size(); i++)
513  // {
514  // priors_[i] = values[offset];
515  // offset += 1;
516  // }
517 
518  // for (size_t i = 0; i < slopes_.size(); i++)
519  // {
520  // for (int col = 0; col < slopes_[i].cols(); col++)
521  // {
522  // slopes_[i].col(col) = values.segment(offset, slopes_[i].rows());
523  // offset += slopes_[i].rows();
524  // }
525  // }
526 
527  // for (size_t i = 0; i < centers_.size(); i++)
528  // {
529  // biases_[i] = values.segment(offset, biases_[i].size());
530  // offset += biases_[i].size();
531  // }
532 
533  // for (size_t i = 0; i < inverseCovarsL_.size(); i++)
534  // {
535  // for (int row = 0; row < inverseCovarsL_[i].rows(); row++)
536  // for (int col = 0; col < row + 1; col++)
537  // {
538  // inverseCovarsL_[i](row, col) = values[offset];
539  // offset += 1;
540  // }
541  // }
542 
543  // assert(offset == getParameterVectorAllSize());
544 
545 };
546 
547 
549 {
550  int n_gaussians = means_x_.size();
551 
552  // This copying is not necessary. It is just done to show which variable in GMR relates to which
553  // variable in the unified model.
554  vector<VectorXd> centers = means_x_;
555  vector<MatrixXd> covars = covars_x_;
556 
557  vector<VectorXd> slopes(n_gaussians);
558  vector<double> offsets(n_gaussians);
559  VectorXd rest;
560  for (int i_gau=0; i_gau<n_gaussians; i_gau++)
561  {
562  slopes[i_gau] = (covars_y_x_[i_gau] * covars_x_inv_[i_gau]).transpose();
563 
564  assert(means_y_[i_gau].size()==1); // Only works for 1D y output for now
565  offsets[i_gau] = means_y_[i_gau][0] - slopes[i_gau].dot(means_x_[i_gau]);
566  }
567 
568 
569  bool normalized_basis_functions = true;
570  bool lines_pivot_at_max_activation = false;
571 
572  return new UnifiedModel(centers, covars, slopes, offsets, priors_, normalized_basis_functions,lines_pivot_at_max_activation);
573 
574 }
575 
576 }
UnifiedModel class header file.
void getParameterVectorAll(Eigen::VectorXd &all_values) const
Return a vector that returns all available parameter values.
Header file for input/output of Eigen matrices to ASCII files.
FunctionApproximator class header file.
bool saveGMMToMatrix(std::string filename, bool overwrite=false) const
Save the GMM as a matrix in an ASCII file.
static bool saveGMM(std::string directory, const std::vector< Eigen::VectorXd > &centers, const std::vector< Eigen::MatrixXd > &covars, bool overwrite=false, int iter=-1)
Save a Gaussian mixture model to a directory; useful for debugging.
static ModelParametersGMR * fromMatrix(const Eigen::MatrixXd &gmm_matrix)
Initialize a GMM from a matrix.
bool saveMatrix(std::string filename, Eigen::Matrix< Scalar, RowsAtCompileTime, ColsAtCompileTime > matrix, bool overwrite=false)
Save an Eigen matrix to an ASCII file.
BOOST_CLASS_EXPORT_IMPLEMENT(DmpBbo::ModelParametersGMR)
For boost::serialization.
virtual int getExpectedOutputDim(void) const
The expected dimensionality of the output data.
static ModelParametersGMR * loadGMMFromMatrix(std::string filename)
Load the GMM from a matrix in an ASCII file.
void toMatrix(Eigen::MatrixXd &gmm_as_matrix) const
This function represents the Gaussian Mixture Model as one big matrix.
#define RETURN_STRING_FROM_BOOST_SERIALIZATION_XML(name)
Macro to convert the boost XML serialization of an object into a string.
std::string toString(void) const
Returns a string representation of the object.
UnifiedModel * toUnifiedModel(void) const
Convert these model parameters to unified model parameters.
ModelParameters * clone(void) const
Return a pointer to a deep copy of the ModelParameters object.
void getParameterVectorMask(const std::set< std::string > selected_values_labels, Eigen::VectorXi &selected_mask) const
Get a mask for selecting parameters.
The unified model, which can be used to represent the model of all other function approximators...
void setParameterVectorAll(const Eigen::VectorXd &values)
Set all available parameter values with one vector.
Model parameters for the GMR function approximator.
ModelParametersGMR class header file.
void getSelectableParameters(std::set< std::string > &selected_values_labels) const
Return all the names of the parameter types that can be selected.
Base class for all model parameters of function approximators.
virtual int getExpectedInputDim(void) const
The expected dimensionality of the input data.
Header file to generate strings from boost serialized files.
unsigned int getNumberOfGaussians(void) const
Get the number of Gaussians in the GMM.
bool loadMatrix(std::string filename, Eigen::Matrix< Scalar, RowsAtCompileTime, ColsAtCompileTime > &m)
Load an Eigen matrix from an ASCII file.
Definition: EigenFileIO.tpp:33
Header file for serialization of Eigen matrices.