- Notifications
You must be signed in to change notification settings - Fork1
A tool for Non-negative matrix factorization
License
mljs/nGMCA
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A tool for non-negative matrix factorization.
$ npm install ml-ngmca
import{nGMCA}from'ml-ngmca';constresult=nGMCA(dataMatrix,options);
const{ nGMCA}=require('ml-ngmca');constresult=nGMCA(dataMatrix,options);
This algorithm is based on the articleJérémy Rapin, Jérôme Bobin, Anthony Larue, Jean-Luc Starck. Sparse and Non-negative BSS for Noisy Data, IEEE Transactions on Signal Processing, 2013.IEEE Transactions on Signal Processing, vol. 61, issue 22, p. 5620-5632, 2013.
In order to get a general idea of the problem you could also check theWikipedia article.
You will be able to separate the components of a mixture if you have a series of measurements correlated by a composition profile e.g NMR or mass spectra coming from a chromatographic coupled technique of two or more close retention times. So you will have a matrix with a number of rows equal or greater than the number of pure components of the mixture.
import{Matrix}from'ml-matrix';import{nGMCA}from'ml-ngmca';letpureSpectra=newMatrix([[1,0,1,0]]);letcomposition=newMatrix([[1,2,3,2,1]]);// matrix = composition.transpose().mmul(pureSpectra)letmatrix=newMatrix([[1,0,1,0],[2,0,2,0],[3,0,3,0],[2,0,2,0],[1,0,1,0],]);constoptions={maximumIteration:200,phaseRatio:0.4,};constresult=nGMCA(matrix,1,options);const{ A, S}=result;console.log(`A =${A.to2DArray()} S =${S.to2DArray()}`);/**A = [ [ 0.22941573387056177 ], [ 0.45883146774112354 ], [ 0.6882472016116853 ], [ 0.45883146774112354 ], [ 0.22941573387056177 ] ]S = [ [ 4.358898943540674, 0, 4.358898943540674, 0 ] ]if you reescale both S maxS and A with 1/maxS.*/letmaxByRow=[];for(leti=0;i<S.rows;i++){maxByRow.push(S.maxRow(i));}S.scale('row',{scale:maxByRow});A.scale('column',{scale:maxByRow.map((e)=>1/e),});/**S = [ [ 1, 0, 1, 0 ] ]A = [ [1.0000000000000002], [2.0000000000000004], [3.0000000000000004], [2.0000000000000004], [1.0000000000000002] ]*/constestimatedMatrix=A.mmul(S);constdiff=Matrix.sub(matrix,estimatedMatrix);
Here is a second example:
letmatrix=newMatrix([[0,0,1,1,1],[0,0,1,1,1],[2,2,2,0,0],[2,2,2,0,0],]);constoptions={maximumIteration:200,phaseRatio:0.4,};constresult=nGMCA(matrix,1,options);const{ A, S}=result;console.log(`A =${A} S =${S}`);/** A = [ [ 0.707107 0 0.707107 0 2.26e-17 0.707107 2.26e-17 0.707107 ]]S = [ [ 9.86e-32 9.86e-32 1.41421 1.41421 1.41421 2.82843 2.82843 2.82843 0 0 ]]note: 9.86e-32 and 2.26e-17 is practically zeroso if you reescale both S maxS and A with 1/maxS.*/letmaxByRow=[];for(leti=0;i<S.rows;i++){maxByRow.push(S.maxRow(i));}S.scale('row',{scale:maxByRow});A.scale('column',{scale:maxByRow.map((e)=>1/e),});console.log(`A =${A} S =${S}`);/** A = [ [ 1 0 1 0 0 1 0 1 ]]S = [ [ 0 0 1 1 1 2 2 2 0 0 ]]*/
The result has the matrices A and S, the estimated matrices of compositions and pureSpectra respectively. It's possible that the matrices A and S have not the same scale than pureSpectra and composition matrices because of AS has an infinity of combination to get the target matrix.
About
A tool for Non-negative matrix factorization