Xmipp  v3.23.11-Nereus
probabilisticPCA.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Author: Itziar Benito Ortega (2013)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "probabilisticPCA.h"
27 #include "core/multidim_array.h"
28 #include "core/xmipp_funcs.h"
29 
31 {
32  this->Niters=Niters;
33 }
34 
36 {
37  size_t N=MAT_YSIZE(*X); // N= number of rows of X
38  size_t D=MAT_XSIZE(*X); // D= number of columns of X
39 
40  bool converged=false;
41  size_t iter=0;
42  double sigma2=rnd_unif()*2;
43  double Q=MAXDOUBLE, oldQ;
44 
45  Matrix2D<double> S, W, inW, invM, Ez, WtX, Wp1, Wp2, invWp2, WinvM, WinvMWt, WtSDIW, invCS;
46 
47  // Compute variance and row energy
50  S/=(double)N;
51  Matrix1D<double> normX;
52  X->rowEnergySum(normX);
53 
55  matrixOperation_AtA(W,inW);
56 
58  while (!converged && iter<=Niters)
59  {
60  ++iter;
61 
62  // Perform E-step
63  // Ez=(W^t*W)^-1*W^t*X^t
64  for (size_t i=0; i<outputDim; ++i)
65  MAT_ELEM(inW,i,i)+=sigma2;
66  inW.inv(invM);
67  matrixOperation_AtBt(W,*X,WtX);
68  matrixOperation_AB(invM,WtX,Ez);
69 
70  for (size_t k=0; k<N; ++k)
72  DIRECT_A3D_ELEM(Ezz,k,i,j)=MAT_ELEM(invM,i,j)*sigma2+MAT_ELEM(Ez,i,k)*MAT_ELEM(Ez,j,k);
73 
74  // Perform M-step (maximize mapping W)
75  Wp1.initZeros(D,outputDim);
76  Wp2.initZeros(outputDim,outputDim);
77  for (size_t k=0; k<N; ++k)
78  {
80  MAT_ELEM(Wp1,i,j)+=MAT_ELEM(*X,k,i)*MAT_ELEM(Ez,j,k);
82  MAT_ELEM(Wp2,i,j)+=DIRECT_A3D_ELEM(Ezz,k,i,j);
83  }
84 
85  Wp2.inv(invWp2);
86  matrixOperation_AB(Wp1,invWp2,W);
87  matrixOperation_AtA(W,inW);
88 
89  // Update sigma2
90  double sigma2_new=0;
91  for (size_t k=0; k<N; ++k){
92  double EzWtX=0;
94  EzWtX+=MAT_ELEM(*X,k,i)*MAT_ELEM(W,i,j)*MAT_ELEM(Ez,j,k);
95 
96  double t=0;
97  for (size_t i = 0; i < outputDim; ++i)
98  {
99  double aux=0.;
100  for (size_t kk = 0; kk < outputDim; ++kk)
101  aux += DIRECT_A3D_ELEM(Ezz,k,i,kk) * MAT_ELEM(inW, kk, i);
102  t+=aux;
103  }
104 
105  sigma2_new += VEC_ELEM(normX,k) - 2 * EzWtX + t;
106  }
107  sigma2_new/=(double) N * (double) D;
108 
109  //Compute likelihood of new model
110  oldQ = Q;
111 
112  if (iter > 1)
113  {
114  matrixOperation_AB(W,invM,WinvM);
115  matrixOperation_ABt(WinvM,W,WinvMWt);
116  matrixOperation_IminusA(WinvMWt);
117  WinvMWt*=1/sigma2_new;
118 
119  matrixOperation_AtA(W,WtSDIW);
120  WtSDIW*=1/sigma2_new;
121  matrixOperation_IplusA(WtSDIW);
122 
123  double detC = pow(sigma2_new,D)* WtSDIW.det();
124 
125  matrixOperation_AB(WinvMWt,S,invCS);
126  Q = (N*(-0.5)) * (D * log (2*PI) + log(detC) + invCS.trace());
127  }
128 
129  // Stop condition to detect convergence
130  // Must not apply to the first iteration, because then it will end inmediately
131  if (iter>2 && abs(oldQ-Q) < 0.001)
132  converged=true;
133 
134  sigma2=sigma2_new;
135  }
136 
137  //mapping.M = (inW \ W')';
138  matrixOperation_ABt(W,inW.inv(),A);
140  if (fnMapping!="")
141  A.write(fnMapping);
142 }
#define FOR_ALL_ELEMENTS_IN_MATRIX2D(m)
Definition: matrix2d.h:104
#define MAT_YSIZE(m)
Definition: matrix2d.h:124
#define MAXDOUBLE
Definition: data_types.h:51
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
void subtractColumnMeans(Matrix2D< double > &A)
Definition: matrix2d.cpp:230
Matrix2D< double > Y
Output data.
Definition: dimred_tools.h:147
void matrixOperation_AB(const Matrix2D< double > &A, const Matrix2D< double > &B, Matrix2D< double > &C)
Definition: matrix2d.cpp:411
void setSpecificParameters(size_t Niters=200)
Set specific parameters.
Matrix2D< double > * X
Pointer to input data.
Definition: dimred_tools.h:141
T trace() const
Definition: matrix2d.cpp:1304
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
void abs(Image< double > &op)
glob_prnt iter
void matrixOperation_IminusA(Matrix2D< double > &A)
Definition: matrix2d.cpp:533
void matrixOperation_AtA(const Matrix2D< double > &A, Matrix2D< double > &B)
Definition: matrix2d.cpp:436
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
size_t outputDim
Output dim.
Definition: dimred_tools.h:144
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
double rnd_unif()
void log(Image< double > &op)
void rowEnergySum(Matrix1D< T > &sum) const
Definition: matrix2d.cpp:795
T det() const
Definition: matrix2d.cpp:38
void matrixOperation_IplusA(Matrix2D< double > &A)
Definition: matrix2d.cpp:527
void matrixOperation_ABt(const Matrix2D< double > &A, const Matrix2D< double > &B, Matrix2D< double > &C)
Definition: matrix2d.cpp:462
#define DIRECT_A3D_ELEM(v, k, i, j)
#define j
FileName fnMapping
Save mapping.
Definition: dimred_tools.h:153
#define MAT_XSIZE(m)
Definition: matrix2d.h:120
void write(const FileName &fn) const
Definition: matrix2d.cpp:113
void initRandom(size_t Ydim, size_t Xdim, double op1, double op2, RandomMode mode=RND_UNIFORM)
Definition: matrix2d.cpp:1108
void initZeros()
Definition: matrix2d.h:626
Matrix2D< double > A
void reduceDimensionality()
Reduce dimensionality.
#define PI
Definition: tools.h:43
void matrixOperation_AtBt(const Matrix2D< double > &A, const Matrix2D< double > &B, Matrix2D< double > &C)
Definition: matrix2d.cpp:500