@@ -61,6 +61,7 @@ GMM* gmm_new(int M, int D, const char *cov_type)
61
61
gmm -> covars [k ] = malloc (1 * sizeof (double ));
62
62
}
63
63
64
+
64
65
return gmm ;
65
66
}
66
67
@@ -92,7 +93,7 @@ void gmm_set_initialization_method(GMM *gmm, const char *method)
92
93
}
93
94
}
94
95
95
- void gmm_fit (GMM * gmm , const double * const * X , int N )
96
+ void gmm_fit (GMM * gmm , const double * X , int N )
96
97
{
97
98
// Initialize GMM parameters
98
99
_gmm_init_params (gmm , X , N );
@@ -133,7 +134,7 @@ void gmm_fit(GMM *gmm, const double * const *X, int N)
133
134
free (gmm -> P_k_giv_xt );
134
135
}
135
136
136
- double gmm_score (GMM * gmm , const double * const * X , int N )
137
+ double gmm_score (GMM * gmm , const double * X , int N )
137
138
{
138
139
// Allocate memory for storing membership probabilities P(k | x_t)
139
140
gmm -> P_k_giv_xt = malloc (gmm -> M * sizeof (double * ));
@@ -152,7 +153,7 @@ double gmm_score(GMM *gmm, const double * const *X, int N)
152
153
}
153
154
154
155
// TODO: Other initialization methods
155
- void _gmm_init_params (GMM * gmm , const double * const * X , int N )
156
+ void _gmm_init_params (GMM * gmm , const double * X , int N )
156
157
{
157
158
if (gmm -> init_method == RANDOM )
158
159
{
@@ -172,14 +173,14 @@ void _gmm_init_params(GMM *gmm, const double * const *X, int N)
172
173
}
173
174
174
175
// TODO: Unique sampling of data points for initializing component means
175
- void _gmm_init_params_random (GMM * gmm , const double * const * X , int N )
176
+ void _gmm_init_params_random (GMM * gmm , const double * X , int N )
176
177
{
177
178
// Initialize means to randomly chosen samples
178
179
srand (time (NULL ));
179
180
for (int k = 0 ; k < gmm -> M ; k ++ )
180
181
{
181
182
int r = rand ()%N ;
182
- memcpy (gmm -> means [k ], X [ r ], gmm -> D * sizeof (double ));
183
+ memcpy (gmm -> means [k ], & X [ gmm -> D * r ], gmm -> D * sizeof (double ));
183
184
}
184
185
185
186
// Initialize component weights to same value
@@ -189,7 +190,7 @@ void _gmm_init_params_random(GMM *gmm, const double * const *X, int N)
189
190
// Initialize component variances to data variance
190
191
double * mean = calloc (gmm -> D , sizeof (double ));
191
192
for (int t = 0 ; t < N ; t ++ )
192
- _gmm_vec_add (mean , X [ t ], 1 , 1 , gmm -> D );
193
+ _gmm_vec_add (mean , & X [ gmm -> D * t ], 1 , 1 , gmm -> D );
193
194
_gmm_vec_divide_by_scalar (mean , N , gmm -> D );
194
195
if (gmm -> cov_type == DIAGONAL )
195
196
{
@@ -198,7 +199,7 @@ void _gmm_init_params_random(GMM *gmm, const double * const *X, int N)
198
199
{
199
200
vars [i ] = 0 ;
200
201
for (int t = 0 ; t < N ; t ++ )
201
- vars [i ] += _gmm_pow2 (X [t ][ i ] - mean [i ]);
202
+ vars [i ] += _gmm_pow2 (X [gmm -> D * t + i ] - mean [i ]);
202
203
vars [i ] = vars [i ]/N ;
203
204
}
204
205
for (int k = 0 ; k < gmm -> M ; k ++ )
@@ -209,7 +210,7 @@ void _gmm_init_params_random(GMM *gmm, const double * const *X, int N)
209
210
{
210
211
double var = 0 ;
211
212
for (int t = 0 ; t < N ; t ++ )
212
- var += _gmm_pow2 (_gmm_vec_l2_dist (X [ t ], mean , gmm -> D ));
213
+ var += _gmm_pow2 (_gmm_vec_l2_dist (& X [ gmm -> D * t ], mean , gmm -> D ));
213
214
var = var /(N * gmm -> D );
214
215
for (int k = 0 ; k < gmm -> M ; k ++ )
215
216
gmm -> covars [k ][0 ] = var ;
@@ -222,7 +223,7 @@ void _gmm_init_params_random(GMM *gmm, const double * const *X, int N)
222
223
// TODO: Handle empty clusters in K-means
223
224
// TODO: Unique sampling of data points for initializing component means
224
225
// TODO: Make K-means more efficient
225
- void _gmm_init_params_kmeans (GMM * gmm , const double * const * X , int N )
226
+ void _gmm_init_params_kmeans (GMM * gmm , const double * X , int N )
226
227
{
227
228
const int num_iter = 10 ;
228
229
@@ -231,7 +232,7 @@ void _gmm_init_params_kmeans(GMM *gmm, const double * const *X, int N)
231
232
for (int k = 0 ; k < gmm -> M ; k ++ )
232
233
{
233
234
int r = rand ()%N ;
234
- memcpy (gmm -> means [k ], X [ r ], gmm -> D * sizeof (double ));
235
+ memcpy (gmm -> means [k ], & X [ gmm -> D * r ], gmm -> D * sizeof (double ));
235
236
}
236
237
237
238
// K-means iterative algorithm
@@ -243,11 +244,11 @@ void _gmm_init_params_kmeans(GMM *gmm, const double * const *X, int N)
243
244
// Find assiciation of each data point
244
245
for (int t = 0 ; t < N ; t ++ )
245
246
{
246
- double min_dist = _gmm_vec_l2_dist (X [ t ], gmm -> means [0 ], gmm -> D );
247
+ double min_dist = _gmm_vec_l2_dist (& X [ gmm -> D * t ], gmm -> means [0 ], gmm -> D );
247
248
associations [t ] = 0 ;
248
249
for (int k = 1 ; k < gmm -> M ; k ++ )
249
250
{
250
- double dist = _gmm_vec_l2_dist (X [ t ], gmm -> means [k ], gmm -> D );
251
+ double dist = _gmm_vec_l2_dist (& X [ gmm -> D * t ], gmm -> means [k ], gmm -> D );
251
252
if (dist < min_dist )
252
253
{
253
254
min_dist = dist ;
@@ -266,7 +267,7 @@ void _gmm_init_params_kmeans(GMM *gmm, const double * const *X, int N)
266
267
if (associations [t ] == k )
267
268
{
268
269
nk ++ ;
269
- _gmm_vec_add (gmm -> means [k ], X [ t ], 1 , 1 , gmm -> D );
270
+ _gmm_vec_add (gmm -> means [k ], & X [ gmm -> D * t ], 1 , 1 , gmm -> D );
270
271
}
271
272
}
272
273
_gmm_vec_divide_by_scalar (gmm -> means [k ], nk , gmm -> D );
@@ -293,11 +294,11 @@ void _gmm_init_params_kmeans(GMM *gmm, const double * const *X, int N)
293
294
{
294
295
nk ++ ;
295
296
if (gmm -> cov_type == SPHERICAL )
296
- gmm -> covars [k ][0 ] += _gmm_pow2 (_gmm_vec_l2_dist (X [ t ], gmm -> means [k ], gmm -> D ));
297
+ gmm -> covars [k ][0 ] += _gmm_pow2 (_gmm_vec_l2_dist (& X [ gmm -> D * t ], gmm -> means [k ], gmm -> D ));
297
298
else if (gmm -> cov_type == DIAGONAL )
298
299
{
299
300
for (int i = 0 ; i < gmm -> D ; i ++ )
300
- gmm -> covars [k ][i ] += _gmm_pow2 (X [t ][ i ] - gmm -> means [k ][i ]);
301
+ gmm -> covars [k ][i ] += _gmm_pow2 (X [gmm -> D * t + i ] - gmm -> means [k ][i ]);
301
302
}
302
303
}
303
304
}
@@ -322,7 +323,7 @@ void _gmm_init_params_kmeans(GMM *gmm, const double * const *X, int N)
322
323
free (associations );
323
324
}
324
325
325
- double _gmm_em_step (GMM * gmm , const double * const * X , int N )
326
+ double _gmm_em_step (GMM * gmm , const double * X , int N )
326
327
{
327
328
double llh ;
328
329
@@ -339,7 +340,7 @@ double _gmm_em_step(GMM *gmm, const double * const *X, int N)
339
340
return llh ;
340
341
}
341
342
342
- double _gmm_compute_membership_prob (GMM * gmm , const double * const * X , int N )
343
+ double _gmm_compute_membership_prob (GMM * gmm , const double * X , int N )
343
344
{
344
345
double llh = 0 ;
345
346
@@ -350,7 +351,7 @@ double _gmm_compute_membership_prob(GMM *gmm, const double * const *X, int N)
350
351
double max = -1 ;
351
352
for (int k = 0 ; k < gmm -> M ; k ++ )
352
353
{
353
- gmm -> P_k_giv_xt [k ][t ] = log (gmm -> weights [k ]) + _gmm_log_gaussian_pdf (X [ t ], gmm -> means [k ], gmm -> covars [k ], gmm -> D , gmm -> cov_type );
354
+ gmm -> P_k_giv_xt [k ][t ] = log (gmm -> weights [k ]) + _gmm_log_gaussian_pdf (& X [ gmm -> D * t ], gmm -> means [k ], gmm -> covars [k ], gmm -> D , gmm -> cov_type );
354
355
if (gmm -> P_k_giv_xt [k ][t ] > max )
355
356
max = gmm -> P_k_giv_xt [k ][t ];
356
357
}
@@ -371,7 +372,7 @@ double _gmm_compute_membership_prob(GMM *gmm, const double * const *X, int N)
371
372
return llh ;
372
373
}
373
374
374
- void _gmm_update_params (GMM * gmm , const double * const * X , int N )
375
+ void _gmm_update_params (GMM * gmm , const double * X , int N )
375
376
{
376
377
if (gmm -> cov_type == SPHERICAL )
377
378
{
@@ -384,8 +385,8 @@ void _gmm_update_params(GMM *gmm, const double * const *X, int N)
384
385
for (int t = 0 ; t < N ; t ++ )
385
386
{
386
387
sum_P_k += gmm -> P_k_giv_xt [k ][t ];
387
- sum_xxP_k += _gmm_vec_dot_prod (X [ t ], X [ t ], gmm -> D ) * gmm -> P_k_giv_xt [k ][t ];
388
- _gmm_vec_add (gmm -> means [k ], X [ t ], 1 , gmm -> P_k_giv_xt [k ][t ], gmm -> D );
388
+ sum_xxP_k += _gmm_vec_dot_prod (& X [ gmm -> D * t ], & X [ gmm -> D * t ], gmm -> D ) * gmm -> P_k_giv_xt [k ][t ];
389
+ _gmm_vec_add (gmm -> means [k ], & X [ gmm -> D * t ], 1 , gmm -> P_k_giv_xt [k ][t ], gmm -> D );
389
390
}
390
391
_gmm_vec_divide_by_scalar (gmm -> means [k ], sum_P_k , gmm -> D );
391
392
gmm -> weights [k ] = sum_P_k /N ;
@@ -404,7 +405,7 @@ void _gmm_update_params(GMM *gmm, const double * const *X, int N)
404
405
for (int t = 0 ; t < N ; t ++ )
405
406
{
406
407
sum_P_k += gmm -> P_k_giv_xt [k ][t ];
407
- _gmm_vec_add (gmm -> means [k ], X [ t ], 1 , gmm -> P_k_giv_xt [k ][t ], gmm -> D );
408
+ _gmm_vec_add (gmm -> means [k ], & X [ gmm -> D * t ], 1 , gmm -> P_k_giv_xt [k ][t ], gmm -> D );
408
409
}
409
410
gmm -> weights [k ] = sum_P_k /N ;
410
411
_gmm_vec_divide_by_scalar (gmm -> means [k ], sum_P_k , gmm -> D );
@@ -413,7 +414,7 @@ void _gmm_update_params(GMM *gmm, const double * const *X, int N)
413
414
for (int t = 0 ; t < N ; t ++ )
414
415
{
415
416
for (int i = 0 ; i < gmm -> D ; i ++ )
416
- gmm -> covars [k ][i ] += gmm -> P_k_giv_xt [k ][t ]* _gmm_pow2 (X [t ][ i ] - gmm -> means [k ][i ]);
417
+ gmm -> covars [k ][i ] += gmm -> P_k_giv_xt [k ][t ]* _gmm_pow2 (X [gmm -> D * t + i ] - gmm -> means [k ][i ]);
417
418
}
418
419
_gmm_vec_divide_by_scalar (gmm -> covars [k ], sum_P_k , gmm -> D );
419
420
for (int i = 0 ; i < gmm -> D ; i ++ )
0 commit comments