-
Notifications
You must be signed in to change notification settings - Fork 55
Nnmf #80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Goneiross
wants to merge
63
commits into
mljs:main
Choose a base branch
from
Goneiross:NNMF
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Nnmf #80
Changes from 20 commits
Commits
Show all changes
63 commits
Select commit
Hold shift + click to select a range
b25e8db
Add minValue for randInt
Goneiross 00c765f
Add minValue for randInt
Goneiross 836538e
Add NNMF
Goneiross 5e5ae9b
fix for NMF
Goneiross d9accce
Change syntax
Goneiross 1dcab6f
Fix for nnmf
Goneiross 5cfc53d
Add error function
Goneiross 9185d71
Replace abs error by relative error
Goneiross f62f2e6
Add NNMF to Index
Goneiross 1663074
Add test for NNMF
Goneiross d3438bd
debug error
Goneiross 515900e
Debug NNMF.doError
Goneiross 1623c1a
Remove useless dependencies for NNMF test
Goneiross 317b298
Remove useless parameters for NNMF
Goneiross 8eea84e
small modifications
lpatiny af958ae
make doNnmf not accessible from outside
lpatiny ddb96ae
Change error as a getter
Goneiross ef06346
add examples folder
lpatiny 83dbb1f
add matrix examples
lpatiny cbb79bd
Add test for positivity
Goneiross d222b85
Change NNMF ini from rand to 0.5
Goneiross 41d8991
Add new test for NNMF
Goneiross d44a77c
Moved NNMF positivity function to test
Goneiross f2f28de
Change back NNMF ini to random matrix
Goneiross 8d1cf72
Change NNMF parameters from (Matrix, r, {iterations}) to (Matrix, r, …
Goneiross 844f8cc
Fix for NaN
Goneiross d11fe0a
Change tests
Goneiross 6786ecc
Change test case for a one with known global minimum
Goneiross 1aec29b
Need to correct NNMF to make test II work
Goneiross f67564a
Change error type
Goneiross e32fa91
Large fix
Goneiross af2e2fb
Remove debug from NNMF
Goneiross 20c0fbf
Remove useless console.log
Goneiross c8a8233
Change NNMF algorithm to reduce error
Goneiross 391502f
fix for non square matrix
Goneiross 00a9b41
Add new test
Goneiross 481b586
Change an exemple for the one in my pdf
Goneiross 421570e
Remove console.table
Goneiross 086d206
Add initialization for positiveLinearDependencies
Goneiross 27da318
Add JS info for function
Goneiross f601dd5
Add function to test linear combinations
Goneiross 6988d61
Add a test for positiveLinearCombination
Goneiross 29a5c40
Rename
Goneiross e309fb9
Moved an example
Goneiross ab9302b
Small fix for PLC but still not working properly
Goneiross f83557f
Now function remove some values in nA.X if not usefull
Goneiross fab98a6
Fix
Goneiross 6909d3d
Fix : NMMF and linear combination now both working
Goneiross 83bdd83
Small fix for end condition + Add base for decimal combination
Goneiross 1ffd24d
small fix
Goneiross 72060b4
Add test for decimal
Goneiross f9287a1
Add non working test case
Goneiross 3a28b5f
Add prototype of projection function
Goneiross 4a3a447
Revert "Add prototype of projection function"
Goneiross 3165750
Revert "Add non working test case"
Goneiross e0c4a1d
Remove LinearCombination
Goneiross 16b0181
Add a test comparing Matrix and this algo
Goneiross 4fb8864
Reduce number of rerandomisation to only two, better for little numbe…
Goneiross bed9cbe
Removed useless comments
Goneiross 52dd5e1
Merge remote-tracking branch 'origin/master' into NNMF
Goneiross 92ecdde
Fix syntax
Goneiross d5cb7e2
Update test cases
Goneiross 6d0ed02
Update matrix.d.ts
Goneiross File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import Matrix from '../src'; | ||
|
||
const test = [ | ||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 1, 0, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0], | ||
[5, 4, 3, 2, 1, 0, 0, 0, 0, 0] | ||
]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Matrix from '../src'; | ||
|
||
const test = [ | ||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 1, 0, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0], | ||
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0], | ||
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0], | ||
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0], | ||
[1, 1, 1, 1, 1, 1, 1, 1, 0, 0], | ||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 0], | ||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | ||
]; | ||
const targets = [ | ||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | ||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0], | ||
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0], | ||
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1], | ||
[4, 4, 2, 2, 0, 0, 0, 0, 0, 0] | ||
]; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { toBeDeepCloseTo } from 'jest-matcher-deep-close-to'; | ||
|
||
import { Matrix, NNMF } from '../..'; | ||
|
||
expect.extend({ toBeDeepCloseTo }); | ||
|
||
describe('Non-negative Matrix Factorization', () => { | ||
it('factorization', () => { | ||
let A = new Matrix([ | ||
[1, 0, 0, 0, 1], | ||
[0, 0, 0, 0, 0], | ||
[0, 0, 0, 0, 0], | ||
[0, 0, 0, 0, 0], | ||
[1, 0, 0, 0, 1] | ||
]); | ||
|
||
let nA = new NNMF(A, 4); | ||
expect(nA.X.mmul(nA.Y)).toBeDeepCloseTo(A); | ||
expect(nA.error).toBeDeepCloseTo(Matrix.zeros(5, 5)); | ||
expect(nA.positivity).toEqual(true); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import { Matrix, WrapperMatrix2D } from '../index'; | ||
|
||
/** | ||
* | ||
* @class NNMF | ||
* @link http://papers.nips.cc/paper/1861-algorithms-for-non-negative-matrix-factorization.pdf | ||
* @param {Matrix} A | ||
* @param {number} r | ||
* @param {object} [options={}] | ||
* @param {number} [options.numberIterations=1000] | ||
*/ | ||
export default class NNMF { | ||
constructor(A, r, options = {}) { | ||
const { numberIterations = 1000 } = options; | ||
A = WrapperMatrix2D.checkMatrix(A); | ||
var m = A.rows; | ||
var n = A.columns; | ||
|
||
this.r = r; | ||
this.A = A; | ||
this.m = m; | ||
this.n = n; | ||
this.X = Matrix.rand(m, r); | ||
this.Y = Matrix.rand(r, n); | ||
|
||
doNnmf.call(this, numberIterations); | ||
} | ||
|
||
/** | ||
* Compute the error | ||
*/ | ||
get error() { | ||
let error = new Matrix(this.m, this.n); | ||
let A2 = this.X.mmul(this.Y); | ||
for (let i = 0; i < this.m; i++) { | ||
for (let j = 0; j < this.n; j++) { | ||
error.set( | ||
i, | ||
j, | ||
Math.abs(A2.get(i, j) - this.A.get(i, j)) / | ||
(this.A.get(i, j) !== 0 ? this.A.get(i, j) : Number.EPSILON) | ||
); | ||
} | ||
} | ||
return (error); | ||
} | ||
get positivity() { | ||
let positive = true; | ||
for (let i = 0; i < this.m; i++) { | ||
for (let j = 0; j < this.r; j++) { | ||
if (this.X.get(i, j) < 0) { | ||
positive = false; | ||
} | ||
} | ||
} | ||
for (let i = 0; i < this.r; i++) { | ||
for (let j = 0; j < this.n; j++) { | ||
if (this.X.get(i, j) < 0) { | ||
positive = false; | ||
} | ||
} | ||
} | ||
return (positive); | ||
} | ||
} | ||
|
||
/** | ||
* Do the NNMF of a matrix A into two matrix X and Y | ||
* @param {number} [numberIterations=1000] | ||
*/ | ||
function doNnmf(numberIterations = 1000) { | ||
let A2 = this.X.mmul(this.Y); | ||
let numX = Matrix.empty(this.m, this.r); | ||
let denumX = Matrix.empty(this.m, this.r); | ||
|
||
let numY = Matrix.empty(this.r, this.n); | ||
let denumY = Matrix.empty(this.r, this.n); | ||
|
||
let temp1 = Matrix.empty(this.m, this.n); | ||
let temp2 = Matrix.empty(this.n, this.m); | ||
|
||
for (let a = 0; a < numberIterations; a++) { | ||
for (let i = 0; i < this.m; i++) { | ||
for (let j = 0; j < this.n; j++) { | ||
temp1.set(i, j, Math.pow(A2.get(i, j), -2) * this.A.get(i, j)); | ||
temp2.set(i, j, Math.pow(A2.get(i, j), -1)); | ||
} | ||
} | ||
numX = temp1.mmul(this.Y.transpose()); | ||
denumX = temp2.mmul(this.Y.transpose()); | ||
for (let i = 0; i < this.m; i++) { | ||
for (let j = 0; j < this.r; j++) { | ||
numX.set(i, j, numX.get(i, j) + Number.EPSILON); | ||
denumX.set(i, j, denumX.get(i, j) + Number.EPSILON); | ||
} | ||
} | ||
for (let i = 0; i < this.m; i++) { | ||
for (let j = 0; j < this.r; j++) { | ||
this.X.set( | ||
i, | ||
j, | ||
(this.X.get(i, j) * numX.get(i, j)) / denumX.get(i, j) | ||
); | ||
} | ||
} | ||
A2 = this.X.mmul(this.Y); | ||
for (let i = 0; i < this.m; i++) { | ||
for (let j = 0; j < this.n; j++) { | ||
A2.set(i, j, A2.get(i, j) + Number.EPSILON); | ||
} | ||
} | ||
|
||
for (let i = 0; i < this.m; i++) { | ||
for (let j = 0; j < this.n; j++) { | ||
temp1.set(i, j, Math.pow(A2.get(i, j), -2) * this.A.get(i, j)); | ||
temp2.set(i, j, Math.pow(A2.get(i, j), -1)); | ||
} | ||
} | ||
numY = this.X.transpose().mmul(temp1); | ||
denumY = this.X.transpose().mmul(temp2); | ||
for (let i = 0; i < this.r; i++) { | ||
for (let j = 0; j < this.n; j++) { | ||
numY.set(i, j, numY.get(i, j) + Number.EPSILON); | ||
denumY.set(i, j, denumY.get(i, j) + Number.EPSILON); | ||
} | ||
} | ||
for (let i = 0; i < this.r; i++) { | ||
for (let j = 0; j < this.n; j++) { | ||
this.Y.set( | ||
i, | ||
j, | ||
(this.Y.get(i, j) * numY.get(i, j)) / denumY.get(i, j) | ||
); | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.