00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
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     
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   
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 
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 
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 
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 
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 }