1
- class AffinityPropagation {
1
+ export default class AffinityPropagation {
2
2
// https://qiita.com/daiki_yosky/items/98ce56e37623c369cc60
3
3
// https://tjo.hatenablog.com/entry/2014/07/31/190218
4
4
constructor ( ) {
5
- this . _epoch = 0 ;
6
- this . _l = 0.8 ;
5
+ this . _epoch = 0
6
+ this . _l = 0.8
7
7
8
- this . _x = [ ] ;
9
- this . _y = null ;
8
+ this . _x = [ ]
9
+ this . _y = null
10
10
}
11
11
12
12
get centroidCategories ( ) {
13
- const y = this . predict ( ) ;
13
+ const y = this . predict ( )
14
14
return [ ...new Set ( y ) ]
15
15
}
16
16
17
17
get centroids ( ) {
18
- return this . centroidCategories . map ( i => this . _x [ i ] ) ;
18
+ return this . centroidCategories . map ( i => this . _x [ i ] )
19
19
}
20
20
21
21
get size ( ) {
22
- const y = this . predict ( ) ;
22
+ const y = this . predict ( )
23
23
return new Set ( y ) . size
24
24
}
25
25
@@ -28,49 +28,49 @@ class AffinityPropagation {
28
28
}
29
29
30
30
init ( datas ) {
31
- this . _x = datas ;
32
- const n = datas . length ;
33
- this . _r = Array ( n ) ;
34
- this . _a = Array ( n ) ;
35
- this . _ar = Array ( n ) ;
36
- this . _s = Array ( n ) ;
37
- this . _as = Array ( n ) ;
31
+ this . _x = datas
32
+ const n = datas . length
33
+ this . _r = Array ( n )
34
+ this . _a = Array ( n )
35
+ this . _ar = Array ( n )
36
+ this . _s = Array ( n )
37
+ this . _as = Array ( n )
38
38
for ( let i = 0 ; i < n ; i ++ ) {
39
39
this . _r [ i ] = Array ( n ) . fill ( 0 )
40
40
this . _a [ i ] = Array ( n ) . fill ( 0 )
41
41
this . _ar [ i ] = Array ( n ) . fill ( 0 )
42
42
this . _s [ i ] = Array ( n )
43
43
this . _as [ i ] = Array ( n )
44
44
}
45
- this . _y = null ;
46
- this . _epoch = 0 ;
45
+ this . _y = null
46
+ this . _epoch = 0
47
47
48
48
let min = Infinity
49
49
for ( let i = 0 ; i < n ; i ++ ) {
50
50
for ( let j = 0 ; j < i ; j ++ ) {
51
51
if ( i === j ) continue
52
52
const d = - this . _x [ i ] . reduce ( ( s , v , k ) => s + ( v - this . _x [ j ] [ k ] ) ** 2 , 0 )
53
- this . _s [ i ] [ j ] = this . _s [ j ] [ i ] = d ;
54
- this . _as [ i ] [ j ] = this . _as [ j ] [ i ] = d ;
53
+ this . _s [ i ] [ j ] = this . _s [ j ] [ i ] = d
54
+ this . _as [ i ] [ j ] = this . _as [ j ] [ i ] = d
55
55
min = Math . min ( min , d )
56
56
}
57
57
}
58
58
for ( let i = 0 ; i < n ; i ++ ) {
59
- this . _s [ i ] [ i ] = this . _as [ i ] [ i ] = min ;
59
+ this . _s [ i ] [ i ] = this . _as [ i ] [ i ] = min
60
60
}
61
61
}
62
62
63
63
fit ( ) {
64
64
// Frey. et al. "Clustering by Passing Messages Between Data Points" (2007)
65
65
// "Fast Algorithm for Affinity Propagation"
66
- const x = this . _x ;
67
- const n = x . length ;
66
+ const x = this . _x
67
+ const n = x . length
68
68
const l = this . _l
69
69
70
70
for ( let i = 0 ; i < n ; i ++ ) {
71
71
for ( let k = 0 ; k < n ; k ++ ) {
72
72
let m = - Infinity
73
- const ss = ( i === k ) ? this . _s [ i ] : this . _as [ i ] ;
73
+ const ss = i === k ? this . _s [ i ] : this . _as [ i ]
74
74
for ( let kd = 0 ; kd < n ; kd ++ ) {
75
75
if ( k === kd ) continue
76
76
m = Math . max ( m , ss [ kd ] )
@@ -81,52 +81,52 @@ class AffinityPropagation {
81
81
82
82
for ( let i = 0 ; i < n ; i ++ ) {
83
83
for ( let k = 0 ; k < n ; k ++ ) {
84
- let s = ( i === k ) ? 0 : this . _r [ k ] [ k ] ;
84
+ let s = i === k ? 0 : this . _r [ k ] [ k ]
85
85
for ( let id = 0 ; id < n ; id ++ ) {
86
86
if ( id !== i && id !== k ) {
87
87
s += Math . max ( 0 , this . _r [ id ] [ k ] )
88
88
}
89
89
}
90
90
if ( i !== k ) s = Math . min ( 0 , s )
91
- const aik = l * this . _a [ i ] [ k ] + ( 1 - l ) * s ;
92
- this . _a [ i ] [ k ] = aik ;
93
- this . _ar [ i ] [ k ] = aik + this . _r [ i ] [ k ] ;
94
- this . _as [ i ] [ k ] = aik + this . _s [ i ] [ k ] ;
91
+ const aik = l * this . _a [ i ] [ k ] + ( 1 - l ) * s
92
+ this . _a [ i ] [ k ] = aik
93
+ this . _ar [ i ] [ k ] = aik + this . _r [ i ] [ k ]
94
+ this . _as [ i ] [ k ] = aik + this . _s [ i ] [ k ]
95
95
}
96
96
}
97
97
98
- this . _y = null ;
99
- this . _epoch ++ ;
98
+ this . _y = null
99
+ this . _epoch ++
100
100
}
101
101
102
102
__fit ( ) {
103
103
// Frey. et al. "Mixture Modeling by Affinity Propagation" (2006)
104
- const x = this . _x ;
105
- const n = x . length ;
104
+ const x = this . _x
105
+ const n = x . length
106
106
107
107
for ( let i = 0 ; i < n ; i ++ ) {
108
108
for ( let j = 0 ; j < n ; j ++ ) {
109
- let s = 0 ;
109
+ let s = 0
110
110
for ( let k = 0 ; k < n ; k ++ ) {
111
111
if ( k === j ) continue
112
- s += this . _a [ i ] [ k ] * this . _s [ i ] [ k ] ;
112
+ s += this . _a [ i ] [ k ] * this . _s [ i ] [ k ]
113
113
}
114
114
this . _r [ i ] [ j ] = this . _s [ i ] [ j ] / s
115
115
}
116
116
}
117
117
118
118
for ( let i = 0 ; i < n ; i ++ ) {
119
- let p = 1 ;
119
+ let p = 1
120
120
for ( let k = 0 ; k < n ; k ++ ) {
121
121
if ( k === i ) continue
122
- p *= ( 1 + this . _r [ k ] [ i ] ) ;
122
+ p *= 1 + this . _r [ k ] [ i ]
123
123
}
124
124
this . _a [ i ] [ i ] = p - 1
125
125
this . _ar [ i ] [ i ] = this . _a [ i ] [ i ] + this . _r [ i ] [ i ]
126
126
127
127
for ( let j = 0 ; j < n ; j ++ ) {
128
- if ( i === j ) continue ;
129
- p = 1 / this . _r [ i ] [ i ] - 1 ;
128
+ if ( i === j ) continue
129
+ p = 1 / this . _r [ i ] [ i ] - 1
130
130
for ( let k = 0 ; k < n ; k ++ ) {
131
131
if ( k === i || k === j ) continue
132
132
p *= 1 / ( 1 + this . _r [ k ] [ i ] )
@@ -135,64 +135,27 @@ class AffinityPropagation {
135
135
this . _ar [ i ] [ j ] = this . _a [ i ] [ j ] + this . _r [ i ] [ j ]
136
136
}
137
137
}
138
- this . _y = null ;
139
- this . _epoch ++ ;
138
+ this . _y = null
139
+ this . _epoch ++
140
140
}
141
141
142
142
predict ( ) {
143
143
if ( ! this . _y ) {
144
- this . _y = [ ] ;
145
- const n = this . _x . length ;
144
+ this . _y = [ ]
145
+ const n = this . _x . length
146
146
for ( let i = 0 ; i < n ; i ++ ) {
147
- let max_v = - Infinity ;
148
- let max_i = - 1 ;
147
+ let max_v = - Infinity
148
+ let max_i = - 1
149
149
for ( let j = 0 ; j < n ; j ++ ) {
150
- const v = this . _ar [ i ] [ j ] ;
150
+ const v = this . _ar [ i ] [ j ]
151
151
if ( max_v < v ) {
152
- max_v = v ;
153
- max_i = j ;
152
+ max_v = v
153
+ max_i = j
154
154
}
155
155
}
156
- this . _y . push ( max_i ) ;
156
+ this . _y . push ( max_i )
157
157
}
158
158
}
159
- return this . _y ;
159
+ return this . _y
160
160
}
161
161
}
162
-
163
- var dispAffinityPropagation = function ( elm , platform ) {
164
- let model = null
165
-
166
- const fitModel = ( cb ) => {
167
- platform . fit (
168
- ( tx , ty , pred_cb ) => {
169
- if ( ! model ) {
170
- model = new AffinityPropagation ( ) ;
171
- model . init ( tx ) ;
172
- }
173
- model . fit ( )
174
- const pred = model . predict ( ) ;
175
- pred_cb ( pred . map ( v => v + 1 ) )
176
- elm . select ( "[name=clusters]" ) . text ( model . size ) ;
177
- platform . centroids ( model . centroids , model . centroidCategories . map ( v => v + 1 ) )
178
- cb && cb ( )
179
- }
180
- ) ;
181
- }
182
-
183
- platform . setting . ml . controller . stepLoopButtons ( ) . init ( ( ) => {
184
- model = null
185
- elm . select ( "[name=clusters]" ) . text ( 0 ) ;
186
- platform . init ( )
187
- } ) . step ( fitModel ) . epoch ( )
188
- elm . append ( "span" )
189
- . text ( " Clusters: " ) ;
190
- elm . append ( "span" )
191
- . attr ( "name" , "clusters" ) ;
192
- }
193
-
194
- export default function ( platform ) {
195
- platform . setting . ml . usage = 'Click and add data point. Then, click "Step" button repeatedly.'
196
- dispAffinityPropagation ( platform . setting . ml . configElement , platform )
197
- }
198
-
0 commit comments