DMP_BBO library
FunctionApproximatorRBFN.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 
38 
41 
42 #include <iostream>
43 #include <eigen3/Eigen/SVD>
44 #include <eigen3/Eigen/LU>
45 
46 using namespace std;
47 using namespace Eigen;
48 
49 namespace DmpBbo {
50 
51 FunctionApproximatorRBFN::FunctionApproximatorRBFN(const MetaParametersRBFN *const meta_parameters, const ModelParametersRBFN *const model_parameters)
52 :
53  FunctionApproximator(meta_parameters,model_parameters)
54 {
55  if (model_parameters!=NULL)
56  preallocateMemory(model_parameters->getNumberOfBasisFunctions());
57 }
58 
59 FunctionApproximatorRBFN::FunctionApproximatorRBFN(const ModelParametersRBFN *const model_parameters)
60 :
61  FunctionApproximator(model_parameters)
62 {
63  preallocateMemory(model_parameters->getNumberOfBasisFunctions());
64 }
65 
67 {
68  weights_prealloc_ = VectorXd(n_basis_functions);
69  activations_one_prealloc_ = MatrixXd(1,n_basis_functions);
70  activations_prealloc_ = MatrixXd(1,n_basis_functions);
71 }
72 
73 
75  // All error checking and cloning is left to the FunctionApproximator constructor.
76  return new FunctionApproximatorRBFN(
77  dynamic_cast<const MetaParametersRBFN*>(getMetaParameters()),
78  dynamic_cast<const ModelParametersRBFN*>(getModelParameters())
79  );
80 };
81 
82 void FunctionApproximatorRBFN::train(const Eigen::Ref<const Eigen::MatrixXd>& inputs, const Eigen::Ref<const Eigen::MatrixXd>& targets)
83 {
84  if (isTrained())
85  {
86  cerr << "WARNING: You may not call FunctionApproximatorRBFN::train more than once. Doing nothing." << endl;
87  cerr << " (if you really want to retrain, call reTrain function instead)" << endl;
88  return;
89  }
90 
91  assert(inputs.rows() == targets.rows());
92  assert(inputs.cols()==getExpectedInputDim());
93 
94  const MetaParametersRBFN* meta_parameters_rbfn =
95  dynamic_cast<const MetaParametersRBFN*>(getMetaParameters());
96 
97  // Determine the centers and widths of the basis functions, given the range of the input data
98  VectorXd min = inputs.colwise().minCoeff();
99  VectorXd max = inputs.colwise().maxCoeff();
100  MatrixXd centers, widths;
101  meta_parameters_rbfn->getCentersAndWidths(min,max,centers,widths);
102 
103  // Get the activations of the basis functions
104  bool normalized_basis_functions=false;
105  bool asymmetric_kernels=false;
106  int n_samples = inputs.rows();
107  int n_kernels = centers.rows();
108  MatrixXd activations(n_samples,n_kernels);
109  BasisFunction::Gaussian::activations(centers,widths,inputs,activations,
110  normalized_basis_functions,asymmetric_kernels);
111 
112  // Least squares, with activations as design matrix
113  bool use_offset=false;
114  double regularization = meta_parameters_rbfn->regularization();
115  VectorXd weights = leastSquares(activations,targets,use_offset,regularization);
116 
117  setModelParameters(new ModelParametersRBFN(centers,widths,weights));
118 
119  preallocateMemory(n_kernels);
120 
121 }
122 
123 void FunctionApproximatorRBFN::predict(const Eigen::Ref<const Eigen::MatrixXd>& inputs, MatrixXd& outputs)
124 {
125  if (!isTrained())
126  {
127  cerr << "WARNING: You may not call FunctionApproximatorLWPR::predict if you have not trained yet. Doing nothing." << endl;
128  return;
129  }
130 
131  const ModelParametersRBFN* model_parameters_rbfn = static_cast<const ModelParametersRBFN*>(getModelParameters());
132 
133  model_parameters_rbfn->weights(weights_prealloc_);
134 
135  int n_basis_functions = model_parameters_rbfn->getNumberOfBasisFunctions();
136 
137  bool only_one_sample = (inputs.rows()==1);
138  if (only_one_sample)
139  {
140  ENTERING_REAL_TIME_CRITICAL_CODE
141 
142  // Get the basis function activations
143  model_parameters_rbfn->kernelActivations(inputs,activations_one_prealloc_);
144 
145  // Weight the basis function activations
146  for (int b=0; b<n_basis_functions; b++)
147  activations_one_prealloc_.col(b).array() *= weights_prealloc_(b);
148 
149  // Sum over weighed basis functions
150  outputs = activations_one_prealloc_.rowwise().sum();
151 
152  EXITING_REAL_TIME_CRITICAL_CODE
153  }
154  else
155  {
156  int n_time_steps = inputs.rows();
157 
158  // The next two lines may not be real-time, as they may allocate memory.
159  // (if the size are already correct, it will be realtime)
160  activations_prealloc_.resize(n_time_steps,n_basis_functions);
161  outputs.resize(n_time_steps,getExpectedOutputDim());
162 
163  // Get the basis function activations
164  model_parameters_rbfn->kernelActivations(inputs,activations_prealloc_);
165 
166  // Weight the basis function activations
167  for (int b=0; b<n_basis_functions; b++)
168  activations_prealloc_.col(b).array() *= weights_prealloc_(b);
169 
170  // Sum over weighed basis functions
171  outputs = activations_prealloc_.rowwise().sum();
172  }
173 
174 }
175 
176 bool FunctionApproximatorRBFN::saveGridData(const VectorXd& min, const VectorXd& max, const VectorXi& n_samples_per_dim, string save_directory, bool overwrite) const
177 {
178  if (save_directory.empty())
179  return true;
180 
181  MatrixXd inputs_grid;
182  FunctionApproximator::generateInputsGrid(min, max, n_samples_per_dim, inputs_grid);
183 
184  const ModelParametersRBFN* model_parameters_rbfn = static_cast<const ModelParametersRBFN*>(getModelParameters());
185 
186  MatrixXd activations_grid;
187  model_parameters_rbfn->kernelActivations(inputs_grid, activations_grid);
188 
189  saveMatrix(save_directory,"n_samples_per_dim.txt",n_samples_per_dim,overwrite);
190  saveMatrix(save_directory,"inputs_grid.txt",inputs_grid,overwrite);
191  saveMatrix(save_directory,"activations_grid.txt",activations_grid,overwrite);
192 
193  // Weight the basis function activations
194  VectorXd weights = model_parameters_rbfn->weights();
195  for (int b=0; b<activations_grid.cols(); b++)
196  activations_grid.col(b).array() *= weights(b);
197  saveMatrix(save_directory,"activations_weighted_grid.txt",activations_grid,overwrite);
198 
199  // Sum over weighed basis functions
200  MatrixXd predictions_grid = activations_grid.rowwise().sum();
201  saveMatrix(save_directory,"predictions_grid.txt",predictions_grid,overwrite);
202 
203  return true;
204 
205 }
206 
207 template<class Archive>
208 void FunctionApproximatorRBFN::serialize(Archive & ar, const unsigned int version)
209 {
210  // serialize base class information
211  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(FunctionApproximator);
212 }
213 
214 }
Meta-parameters for the Radial Basis Function Network (RBFN) function approximator.
Header file for input/output of Eigen matrices to ASCII files.
RBFN (Radial Basis Function Network) function approximator.
void kernelActivations(const Eigen::Ref< const Eigen::MatrixXd > &inputs, Eigen::MatrixXd &kernel_activations) const
Get the kernel activations for given inputs.
Header file for various least squares functions.
void predict(const Eigen::Ref< const Eigen::MatrixXd > &inputs, Eigen::MatrixXd &output)
Query the function approximator to make a prediction.
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.
static void generateInputsGrid(const Eigen::VectorXd &min, const Eigen::VectorXd &max, const Eigen::VectorXi &n_samples_per_dim, Eigen::MatrixXd &inputs_grid)
Generate a input samples that lie on a grid (much like Matlab&#39;s meshgrid) For instance, if min = [2 6], and max = [3 8], and n_samples_per_dim = [3 5] then this function first makes linearly spaces samples along each dimension, e.g.
const Eigen::VectorXd & weights(void) const
Return the weights of the basis functions.
BOOST_CLASS_EXPORT_IMPLEMENT(DmpBbo::FunctionApproximatorRBFN)
For boost::serialization.
bool saveMatrix(std::string filename, Eigen::Matrix< Scalar, RowsAtCompileTime, ColsAtCompileTime > matrix, bool overwrite=false)
Save an Eigen matrix to an ASCII file.
bool isTrained(void) const
Determine whether the function approximator has already been trained with data or not...
void preallocateMemory(int n_basis_functions)
Preallocate memory to make certain functions real-time.
BasisFunction header file.
int getExpectedOutputDim(void) const
The expected dimensionality of the output data.
Base class for all function approximators.
ModelParametersRBFN class header file.
FunctionApproximatorRBFN class header file.
FunctionApproximator * clone(void) const
Return a pointer to a deep copy of the FunctionApproximator object.
void getCentersAndWidths(const Eigen::VectorXd &min, const Eigen::VectorXd &max, Eigen::MatrixXd &centers, Eigen::MatrixXd &widths) const
Get the centers and widths of the basis functions.
Model parameters for the Radial Basis Function Network (RBFN) function approximator.
const MetaParameters * getMetaParameters(void) const
Accessor for FunctionApproximator::meta_parameters_.
unsigned int getNumberOfBasisFunctions() const
Get the number of basis functions in this model.
const ModelParameters * getModelParameters(void) const
Accessor for FunctionApproximator::model_parameters_.
bool saveGridData(const Eigen::VectorXd &min, const Eigen::VectorXd &max, const Eigen::VectorXi &n_samples_per_dim, std::string directory, bool overwrite=false) const
Generate a grid of inputs, and output the response of the basis functions and line segments for these...
MetaParametersRBFN class header file.
void setModelParameters(ModelParameters *model_parameters)
Accessor for FunctionApproximator::model_parameters_.
int getExpectedInputDim(void) const
The expected dimensionality of the input data.
Header file for serialization of Eigen matrices.
Eigen::MatrixXd leastSquares(const Eigen::Ref< const Eigen::MatrixXd > &inputs, const Eigen::Ref< const Eigen::MatrixXd > &targets, bool use_offset, double regularization)
(Regularized) least squares with bias