Statismo  0.10.1
 All Classes Namespaces Functions Typedefs
LowRankGPModelBuilder.h
1 
13 #ifndef __LOW_RANK_GP_MODEL_BUILDER_H
14 #define __LOW_RANK_GP_MODEL_BUILDER_H
15 
16 #include <cmath>
17 
18 #include <vector>
19 
20 #include <boost/thread.hpp>
21 #include <boost/scoped_ptr.hpp>
22 #include <boost/thread/future.hpp>
23 
24 #include "CommonTypes.h"
25 #include "Config.h"
26 #include "DataManager.h"
27 #include "Kernels.h"
28 #include "ModelInfo.h"
29 #include "ModelBuilder.h"
30 #include "Nystrom.h"
31 #include "Representer.h"
32 #include "StatisticalModel.h"
33 
34 namespace statismo {
35 
36 
42 
43 
44  EigenfunctionComputationResult(unsigned _lowerInd, unsigned _upperInd,
45  const MatrixType& _resMat) :
46  lowerInd(_lowerInd), upperInd(_upperInd), resultForPoints(_resMat) {
47  }
48 
49  unsigned lowerInd;
50  unsigned upperInd;
51  MatrixType resultForPoints;
52 
53  // emulate move semantics, as boost::async seems to depend on it.
54  EigenfunctionComputationResult& operator=(BOOST_COPY_ASSIGN_REF(EigenfunctionComputationResult) rhs) { // Copy assignment
55  if (&rhs != this) {
56  copyMembers(rhs);
57  }
58  return *this;
59  }
60 
61  EigenfunctionComputationResult(BOOST_RV_REF(EigenfunctionComputationResult) that) { //Move constructor
62  copyMembers(that);
63  }
64  EigenfunctionComputationResult& operator=(BOOST_RV_REF(EigenfunctionComputationResult) rhs) { //Move assignment
65  if (&rhs != this) {
66  copyMembers(rhs);
67  }
68  return *this;
69  }
70  private:
71  BOOST_COPYABLE_AND_MOVABLE(EigenfunctionComputationResult)
72  void copyMembers(const EigenfunctionComputationResult& that) {
73  lowerInd = that.lowerInd;
74  upperInd = that.upperInd;
75  resultForPoints = that.resultForPoints;
76  }
77 };
78 
79 
91 template<typename T>
93 
94  public:
95 
96  typedef Representer<T> RepresenterType;
97  typedef typename RepresenterType::PointType PointType;
98 
101 
103  typedef typename DomainType::DomainPointsListType DomainPointsListType;
104 
106 
110  static LowRankGPModelBuilder* Create(const RepresenterType* representer) {
111  return new LowRankGPModelBuilder(representer);
112  }
113 
119  void Delete() {
120  delete this;
121  }
122 
127  }
128 
129 
139  const MatrixValuedKernelType& kernel, unsigned numComponents,
140  unsigned numPointsForNystrom = 500) const {
141 
142  VectorType zeroVec = VectorType::Zero(
143  m_representer->GetDomain().GetNumberOfPoints()
144  * m_representer->GetDimensions());
145 
146  typename RepresenterType::DatasetConstPointerType zeroMean =
147  m_representer->SampleVectorToSample(zeroVec);
148 
149  return BuildNewModel(zeroMean, kernel, numComponents,
150  numPointsForNystrom);
151  }
152 
163  typename RepresenterType::DatasetConstPointerType mean,
164  const MatrixValuedKernelType& kernel,
165  unsigned numComponents,
166  unsigned numPointsForNystrom = 500) const {
167 
168 
169  std::vector<PointType> domainPoints = m_representer->GetDomain().GetDomainPoints();
170  unsigned numDomainPoints = m_representer->GetDomain().GetNumberOfPoints();
171  unsigned kernelDim = kernel.GetDimension();
172 
173 
174  boost::scoped_ptr<Nystrom<T> > nystrom(Nystrom<T>::Create(m_representer, kernel, numComponents, numPointsForNystrom));
175 
176  // we precompute the value of the eigenfunction for each domain point
177  // and store it later in the pcaBasis matrix. In this way we obtain
178  // a standard statismo model.
179  // To save time, we parallelize over the rows
180  std::vector<boost::future<EigenfunctionComputationResult>* > futvec;
181 
182 
183  unsigned numChunks = boost::thread::hardware_concurrency() + 1;
184 
185  for (unsigned i = 0; i <= numChunks; i++) {
186 
187  unsigned chunkSize = static_cast< unsigned >( ceil( static_cast< float >( numDomainPoints ) / static_cast< float >( numChunks ) ) );
188  unsigned lowerInd = i * chunkSize;
189  unsigned upperInd =
190  std::min( static_cast< unsigned >(numDomainPoints),
191  (i + 1) * chunkSize);
192 
193  if (lowerInd >= upperInd) {
194  break;
195  }
196 
197  boost::future<EigenfunctionComputationResult>* fut = new boost::future<EigenfunctionComputationResult>(
198  boost::async(boost::launch::async, boost::bind(&LowRankGPModelBuilder<T>::computeEigenfunctionsForPoints,
199  this, nystrom.get(), &kernel, numComponents, domainPoints, lowerInd, upperInd)));
200  futvec.push_back(fut);
201  }
202 
203  MatrixType pcaBasis = MatrixType::Zero(numDomainPoints * kernelDim, numComponents);
204 
205  // collect the result
206  for (unsigned i = 0; i < futvec.size(); i++) {
207  EigenfunctionComputationResult res = futvec[i]->get();
208  pcaBasis.block(res.lowerInd * kernelDim, 0,
209  (res.upperInd - res.lowerInd) * kernelDim, pcaBasis.cols()) =
210  res.resultForPoints;
211  delete futvec[i];
212  }
213 
214 
215  VectorType pcaVariance = nystrom->getEigenvalues();
216 
217  RowVectorType mu = m_representer->SampleToSampleVector(mean);
218 
219  StatisticalModelType* model = StatisticalModelType::Create(
220  m_representer, mu, pcaBasis, pcaVariance, 0);
221 
222  // the model builder does not use any data. Hence the scores and the datainfo is emtpy
223  MatrixType scores; // no scores
224  typename BuilderInfo::DataInfoList dataInfo;
225 
226 
227  typename BuilderInfo::ParameterInfoList bi;
228  bi.push_back(BuilderInfo::KeyValuePair("NoiseVariance", Utils::toString(0)));
229  bi.push_back(BuilderInfo::KeyValuePair("KernelInfo", kernel.GetKernelInfo()));
230 
231  // finally add meta data to the model info
232  BuilderInfo builderInfo("LowRankGPModelBuilder", dataInfo, bi);
233 
234  ModelInfo::BuilderInfoList biList( 1, builderInfo );;
235 
236  ModelInfo info(scores, biList);
237  model->SetModelInfo(info);
238 
239  return model;
240  }
241 
242 
243  private:
244 
245 
246 
247  /*
248  * Compute the eigenfunction value at the poitns with index lowerInd - upperInd.
249  * Return a result object with the given values.
250  * This method is used to be able to parallelize the computations.
251  */
252  EigenfunctionComputationResult computeEigenfunctionsForPoints(
253  const Nystrom<T>* nystrom,
254  const MatrixValuedKernelType* kernel, unsigned numEigenfunctions,
255  const std::vector<PointType> & domainPts,
256  unsigned lowerInd, unsigned upperInd) const {
257 
258  unsigned kernelDim = kernel->GetDimension();
259 
260  assert(upperInd <= domainPts.size());
261 
262  // holds the results of the computation
263  MatrixType resMat = MatrixType::Zero((upperInd - lowerInd) * kernelDim,
264  numEigenfunctions);
265 
266  // compute the nystrom extension for each point i in domainPts, for which
267  // i is in the right range
268  for (unsigned i = lowerInd; i < upperInd; i++) {
269 
270  PointType pti = domainPts[i];
271  resMat.block((i - lowerInd) * kernelDim, 0, kernelDim, resMat.cols()) = nystrom->computeEigenfunctionsAtPoint(pti);
272 
273  }
274  return EigenfunctionComputationResult(lowerInd, upperInd, resMat);
275  }
276 
277 
278 
282  LowRankGPModelBuilder(const RepresenterType* representer) :
283  m_representer(representer) {
284  }
285 
286  // purposely not implemented
287  LowRankGPModelBuilder(const LowRankGPModelBuilder& orig);
288  LowRankGPModelBuilder& operator=(const LowRankGPModelBuilder& rhs);
289 
290  const RepresenterType* m_representer;
291 
292 };
293 
294 } // namespace statismo
295 
296 #endif // __LOW_RANK_GP_MODEL_BUILDER_H
StatisticalModelType * BuildNewZeroMeanModel(const MatrixValuedKernelType &kernel, unsigned numComponents, unsigned numPointsForNystrom=500) const
Definition: LowRankGPModelBuilder.h:138
StatisticalModelType * BuildNewModel(typename RepresenterType::DatasetConstPointerType mean, const MatrixValuedKernelType &kernel, unsigned numComponents, unsigned numPointsForNystrom=500) const
Definition: LowRankGPModelBuilder.h:162
MatrixType computeEigenfunctionsAtPoint(const PointType &pt) const
Definition: Nystrom.h:46
Common base class for all the model builder classes.
Definition: ModelBuilder.h:54
virtual ~LowRankGPModelBuilder()
Definition: LowRankGPModelBuilder.h:126
Definition: Nystrom.h:30
virtual unsigned GetDimension() const
Definition: Kernels.h:82
A trivial representer, that does no representation at all, but works directly with vectorial data...
Definition: TrivialVectorialRepresenter.h:83
virtual std::string GetKernelInfo() const =0
static LowRankGPModelBuilder * Create(const RepresenterType *representer)
Definition: LowRankGPModelBuilder.h:110
void Delete()
Definition: LowRankGPModelBuilder.h:119
Holds information about the data and the parameters used by a specific modelbuilder.
Definition: ModelInfo.h:125
void SetModelInfo(const ModelInfo &modelInfo)
Definition: StatisticalModel.hxx:486
stores meta information about the model, such as e.g. the name (uri) of the datasets used to build th...
Definition: ModelInfo.h:61
Definition: LowRankGPModelBuilder.h:92
Definition: LowRankGPModelBuilder.h:41
A Point/Value pair that is used to specify a value at a given point.
Definition: StatisticalModel.h:100
Definition: Domain.h:51