@ai-on-browser/data-analysis-models
Version:
Data analysis model package without any dependencies
80 lines (70 loc) • 1.55 kB
JavaScript
import Matrix from '../util/matrix.js'
/**
* Partial least squares regression
*/
export default class PLS {
/**
* @param {number} l Limit on the number of latent factors
*/
constructor(l) {
this._l = l
}
/**
* Initialize model.
* @param {Array<Array<number>>} x Training data
* @param {Array<Array<number>>} y Target values
*/
init(x, y) {
this._x = Matrix.fromArray(x)
this._y = Matrix.fromArray(y)
}
/**
* Fit model.
*/
fit() {
if (this._y.cols === 1) {
;[this._b, this._b0] = this._pls1()
} else {
throw ''
}
}
_pls1() {
// https://ja.wikipedia.org/wiki/部分的最小二乗回帰
let x = this._x.copy()
let w = x.tDot(this._y)
w.div(w.norm())
const ws = []
const ps = []
const qs = []
for (let k = 0; k < this._l; k++) {
const t = x.dot(w)
const tk = t.tDot(t).toScaler()
t.div(tk)
const p = x.tDot(t)
const qk = this._y.tDot(t).toScaler()
ps.push(p.value)
qs.push(qk)
ws.push(w.value)
if (qk === 0) break
const xsub = t.dot(p.t)
xsub.mult(tk)
x.sub(xsub)
w = x.tDot(this._y)
}
const W = Matrix.fromArray(ws).t
const P = Matrix.fromArray(ps).t
const q = new Matrix(qs.length, 1, qs)
const B = W.dot(P.tDot(W).solve(q))
const B0 = qs[0] - P.col(0).tDot(B).toScaler()
return [B, B0]
}
/**
* Returns predicted values.
* @param {Array<Array<number>>} x Sample data
* @returns {Array<Array<number>>} Predicted values
*/
predict(x) {
x = Matrix.fromArray(x)
return Matrix.add(x.dot(this._b), this._b0).toArray()
}
}