/
rls.js
59 lines (54 loc) · 1.24 KB
/
rls.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import Matrix from '../util/matrix.js'
/**
* Recursive least squares
*/
export default class RecursiveLeastSquares {
// https://en.wikipedia.org/wiki/Online_machine_learning
constructor() {
this._w = null
this._s = null
}
/**
* Update model parameters with one data.
*
* @param {Matrix} x Training data
* @param {number} y Target value
*/
update(x, y) {
const ds = this._s.dot(x).dot(x.tDot(this._s))
ds.div(1 + x.tDot(this._s).dot(x).toScaler())
this._s.sub(ds)
const dw = this._s.dot(x)
dw.mult(x.tDot(this._w).toScaler() - y)
this._w.sub(dw)
}
/**
* Fit model.
*
* @param {Array<Array<number>>} x Training data
* @param {number[]} y Target values
*/
fit(x, y) {
x = Matrix.fromArray(x)
const xh = Matrix.resize(x, x.rows, x.cols + 1, 1)
if (!this._w) {
this._w = Matrix.zeros(xh.cols, 1)
this._s = Matrix.eye(xh.cols, xh.cols)
}
for (let i = 0; i < x.rows; i++) {
this.update(xh.row(i).t, y[i])
}
}
/**
* Returns predicted datas.
*
* @param {Array<Array<number>>} data Sample data
* @returns {number[]} Predicted values
*/
predict(data) {
const x = Matrix.fromArray(data)
const xh = Matrix.resize(x, x.rows, x.cols + 1, 1)
const r = xh.dot(this._w)
return r.value
}
}