/
tukey_regression.js
57 lines (52 loc) · 1.15 KB
/
tukey_regression.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
import Matrix from '../util/matrix.js'
/**
* Tukey regression
*/
export default class TukeyRegression {
// https://www.smartbowwow.com/2019/05/blog-post.html
/**
* @param {number} e Error tolerance
*/
constructor(e) {
this._e = e
this._w = null
}
/**
* Fit model.
*
* @param {Array<Array<number>>} x Training data
* @param {Array<Array<number>>} y Target values
*/
fit(x, y) {
x = Matrix.fromArray(x)
const xh = Matrix.resize(x, x.rows, x.cols + 1, 1)
y = Matrix.fromArray(y)
if (!this._w) {
this._w = xh.tDot(xh).solve(xh.tDot(y))
}
const r = xh.dot(this._w)
r.sub(y)
r.map(v => {
if (Math.abs(v) <= this._e) {
return ((1 - v ** 2) / this._e ** 2) ** 2
}
return 0
})
for (let i = 0; i < this._w.cols; i++) {
const xhw = Matrix.mult(xh, r.col(i))
const w = xhw.tDot(xh).solve(xhw.tDot(y.col(i)))
this._w.set(0, i, w)
}
}
/**
* Returns predicted values.
*
* @param {Array<Array<number>>} x Sample data
* @returns {Array<Array<number>>} Predicted values
*/
predict(x) {
x = Matrix.fromArray(x)
const xh = Matrix.resize(x, x.rows, x.cols + 1, 1)
return xh.dot(this._w).toArray()
}
}