infomax_ica.cc

Go to the documentation of this file.
00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00041 #include "infomax_ica.h"
00042 
00046 InfomaxICA::InfomaxICA(){
00047 
00048 }
00049 
00050 InfomaxICA::InfomaxICA(double lambda, int b, double epsilon):
00051   lambda_(lambda),
00052   b_(b),
00053   epsilon_(epsilon){
00054 
00055 }
00056 
00061 void InfomaxICA::applyICA(const Matrix &dataset){
00062   double current_cos=DBL_MAX;
00063   w_.Init(b_,b_);
00064   data_.Init(dataset.n_rows(),dataset.n_cols());
00065   la::ScaleOverwrite(1.0,dataset,&data_);
00066   if (b_<data_.n_cols()){
00067     sphere(data_);
00068     // initial estimate for w is Id
00069     Matrix i1 = eye(data_.n_rows(),double(1));
00070     la::ScaleOverwrite(1.0,i1,&w_);    
00071     while (epsilon_<=current_cos){
00072       Matrix w_prev;
00073       w_prev.Copy(w_);
00074       evaluateICA();
00075       current_cos = w_delta(w_prev,w_);
00076     }
00077   }
00078   else
00079     fprintf(stdout,"Window size must be less than number of instances.");
00080 }
00081 
00085 void InfomaxICA::evaluateICA(){
00086   Matrix BI = eye(w_.n_rows(),double(b_));
00087   // intermediate calculation variables
00088   Matrix icv = Matrix(w_.n_rows(),b_);
00089   Matrix icv2 = Matrix(w_.n_rows(),w_.n_cols());
00090   Matrix icv4 = Matrix(w_.n_rows(),w_.n_cols());
00091   for (index_t i=0;i<data_.n_cols();i+=b_){
00092     if (i+b_<data_.n_cols()){
00093       Matrix subm;
00094       data_.MakeColumnSlice(i,b_,&subm);
00095       la::MulExpert(1,false,w_,false,subm,0.0,&icv);
00096       la::Scale(double(-1.0),&icv);
00097       expM(icv);  
00098       addOne(icv);
00099       invertVals(icv);
00100       la::Scale(-2.0,&icv);
00101       addOne(icv);
00102       la::MulExpert(1,false,icv,true,subm,0.0,&icv2);
00103       la::AddOverwrite(icv2,BI,&icv4);
00104       la::Scale(lambda_,&icv4);
00105       la::MulExpert(1,false,icv4,false,w_,0.0,&icv2);
00106       la::AddTo(w_.n_elements(),icv2.ptr(),w_.ptr());
00107     }
00108   }
00109 }
00110 
00111 // sphereing functions
00115 void InfomaxICA::sphere(Matrix &data){
00116   Matrix sample_covariance = sampleCovariance(data);
00117   Matrix wz = sqrtm(sample_covariance);
00118   Matrix wz_inverse = Matrix(wz.n_rows(),wz.n_cols());
00119   Matrix data_sub_means = subMeans(data);
00120   if (la::InverseOverwrite(wz,&wz_inverse)){
00121     la::Scale(wz.n_cols()*wz.n_rows(),2.0,wz_inverse.ptr());
00122     la::MulOverwrite(wz_inverse,data_sub_means,&data);
00123   }
00124 }
00125 
00126 // Covariance matrix.
00127 Matrix InfomaxICA::sampleCovariance(const Matrix &m){
00128   Matrix ttm = subMeans(m);
00129   Matrix wm = Matrix(m.n_cols(),m.n_rows());  
00130   la::TransposeOverwrite(ttm,&wm);
00131 
00132   Matrix twm = Matrix(ttm.n_rows(),ttm.n_rows());
00133   Matrix output = Matrix(ttm.n_rows(),ttm.n_rows());
00134   output.SetZero();
00135   Matrix tttm = Matrix(wm);
00136 
00137   la::Scale(tttm.n_rows()*tttm.n_cols(),1/(double(ttm.n_cols())-1),tttm.ptr());
00138   la::MulTransAOverwrite(wm,tttm,&twm);
00139   la::AddOverwrite(twm.n_rows()*twm.n_cols(),twm.ptr(),twm.ptr(),output.ptr());
00140   la::Scale(output.n_rows()*output.n_cols(),double(0.5),output.ptr());
00141   return output;
00142 }
00143 
00144 Matrix InfomaxICA::subMeans(const Matrix &m){
00145   Matrix output = Matrix(m);
00146   Vector row_means = rowMean(output);
00147   la::Scale(row_means.length(),-1.0,row_means.ptr());
00148   for (index_t j=0;j<output.n_cols();j++){
00149     la::AddTo(row_means.length(),row_means.ptr(),output.GetColumnPtr(j));
00150   }  
00151   return output;
00152 }
00153 
00157 Vector InfomaxICA::rowMean(const Matrix &m){
00158   Vector row_means;
00159   row_means.Init(m.n_rows());
00160   row_means.SetZero();
00161   for (index_t j=0;j<m.n_cols();j++){
00162     la::AddTo(row_means.length(),m.GetColumnPtr(j),row_means.ptr());
00163   }
00164   la::Scale(row_means.length(),1/double(m.n_cols()),row_means.ptr());
00165   return row_means;
00166 }
00167 
00172 Matrix InfomaxICA::sqrtm(const Matrix &m){
00173   Matrix output = Matrix(m.n_rows(), m.n_cols());
00174   Matrix chol = Matrix(m);
00175   if (la::Cholesky(&chol)){
00176     Matrix u,vt;
00177     Vector s;
00178     la::TransposeSquare(&chol);
00179     if (la::SVDInit(chol,&s,&u,&vt)){
00180       Matrix S = Matrix(s.length(),s.length());
00181       Matrix tm1 = Matrix(u.n_rows(),S.n_cols());
00182       S.SetZero();
00183       S.SetDiagonal(s);
00184       la::MulExpert(1,false,u,false,S,0.0,&tm1);
00185       la::MulExpert(1,false,tm1,true,u,0.0,&output);
00186     }
00187     else
00188       fprintf(stderr,"infomaxICA sqrtm: SVD failed.\n");      
00189   }
00190   else
00191     fprintf(stderr,"infomaxICA sqrtm: Cholesky decomposition failed.\n");
00192   return output;
00193 }
00194 
00195 // Compare w estimates for convergence
00196 double InfomaxICA::w_delta(const Matrix &w_prev, const Matrix &w_pres){
00197   Matrix temp;
00198   Vector delta_c;
00199   Vector delta_r;
00200   double delta_dot;
00201   la::SubInit(w_pres,w_prev,&temp);
00202   vectorize(temp,delta_r);
00203   vectorize(temp,delta_c);
00204   delta_dot = la::Dot(delta_r.length(),delta_r.ptr(),delta_c.ptr());
00205   fprintf(stderr,"w change=%f\n",delta_dot);
00206   return delta_dot;
00207 }
00208 
00209 // utility functions
00210 
00214 void InfomaxICA::expM(Matrix &m){
00215   for (index_t i=0;i<m.n_rows();i++){
00216     for (index_t j=0;j<m.n_cols();j++){
00217       m.set(i,j,exp(m.get(i,j)));
00218     }
00219   }
00220 }
00221 
00225 void InfomaxICA::addOne(Matrix &m){
00226   for (index_t i=0;i<m.n_rows();i++){
00227     for (index_t j=0;j<m.n_cols();j++){
00228       m.set(i,j,m.get(i,j)+1);
00229     }
00230   }
00231 }
00232 
00236 void InfomaxICA::invertVals(Matrix &m){
00237   for (index_t i=0;i<m.n_rows();i++){
00238     for (index_t j=0;j<m.n_cols();j++){
00239       m.set(i,j,1/m.get(i,j));
00240     }
00241   }
00242 }
00243 
00247 Matrix InfomaxICA::eye(index_t dim, double diagVal){
00248   Matrix output;
00249   Vector *diag = new Vector();
00250   diag->Init(dim);
00251   diag->SetAll(diagVal);
00252   output.InitDiagonal(*diag);
00253   return output;
00254 }
00255 
00259 void InfomaxICA::vectorize(const Matrix &m, Vector &v){
00260   index_t v_ind = 0;
00261   v.Init(m.n_rows()*m.n_cols());
00262   for (index_t i=0;i<m.n_rows();i++){
00263     for (index_t j=0;j<m.n_cols();j++){
00264       v[v_ind]=m.get(i,j);
00265       v_ind++;
00266     }
00267   }
00268   
00269 }
00270 
00274 void InfomaxICA::displayMatrix(const Matrix &m){
00275   fprintf(stdout,"\n");
00276   for (index_t i=0;i<m.n_rows();i++){
00277     for (index_t j=0;j<m.n_cols();j++){
00278       fprintf(stdout,"%f ",m.get(i,j));
00279     }
00280     fprintf(stdout,"\n");
00281   }  
00282 }
00283 
00287 void InfomaxICA::displayVector(const Vector &m){
00288   fprintf(stdout,"\n");
00289   for (index_t i=0;i<m.length();i++){
00290     fprintf(stdout,"%f ",m[i]);
00291   }
00292   fprintf(stdout,"\n");
00293 }
00294 
00299 void InfomaxICA::getUnmixing(Matrix &w){
00300   w.Copy(w_);
00301 }
00302 
00307 void InfomaxICA::getSources(const Matrix &dataset, Matrix &s){
00308   s.Init(dataset.n_rows(),dataset.n_cols());
00309   la::MulExpert(1.0,false,w_,false,dataset,0.0,&s);
00310 }
00311 
00312 void InfomaxICA::setLambda(const double lambda){
00313   lambda_=lambda;
00314 }
00315 
00316 void InfomaxICA::setB(const int b){
00317   b_=b;
00318 }
00319 
00320 void InfomaxICA::setEpsilon(const double epsilon){
00321   epsilon_=epsilon;
00322 }
Generated on Mon Jan 24 12:04:38 2011 for FASTlib by  doxygen 1.6.3