-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
93 lines (70 loc) · 1.71 KB
/
index.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
class SOM {
constructor({
mapSize,
vectorSize,
learningRate = 0.07,
radiusShrinkRate = 14000
}){
this.units = []
this.learningRate = learningRate
this.step = 0
this.radiusShrinkRate = radiusShrinkRate
this.build(mapSize,vectorSize)
}
build(mapSize,vectorSize){
for(var x = 0; x < mapSize; x++){
for(var y = 0; y < mapSize; y++){
const vector = Array.from({length: vectorSize},Math.random)
this.units.push({ x, y, vector })
}
}
}
compute(input){
const output = []
let bmi = {similarity: 0}
for(var i = 0; i < this.units.length; i++){
const unit = this.units[i]
const dist = this.getEuclideanDistance(input,unit.vector)
const similarity = 1 / (dist + 1)
output[i] = similarity
if(similarity > bmi.similarity){
bmi = {similarity, index: i}
}
}
return {
vector: output,
bmi: this.units[bmi.index],
bmiIndex: bmi.index
}
}
train(input,bmi){
this.step++
for(var i = 0; i < this.units.length; i++){
const unit = this.units[i]
const dist = this.getUnitDistance(bmi,unit)
for(var j = 0; j < input.length; j++){
const diff = input[j] - unit.vector[j]
unit.vector[j] += diff * dist * this.learningRate
}
}
}
getEuclideanDistance(a,b){
let sum = 0
for(var j = 0; j < a.length; j++){
sum += (a[j] - b[j]) ** 2
}
return Math.sqrt(sum)
}
getUnitDistance(a,b){
return Math.exp(
- (
(Math.pow(b.x - a.x, 2) / 2) +
(Math.pow(b.y - a.y, 2) / 2)
) * (
this.step / this.radiusShrinkRate
)
)
}
}
try { module.exports = SOM }
catch (e) {}