DMP_BBO library
FunctionApproximatorLWPR.cpp
Go to the documentation of this file.
1 
24 #include <boost/serialization/export.hpp>
25 #include <boost/archive/text_iarchive.hpp>
26 #include <boost/archive/text_oarchive.hpp>
27 #include <boost/archive/xml_iarchive.hpp>
28 #include <boost/archive/xml_oarchive.hpp>
30 
33 
35 
38 
39 #include "lwpr.hh"
40 
41 #include <iostream>
42 
43 using namespace Eigen;
44 using namespace std;
45 
46 namespace DmpBbo {
47 
48 FunctionApproximatorLWPR::FunctionApproximatorLWPR(const MetaParametersLWPR *const meta_parameters, const ModelParametersLWPR *const model_parameters)
49 :
50  FunctionApproximator(meta_parameters,model_parameters),
51  print_training_progress_(false)
52 {
53 }
54 
55 FunctionApproximatorLWPR::FunctionApproximatorLWPR(const ModelParametersLWPR *const model_parameters)
56 :
57  FunctionApproximator(model_parameters),
58  print_training_progress_(false)
59 {
60 }
61 
63  // All error checking and cloning is left to the FunctionApproximator constructor.
65  dynamic_cast<const MetaParametersLWPR*>(getMetaParameters()),
66  dynamic_cast<const ModelParametersLWPR*>(getModelParameters())
67  );
68  fa_lwpr->set_print_training_progress(print_training_progress_);
69  return fa_lwpr;
70 };
71 
72 void FunctionApproximatorLWPR::train(const Eigen::Ref<const Eigen::MatrixXd>& inputs, const Eigen::Ref<const Eigen::MatrixXd>& targets)
73 {
74  if (isTrained())
75  {
76  cerr << "WARNING: You may not call FunctionApproximatorLWPR::train more than once. Doing nothing." << endl;
77  cerr << " (if you really want to retrain, call reTrain function instead)" << endl;
78  return;
79  }
80 
81  assert(inputs.rows() == targets.rows()); // Must have same number of examples
82  assert(inputs.cols()==getExpectedInputDim());
83 
84  const MetaParametersLWPR* meta_parameters_lwpr = dynamic_cast<const MetaParametersLWPR*>(getMetaParameters());
85 
86  int n_in =inputs.cols();
87  int n_out=targets.cols();
88 
89  LWPR_Object* lwpr_object = new LWPR_Object(n_in, n_out);
90  lwpr_object->setInitD( meta_parameters_lwpr->init_D_[0]); // todo Fix this
91  lwpr_object->wGen( meta_parameters_lwpr->w_gen_);
92  lwpr_object->wPrune( meta_parameters_lwpr->w_prune_);
93  lwpr_object->updateD( meta_parameters_lwpr->update_D_);
94  lwpr_object->setInitAlpha(meta_parameters_lwpr->init_alpha_);
95  lwpr_object->penalty( meta_parameters_lwpr->penalty_);
96  lwpr_object->diagOnly( meta_parameters_lwpr->diag_only_);
97  lwpr_object->useMeta( meta_parameters_lwpr->use_meta_);
98  lwpr_object->metaRate( meta_parameters_lwpr->meta_rate_);
99  lwpr_object->kernel( meta_parameters_lwpr->kernel_name_.c_str());
100 
101 
102  vector<double> input_vector(n_in);
103  vector<double> target_vector(n_out);
104  int n_input_samples = inputs.rows();
105 
106  //http://stackoverflow.com/questions/15858569/randomly-permute-rows-columns-of-a-matrix-with-eigen
107  PermutationMatrix<Dynamic,Dynamic> permute(n_input_samples);
108  permute.setIdentity();
109  VectorXi shuffled_indices = VectorXi::LinSpaced(n_input_samples,0,n_input_samples-1);
110  MatrixXd outputs;
111  for (int iterations=0; iterations<50; iterations++)
112  {
113  random_shuffle(permute.indices().data(), permute.indices().data()+permute.indices().size());
114  shuffled_indices = (shuffled_indices.transpose()*permute).transpose();
115 
116  for (int ii=0; ii<n_input_samples; ii++)
117  {
118  // Eigen::VectorXd -> std::vector
119  Map<VectorXd>(input_vector.data(),n_in) = inputs.row(shuffled_indices[ii]);
120  Map<VectorXd>(target_vector.data(),n_out) = targets.row(shuffled_indices[ii]);
121  // update model
122  lwpr_object->update(input_vector, target_vector);
123  }
124 
125  if (print_training_progress_)
126  {
127  if (iterations%5==0)
128  {
129  FunctionApproximatorLWPR* fa_tmp = new FunctionApproximatorLWPR(new ModelParametersLWPR(new LWPR_Object(*lwpr_object)));
130  fa_tmp->predict(inputs, outputs);
131  delete fa_tmp;
132  MatrixXd abs_error = (targets.array()-outputs.array()).abs();
133  VectorXd mean_abs_error_per_output_dim = abs_error.colwise().mean();
134  cout << "Iteration " << iterations << " MEA=" << mean_abs_error_per_output_dim << endl;
135  }
136  }
137 
138  }
139  setModelParameters(new ModelParametersLWPR(lwpr_object));
140 
141 }
142 
143 
144 void FunctionApproximatorLWPR::predict(const Eigen::Ref<const Eigen::MatrixXd>& inputs, MatrixXd& outputs)
145 {
146  if (!isTrained())
147  {
148  cerr << "WARNING: You may not call FunctionApproximatorLWPR::predict if you have not trained yet. Doing nothing." << endl;
149  return;
150  }
151 
152  const ModelParametersLWPR* model_parameters_lwpr = static_cast<const ModelParametersLWPR*>(getModelParameters());
153 
154  int n_in = model_parameters_lwpr->lwpr_object_->model.nIn;
155  assert(inputs.cols()==n_in);
156 
157  int n_input_samples = inputs.rows();
158  int n_out = model_parameters_lwpr->lwpr_object_->model.nOut;
159 
160  outputs.resize(n_input_samples,n_out);
161 
162  // Allocate memory for the temporary vectors for LWPR_Object::predict
163  vector<double> input_vector(n_in);
164  vector<double> output_vector(n_out);
165 
166  // Do prediction for each sample
167  for (int ii=0; ii<n_input_samples; ii++)
168  {
169  // LWPR_Object::predict uses std::vector, so do some conversions here.
170  Map<VectorXd>(input_vector.data(),n_in) = inputs.row(ii); // Eigen::VectorXd -> std::vector
171  output_vector = model_parameters_lwpr->lwpr_object_->predict(input_vector);
172  outputs.row(ii) = Map<VectorXd>(&output_vector[0], n_out); // std::vector -> Eigen::VectorXd
173  }
174 
175 }
176 
177 template<class Archive>
178 void FunctionApproximatorLWPR::serialize(Archive & ar, const unsigned int version)
179 {
180  // serialize base class information
181  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(FunctionApproximator);
182 }
183 
184 
185 }
void train(const Eigen::Ref< const Eigen::MatrixXd > &inputs, const Eigen::Ref< const Eigen::MatrixXd > &targets)
Train the function approximator with corresponding input and target examples.
FunctionApproximatorLWPR class header file.
MetaParametersLWPR class header file.
bool isTrained(void) const
Determine whether the function approximator has already been trained with data or not...
ModelParametersLWPR class header file.
Base class for all function approximators.
BOOST_CLASS_EXPORT_IMPLEMENT(DmpBbo::FunctionApproximatorLWPR)
For boost::serialization.
FunctionApproximator * clone(void) const
Return a pointer to a deep copy of the FunctionApproximator object.
void predict(const Eigen::Ref< const Eigen::MatrixXd > &inputs, Eigen::MatrixXd &output)
Query the function approximator to make a prediction.
Model parameters for the Locally Weighted Projection Regression (LWPR) function approximator.
LWPR (Locally Weighted Projection Regression) function approximator.
const MetaParameters * getMetaParameters(void) const
Accessor for FunctionApproximator::meta_parameters_.
const ModelParameters * getModelParameters(void) const
Accessor for FunctionApproximator::model_parameters_.
Meta-parameters for the Locally Weighted Projection Regression (LWPR) function approximator.
void setModelParameters(ModelParameters *model_parameters)
Accessor for FunctionApproximator::model_parameters_.
void set_print_training_progress(bool print_training_progress)
Print some output to cout during training.
int getExpectedInputDim(void) const
The expected dimensionality of the input data.
Header file for serialization of Eigen matrices.