
Simple ICA


Igor
#pragma rtGlobals=3 // Use modern global access method. #pragma IgorVersion=6.2 // Requires Igor 6.2 // // simpleICA(inX,reqComponents,w_init) // Parameters: // inX is a 2D wave where columns contain a finite mix of independent components. // reqComponents is the number of independent components that you want to extract. // This number must be less than or equal to the number of columns of inX. // w_init is a 2D wave of dimensions (reqComponents x reqComponents) and contains // an estimate of the mixing matrix. You can simply pass $"" for this parameter // so the algorithm will use an equivalent size matrix filled with enoise(). // // The results of the function are the waves ICARes and WunMixing. ICARes is a 2D // wave in which each column contains an independent component. WunMixing is a 2D // wave that can be used to multiply the (re)conditioned input in order to obtain the unmixed // components. // // The code below implements the "deflation" approach for fastICA. It is based on the // fastICA algorithm: Hyvärinen,A (1999). Fast and Robust Fixed-Point Algorithms // for Independent Component Analysis. IEEE Transactions on Neural Networks, 10(3),626-634. // // See testing example below the main function. Function simpleICA(inX,reqComponents,w_init) Wave inX,w_init Variable reqComponents // The following 3 variables can be converted into function arguments. Variable maxNumIterations=1000 Variable tolerance=1e-5 Variable alpha=1 Variable i,ii Variable iteration Variable nRows=DimSize(inX,0) Variable nCols=DimSize(inX,1) // check the number of requested components: if(reqComponents>min(dimSize(inX,0),dimSize(inX,1))) doAlert 0,"Bad requested number of components" return 0 endif // Never mess up the original data Duplicate/O/Free inX,xx // Initialize the w matrix if it is not provided. if(WaveExists(w_init)==0) Make/O/N=(reqComponents,reqComponents) w_init=enoise(1) endif // condition and transpose the input: MatrixOP/O xx=(NormalizeCols(subtractMean(xx,1)))^t // Just like PCA: MatrixOP/O/Free V=(xx x (xx^t))/nRows MatrixSVD V // M_VT is not used here. Wave M_U,W_W,M_VT W_W=1.0/sqrt(w_w) MatrixOP/O/Free D=diagonal(W_W) MatrixOP/O/FREE K=D x (M_U^t) KillWaves/z W_W,M_U,M_VT Duplicate/Free/R=[0,reqComponents-1][] k,kk Duplicate/O/FREE kk,k // X1 could be output as PCA result. MatrixOP/O/FREE X1=K x xx // create and initialize working W; this is not an output! Make/O/Free/N=(reqComponents,reqComponents) W=0 for(i=1;i<=reqComponents;i+=1) MatrixOP/O/FREE lcw=row(w_init,i-1) // decorrelating if(i>1) Duplicate/O/Free lcw,tt tt=0 for(ii=0;ii<i;ii+=1) MatrixOP/O/Free r_ii=row(W,ii) // row ii of matrix W MatrixOP/O/FREE ru=sum(lcw*r_ii) // dot product Variable ks=ru[0] MatrixOP/O/Free tt=tt+ks*r_ii endfor MatrixOP/O/FREE lcw=lcw-tt endif MatrixOP/O/Free lcw=normalize(lcw) // iterate till convergence: for(iteration=1;iteration<maxNumIterations;iteration+=1) MatrixOP/O/Free wxProduct=lcw x x1 // should be supported by matrixop :( Duplicate/O/Free wxProduct,gwx gwx=tanh(alpha*wxProduct) Duplicate/Free/R=[reqComponents,nRows] gwx,gwxf Make/O/Free/N=(reqComponents,nRows) gwxf // repeat the values from the first row on. gwxf=gwx[q] Duplicate/O/FREE gwxf,gwx MatrixOP/O/Free x1gwxProd=x1*gwx Duplicate/O/FREE wxProduct,gwx2 gwx2=alpha*(1-(tanh(alpha*wxProduct))^2) Variable theMean=mean(gwx2) MatrixOP/O/Free wPlus=(sumRows(x1gwxProd)/numCols(x1gwxProd))^t-theMean*lcw // reduce components Redimension/N=(1,reqComponents) wPlus // starting from the second component; if(i>1) Duplicate/O/FREE wPlus,tt tt=0 for(ii=0;ii<i;ii+=1) MatrixOP/O/Free r_ii=row(W,ii) MatrixOP/O/FREE ru=wPlus.(r_ii^t) ks=ru[0] MatrixOP/O tt=tt+ks*r_ii endfor wPlus=wPlus-tt endif MatrixOP/O/FREE wPlus=normalize(wPlus) MatrixOP/O/Free limV=abs(mag(sum(wPlus*lcw))-1) printf "Iteration %d, diff=%g\r",iteration,limV[0] lcw=wPlus if(limV[0]<tolerance) break endif endfor // store the computed row in final W. W[i-1][]=lcw[q] endfor // loop over components // Calculate the un-mixing matrix MatrixOP/O WunMixing=W x K // Un-mix; MatrixOP/O ICARes=(WunMixing x xx)^t End Function testICA() // Create distinct frequencies: Make/O/N=(1000,3) ddd ddd[][0]=sin(2*pi*x/13) ddd[][1]=sin(2*pi*x/17) ddd[][2]=sin(2*pi*x/23) // Create mixing matrix: Make/O/N=(3,3) AA AA[0][0]= {0.291,0.6557,-0.5439} AA[0][1]= {0.5572,0.3,-0.2} AA[0][2]= {-0.1,-0.7,0.4} // Do your mixing: MatrixOP/O xx=ddd x AA // Try the ICA simpleICA(xx,3,$"") // Plot the results: Wave ICARes Display ICARes[][0] Display ICARes[][1] Display ICARes[][2] End

Forum

Support

Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More