UNPKG

@ai-on-browser/data-analysis-models

Version:

Data analysis model package without any dependencies

86 lines (77 loc) 1.82 kB
import Matrix from '../util/matrix.js' /** * Method of Optimal Direction */ export default class MOD { // https://www.ieice.org/ess/sita/forum/article/2015/201512081915.pdf // https://en.wikipedia.org/wiki/Sparse_dictionary_learning /** * @param {number} m Reduced dimension * @param {number} [k] Sparsity parameter */ constructor(m, k = m) { this._m = m this._k = k } /** * Initialize model. * @param {Array<Array<number>>} x Training data */ init(x) { this._x = Matrix.fromArray(x) this._d = Matrix.randn(this._x.cols, this._m) this._d.div(Matrix.map(Matrix.map(this._d, v => v ** 2).mean(0), Math.sqrt)) } /** * Fit model and returns reduced values. * @returns {Array<Array<number>>} Predicted values */ fit() { const x = new Matrix(this._x.rows, this._m) for (let i = 0; i < this._x.rows; i++) { const xi = this._omp(this._x.row(i).t) x.set(i, 0, xi.t) } this._d = this._x.tDot(x.dot(x.tDot(x).inv())) this._r = x return this._r.toArray() } _omp(y) { const x = Matrix.zeros(this._m, 1) let r = y const s = [] for (let i = 0; i < this._k; i++) { let min_e = Infinity let min_i = -1 for (let k = 0; k < this._m; k++) { if (s.includes(k)) { continue } const a = this._d.col(k) const e = r.norm() ** 2 - a.tDot(r).toScaler() ** 2 / (a.norm() ** 2 + 1.0e-12) if (e < min_e) { min_e = e min_i = k } } s.push(min_i) const as = this._d.col(s) const xs = as.tDot(as).solve(as.tDot(y)) for (let i = 0; i < s.length; i++) { x.set(s[i], 0, xs.row(i)) } r = Matrix.sub(y, as.dot(xs)) if (r.norm() < 1.0e-8) { break } } return x } /** * Returns reduced values. * @returns {Array<Array<number>>} Predicted values */ predict() { return this._r.toArray() } }