ml-ngmca
Version:
non-negative Generalized Morphological Component Analysis
46 lines (41 loc) • 1.31 kB
JavaScript
import { Matrix, EVD } from 'ml-matrix';
import { normBy } from '../util/normBy';
import { normProj } from '../util/normProj';
import { zeroInsteadOfNegative } from '../util/zeroInsteadOfNegative';
export function updateMatrixA(Ainit, S, originalMatrix, options) {
let {
maxFBIteration,
toleranceFB,
normConstrained = false,
lambda,
} = options;
let St = S.transpose();
let H = S.mmul(St);
let YSt = originalMatrix.mmul(St);
let evd = new EVD(H, { assumeSymmetric: true });
let L = Math.max(...evd.realEigenvalues);
let A = Ainit;
let prevA = A.clone();
let t = 1;
let gradient = (a) => a.mmul(H).sub(YSt);
let proximal;
if (normConstrained) {
let normLimits = normBy(Ainit, 'column');
proximal = (x, threshold) =>
normProj(zeroInsteadOfNegative(x.subS(threshold)), normLimits);
} else {
proximal = (x, threshold) => zeroInsteadOfNegative(x.subS(threshold));
}
for (let i = 0; i < maxFBIteration; i++) {
let tNext = (1 + Math.sqrt(1 + 4 * t * t)) / 2;
let w = (t - 1) / tNext;
t = tNext;
let B = Matrix.mul(A, w + 1).sub(Matrix.mul(prevA, w));
prevA = A.clone();
A = proximal(B.sub(gradient(B).divS(L)), lambda / L);
if (Matrix.sub(prevA, A).norm() / A.norm() < toleranceFB) {
break;
}
}
return A;
}