38 #ifndef __StatisticalModel_hxx
39 #define __StatisticalModel_hxx
47 #include "Exceptions.h"
48 #include "HDF5Utils.h"
49 #include "ModelBuilder.h"
50 #include "StatisticalModel.h"
55 StatisticalModel<T>::StatisticalModel(
const RepresenterType* representer,
const VectorType& m,
const MatrixType& orthonormalPCABasis,
const VectorType& pcaVariance,
double noiseVariance)
56 : m_representer(representer->Clone()),
58 m_pcaVariance(pcaVariance),
59 m_noiseVariance(noiseVariance),
60 m_cachedValuesValid(false),
61 m_modelLoaded(false) {
62 VectorType D = pcaVariance.array().sqrt();
63 m_pcaBasisMatrix = orthonormalPCABasis * DiagMatrixType(D);
67 StatisticalModel<T>::StatisticalModel(
const RepresenterType* representer)
68 : m_representer(representer->Clone()), m_noiseVariance(0), m_cachedValuesValid(0) {
75 if (m_representer != 0) {
78 const_cast<RepresenterType*
>(m_representer)->Delete();
87 typename StatisticalModel<T>::DatasetPointerType
89 DatasetPointerType sample;
90 sample = m_representer->CloneDataset(ds);
96 typename StatisticalModel<T>::ValueType
98 unsigned ptid = this->m_representer->GetPointIdForPoint(point);
99 return EvaluateSampleAtPoint(sample, ptid);
103 template <
typename T>
104 typename StatisticalModel<T>::ValueType
106 return this->m_representer->PointSampleFromSample(sample, ptid);
110 template <
typename T>
111 typename StatisticalModel<T>::DatasetPointerType
113 VectorType coeffs = VectorType::Zero(this->GetNumberOfPrincipalComponents());
114 return DrawSample(coeffs,
false);
118 template <
typename T>
119 typename StatisticalModel<T>::ValueType
121 VectorType coeffs = VectorType::Zero(this->GetNumberOfPrincipalComponents());
122 return DrawSampleAtPoint(coeffs, point);
126 template <
typename T>
127 typename StatisticalModel<T>::ValueType
129 VectorType coeffs = VectorType::Zero(this->GetNumberOfPrincipalComponents());
130 return DrawSampleAtPoint(coeffs, pointId,
false);
137 template <
typename T>
138 typename StatisticalModel<T>::DatasetPointerType
142 VectorType coeffs = Utils::generateNormalVector(GetNumberOfPrincipalComponents());
144 return DrawSample(coeffs, addNoise);
148 template <
typename T>
149 typename StatisticalModel<T>::DatasetPointerType
151 return m_representer->SampleVectorToSample(DrawSampleVector(coefficients, addNoise));
155 template <
typename T>
156 typename StatisticalModel<T>::DatasetPointerType
158 if (pcaComponent >= this->GetNumberOfPrincipalComponents()) {
163 return m_representer->SampleVectorToSample( m_pcaBasisMatrix.col(pcaComponent));
168 template <
typename T>
172 if (coefficients.size() != this->GetNumberOfPrincipalComponents()) {
176 unsigned vectorSize = this->m_mean.size();
177 assert (vectorSize != 0);
179 VectorType epsilon = VectorType::Zero(vectorSize);
181 epsilon = Utils::generateNormalVector(vectorSize) * sqrt(m_noiseVariance);
185 return m_mean+ m_pcaBasisMatrix * coefficients + epsilon;
189 template <
typename T>
190 typename StatisticalModel<T>::ValueType
193 unsigned ptId = this->m_representer->GetPointIdForPoint(point);
195 return DrawSampleAtPoint(coefficients, ptId, addNoise);
199 template <
typename T>
200 typename StatisticalModel<T>::ValueType
203 unsigned dim = m_representer->GetDimensions();
206 VectorType epsilon = VectorType::Zero(dim);
208 epsilon = Utils::generateNormalVector(dim) * sqrt(m_noiseVariance);
210 for (
unsigned d = 0; d < dim; d++) {
211 unsigned idx =m_representer->MapPointIdToInternalIdx(ptId, d);
213 if (idx >= m_mean.rows()) {
214 std::ostringstream os;
215 os <<
"Invalid idx computed in DrawSampleAtPoint. ";
216 os <<
" The most likely cause of this error is that you provided an invalid point id (" << ptId <<
")";
220 v[d] = m_mean[idx] + m_pcaBasisMatrix.row(idx).dot(coefficients) + epsilon[d];
223 return this->m_representer->PointSampleVectorToPointSample(v);
228 template <
typename T>
231 unsigned ptId1 = this->m_representer->GetPointIdForPoint(pt1);
232 unsigned ptId2 = this->m_representer->GetPointIdForPoint(pt2);
234 return GetCovarianceAtPoint(ptId1, ptId2);
237 template <
typename T>
240 unsigned dim = m_representer->GetDimensions();
241 MatrixType cov(dim, dim);
243 for (
unsigned i = 0; i < dim; i++) {
244 unsigned idxi = m_representer->MapPointIdToInternalIdx(ptId1, i);
245 VectorType vi = m_pcaBasisMatrix.row(idxi);
246 for (
unsigned j = 0; j < dim; j++) {
247 unsigned idxj = m_representer->MapPointIdToInternalIdx(ptId2, j);
248 VectorType vj = m_pcaBasisMatrix.row(idxj);
249 cov(i,j) = vi.dot(vj);
250 if (i == j) cov(i,j) += m_noiseVariance;
256 template <
typename T>
259 MatrixType M = m_pcaBasisMatrix * m_pcaBasisMatrix.transpose();
260 M.diagonal() += m_noiseVariance * VectorType::Ones(m_pcaBasisMatrix.rows());
265 template <
typename T>
268 DatasetPointerType sample;
269 sample = m_representer->CloneDataset(dataset);
270 VectorType v = ComputeCoefficientsForSample(sample);
271 m_representer->DeleteDataset(sample);
275 template <
typename T>
278 return ComputeCoefficientsForSampleVector(m_representer->SampleToSampleVector(sample));
281 template <
typename T>
285 CheckAndUpdateCachedParameters();
287 const MatrixType& WT = m_pcaBasisMatrix.transpose();
289 VectorType coeffs = m_MInverseMatrix * (WT * (sample - m_mean));
295 template <
typename T>
298 PointIdValueListType ptIdValueList;
300 for (
typename PointValueListType::const_iterator it = pointValueList.begin();
301 it != pointValueList.end();
303 ptIdValueList.push_back(PointIdValuePairType(m_representer->GetPointIdForPoint(it->first), it->second));
305 return ComputeCoefficientsForPointIDValues(ptIdValueList, pointValueNoiseVariance);
308 template <
typename T>
312 unsigned dim = m_representer->GetDimensions();
314 double noiseVariance = std::max(pointValueNoiseVariance, (
double) m_noiseVariance);
317 MatrixType PCABasisPart(pointIdValueList.size()* dim, this->GetNumberOfPrincipalComponents());
318 VectorType muPart(pointIdValueList.size() * dim);
319 VectorType sample(pointIdValueList.size() * dim);
322 for (
typename PointIdValueListType::const_iterator it = pointIdValueList.begin(); it != pointIdValueList.end(); ++it) {
323 VectorType val = this->m_representer->PointSampleToPointSampleVector(it->second);
324 unsigned pt_id = it->first;
325 for (
unsigned d = 0; d < dim; d++) {
326 PCABasisPart.row(i * dim + d) = this->GetPCABasisMatrix().row(m_representer->MapPointIdToInternalIdx(pt_id, d));
327 muPart[i * dim + d] = this->GetMeanVector()[m_representer->MapPointIdToInternalIdx(pt_id, d)];
328 sample[i * dim + d] = val[d];
333 MatrixType M = PCABasisPart.transpose() * PCABasisPart;
334 M.diagonal() += noiseVariance * VectorType::Ones(PCABasisPart.cols());
335 VectorType coeffs = M.inverse() * PCABasisPart.transpose() * (sample - muPart);
341 template <
typename T>
344 VectorType alpha = ComputeCoefficientsForDataset(ds);
345 return ComputeLogProbabilityOfCoefficients(alpha);
348 template <
typename T>
351 VectorType alpha = ComputeCoefficientsForDataset(ds);
352 return ComputeProbabilityOfCoefficients(alpha);
356 template <
typename T>
359 return log(pow(2 * PI, -0.5 * this->GetNumberOfPrincipalComponents())) - 0.5 * coefficents.squaredNorm();
362 template <
typename T>
365 return pow(2 * PI, - 0.5 * this->GetNumberOfPrincipalComponents()) * exp(- 0.5 * coefficients.squaredNorm());
369 template <
typename T>
372 VectorType alpha = ComputeCoefficientsForDataset(ds);
373 return std::sqrt(alpha.squaredNorm());
377 template <
typename T>
445 template <
typename T>
448 return m_noiseVariance;
452 template <
typename T>
458 template <
typename T>
461 return m_pcaVariance;
465 template <
typename T>
468 return m_pcaBasisMatrix;
471 template <
typename T>
477 assert(m_pcaVariance.maxCoeff() > 1e-8);
478 VectorType D = m_pcaVariance.array().sqrt();
479 return m_pcaBasisMatrix * DiagMatrixType(D).inverse();
484 template <
typename T>
487 m_modelInfo = modelInfo;
491 template <
typename T>
499 template <
typename T>
502 return m_pcaBasisMatrix.cols();
505 template <
typename T>
509 unsigned Dimensions = m_representer->GetDimensions();
510 MatrixType J = MatrixType::Zero(Dimensions, GetNumberOfPrincipalComponents());
512 unsigned ptId = m_representer->GetPointIdForPoint(pt);
514 for(
unsigned i = 0; i < Dimensions; i++) {
515 unsigned idx = m_representer->MapPointIdToInternalIdx(ptId, i);
516 for(
unsigned j = 0; j < GetNumberOfPrincipalComponents(); j++) {
517 J(i,j) += m_pcaBasisMatrix(idx,j) ;
524 template <
typename T>
532 file = H5::H5File(filename.c_str(), H5F_ACC_RDONLY);
533 }
catch (H5::Exception& e) {
534 std::string msg(std::string(
"could not open HDF5 file \n") + e.getCDetailMsg());
538 H5::Group modelRoot = file.openGroup(
"/");
540 newModel = Load(representer, modelRoot, maxNumberOfPCAComponents);
549 template <
typename T>
556 H5::Group representerGroup = modelRoot.openGroup(
"./representer");
558 representer->Load(representerGroup);
559 representerGroup.close();
563 int minorVersion = 0;
564 int majorVersion = 0;
569 std::cout <<
"Warning: version attribute does not exist in hdf5 file. Assuming version 0.8" <<std::endl;
573 H5::Group versionGroup = modelRoot.openGroup(
"./version");
578 H5::Group modelGroup = modelRoot.openGroup(
"./model");
580 statismo::VectorType pcaVariance;
582 newModel->m_pcaVariance = pcaVariance;
586 if (majorVersion == 0 && minorVersion == 8) {
587 HDF5Utils::readMatrix(modelGroup,
"./pcaBasis", maxNumberOfPCAComponents, newModel->m_pcaBasisMatrix);
588 }
else if (majorVersion ==0 && minorVersion == 9) {
589 MatrixType orthonormalPCABasis;
592 VectorType D = pcaVariance.array().sqrt();
593 newModel->m_pcaBasisMatrix = orthonormalPCABasis * DiagMatrixType(D);
595 std::ostringstream os;
596 os <<
"an invalid statismo version was provided (" << majorVersion <<
"." << minorVersion <<
")";
602 newModel->m_modelInfo.
Load(modelRoot);
604 }
catch (H5::Exception& e) {
605 std::string msg(std::string(
"an exeption occured while reading HDF5 file") +
606 "The most likely cause is that the hdf5 file does not contain the required objects. \n" + e.getCDetailMsg());
610 assert(newModel != 0);
611 newModel->m_cachedValuesValid =
false;
613 newModel->m_modelLoaded =
true;
618 template <
typename T>
623 if (m_modelLoaded ==
true) {
624 throw StatisticalModelException(
"Cannot save the model: Note, to prevent inconsistencies in the model's history, only models that have been newly created can be saved, and not those loaded from an hdf5 file.");
630 std::ifstream ifile(filename.c_str());
633 file = H5::H5File( filename.c_str(), H5F_ACC_TRUNC);
634 }
catch (H5::FileIException& e) {
635 std::string msg(std::string(
"Could not open HDF5 file for writing \n") + e.getCDetailMsg());
640 H5::Group modelRoot = file.openGroup(
"/");
642 H5::Group versionGroup = modelRoot.createGroup(
"version");
645 versionGroup.close();
652 template <
typename T>
659 std::string dataTypeStr = RepresenterType::TypeToString(m_representer->GetType());
661 H5::Group representerGroup = modelRoot.createGroup(
"./representer");
666 this->m_representer->Save(representerGroup);
667 representerGroup.close();
669 H5::Group modelGroup = modelRoot.createGroup(
"./model" );
676 m_modelInfo.Save(modelRoot);
679 }
catch (H5::Exception& e) {
680 std::string msg(std::string(
"an exception occurred while writing HDF5 file \n") + e.getCDetailMsg());
685 template <
typename T>
689 if (m_cachedValuesValid ==
false) {
690 VectorType I = VectorType::Ones(m_pcaBasisMatrix.cols());
691 MatrixType Mmatrix = m_pcaBasisMatrix.transpose() * m_pcaBasisMatrix;
692 Mmatrix.diagonal() += m_noiseVariance * I;
694 m_MInverseMatrix = Mmatrix.inverse();
697 m_cachedValuesValid =
true;
static bool existsObjectWithName(const H5::CommonFG &fg, const std::string &name)
Definition: HDF5Utils.hxx:542
static void readMatrix(const H5::CommonFG &fg, const char *name, MatrixType &matrix)
Definition: HDF5Utils.hxx:154
static StatisticalModel * Load(Representer< T > *representer, const std::string &filename, unsigned maxNumberOfPCAComponents=std::numeric_limits< unsigned >::max())
Definition: StatisticalModel.hxx:526
ValueType DrawSampleAtPoint(const VectorType &coefficients, const PointType &point, bool addNoise=false) const
Definition: StatisticalModel.hxx:191
VectorType ComputeCoefficientsForPointIDValues(const PointIdValueListType &pointValues, double pointValueNoiseVariance=0.0) const
Definition: StatisticalModel.hxx:310
double ComputeMahalanobisDistanceForDataset(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:371
static H5::DataSet writeMatrix(const H5::CommonFG &fg, const char *name, const MatrixType &matrix)
Definition: HDF5Utils.hxx:248
const ModelInfo & GetModelInfo() const
Definition: StatisticalModel.hxx:493
A trivial representer, that does no representation at all, but works directly with vectorial data...
Definition: TrivialVectorialRepresenter.h:83
VectorType DrawSampleVector(const VectorType &coefficients, bool addNoise=false) const
Definition: StatisticalModel.hxx:170
Used to indicate that a method has not yet been implemented.
Definition: Exceptions.h:50
MatrixType GetOrthonormalPCABasisMatrix() const
Definition: StatisticalModel.hxx:473
VectorType ComputeCoefficientsForSample(DatasetConstPointerType sample) const
Definition: StatisticalModel.hxx:277
float GetNoiseVariance() const
Definition: StatisticalModel.hxx:447
VectorType ComputeCoefficientsForSampleVector(const VectorType &sample) const
Definition: StatisticalModel.hxx:283
VectorType RobustlyComputeCoefficientsForDataset(DatasetConstPointerType dataset, unsigned nIterations=100, unsigned nu=6, double sigma2=1) const
Definition: StatisticalModel.hxx:379
DatasetPointerType DrawPCABasisSample(unsigned componentNumber) const
Definition: StatisticalModel.hxx:157
static void writeStringAttribute(const H5::H5Object &group, const char *name, const std::string &s)
Definition: HDF5Utils.hxx:387
static float readFloat(const H5::CommonFG &fg, const char *name)
Definition: HDF5Utils.hxx:452
virtual ~StatisticalModel()
Definition: StatisticalModel.hxx:73
static H5::DataSet writeInt(const H5::CommonFG &fg, const char *name, int value)
Definition: HDF5Utils.hxx:426
MatrixType GetCovarianceMatrix() const
Definition: StatisticalModel.hxx:258
Generic Exception class for the statismo Library.
Definition: Exceptions.h:68
const VectorType & GetPCAVarianceVector() const
Definition: StatisticalModel.hxx:460
const MatrixType & GetPCABasisMatrix() const
Definition: StatisticalModel.hxx:467
void SetModelInfo(const ModelInfo &modelInfo)
Definition: StatisticalModel.hxx:486
ValueType DrawMeanAtPoint(const PointType &point) const
Definition: StatisticalModel.hxx:120
stores meta information about the model, such as e.g. the name (uri) of the datasets used to build th...
Definition: ModelInfo.h:61
DatasetPointerType DatasetToSample(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:88
DatasetPointerType DrawMean() const
Definition: StatisticalModel.hxx:112
double ComputeProbabilityOfCoefficients(const VectorType &coefficients) const
Definition: StatisticalModel.hxx:364
static void readVector(const H5::CommonFG &fg, const char *name, unsigned nElements, VectorType &vector)
Definition: HDF5Utils.hxx:296
static H5::DataSet writeVector(const H5::CommonFG &fg, const char *name, const VectorType &vector)
Definition: HDF5Utils.hxx:363
MatrixType GetJacobian(const PointType &pt) const
Definition: StatisticalModel.hxx:507
double ComputeProbabilityOfDataset(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:350
unsigned int GetNumberOfPrincipalComponents() const
Definition: StatisticalModel.hxx:501
VectorType ComputeCoefficientsForDataset(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:267
ValueType EvaluateSampleAtPoint(DatasetConstPointerType sample, unsigned ptId) const
Definition: StatisticalModel.hxx:105
double ComputeLogProbabilityOfDataset(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:343
MatrixType GetCovarianceAtPoint(const PointType &pt1, const PointType &pt2) const
Definition: StatisticalModel.hxx:230
const VectorType & GetMeanVector() const
Definition: StatisticalModel.hxx:454
static H5::DataSet writeFloat(const H5::CommonFG &fg, const char *name, float value)
Definition: HDF5Utils.hxx:444
DatasetPointerType DrawSample(const VectorType &coefficients, bool addNoise=false) const
Definition: StatisticalModel.hxx:150
A Point/Value pair that is used to specify a value at a given point.
Definition: StatisticalModel.h:100
virtual void Load(const H5::CommonFG &publicFg)
Definition: ModelInfo.cxx:118
void Save(const std::string &filename) const
Definition: StatisticalModel.hxx:620
double ComputeLogProbabilityOfCoefficients(const VectorType &coefficients) const
Definition: StatisticalModel.hxx:358
static int readInt(const H5::CommonFG &fg, const char *name)
Definition: HDF5Utils.hxx:434
VectorType ComputeCoefficientsForPointValues(const PointValueListType &pointValues, double pointValueNoiseVariance=0.0) const
Definition: StatisticalModel.hxx:297