/
rdf.js
61 lines (57 loc) · 1.3 KB
/
rdf.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
60
61
/**
* Relative Density Factor
*/
export default class RDF {
// Progress in Outlier Detection Techniques: A Survey
// https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8786096
// RDF: a density-based outlier detection method using vertical data representation
/**
* @param {number} [r] Radius
*/
constructor(r = 1.0) {
this._r = r
}
_distance(a, b) {
return Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0))
}
/**
* Returns anomaly degrees.
*
* @param {Array<Array<number>>} datas Training data
* @returns {number[]} Predicted values
*/
predict(datas) {
const n = datas.length
const distances = []
for (let i = 0; i < n; i++) {
distances[i] = []
distances[i][i] = { d: 0, i }
for (let j = 0; j < i; j++) {
const d = this._distance(datas[i], datas[j])
distances[i][j] = { d, i: j }
distances[j][i] = { d, i }
}
}
const nbrs = []
for (let i = 0; i < n; i++) {
distances[i].sort((a, b) => a.d - b.d)
nbrs[i] = 0
for (let j = 0; j < n; j++) {
if (distances[i][j].d < this._r) {
nbrs[i]++
}
}
}
const rdf = []
for (let i = 0; i < n; i++) {
rdf[i] = 0
for (let j = 0; j < n; j++) {
if (distances[i][j].d < this._r) {
rdf[i] += nbrs[distances[i][j].i]
}
}
rdf[i] /= nbrs[i] ** 2
}
return rdf
}
}