Mercurial > hg > qm-dsp
comparison hmm/hmm.c @ 483:fdaa63607c15
Untabify, indent, tidy
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Fri, 31 May 2019 11:54:32 +0100 |
parents | 7e8d1f26b098 |
children | d48276a3ae24 |
comparison
equal
deleted
inserted
replaced
482:cbe668c7d724 | 483:fdaa63607c15 |
---|---|
14 | 14 |
15 #include <stdio.h> | 15 #include <stdio.h> |
16 #include <math.h> | 16 #include <math.h> |
17 #include <stdlib.h> | 17 #include <stdlib.h> |
18 #include <float.h> | 18 #include <float.h> |
19 #include <time.h> /* to seed random number generator */ | 19 #include <time.h> /* to seed random number generator */ |
20 | 20 |
21 #include <clapack.h> /* LAPACK for matrix inversion */ | 21 #include <clapack.h> /* LAPACK for matrix inversion */ |
22 | 22 |
23 #include "maths/nan-inf.h" | 23 #include "maths/nan-inf.h" |
24 | 24 |
25 #ifdef ATLAS_ORDER | 25 #ifdef ATLAS_ORDER |
26 #define HAVE_ATLAS 1 | 26 #define HAVE_ATLAS 1 |
35 #endif | 35 #endif |
36 | 36 |
37 #ifdef _MAC_OS_X | 37 #ifdef _MAC_OS_X |
38 #include <vecLib/cblas.h> | 38 #include <vecLib/cblas.h> |
39 #else | 39 #else |
40 #include <cblas.h> /* BLAS for matrix multiplication */ | 40 #include <cblas.h> /* BLAS for matrix multiplication */ |
41 #endif | 41 #endif |
42 | 42 |
43 #include "hmm.h" | 43 #include "hmm.h" |
44 | 44 |
45 model_t* hmm_init(double** x, int T, int L, int N) | 45 model_t* hmm_init(double** x, int T, int L, int N) |
46 { | 46 { |
47 int i, j, d, e, t; | 47 int i, j, d, e, t; |
48 double s, ss; | 48 double s, ss; |
49 | 49 |
50 model_t* model; | 50 model_t* model; |
51 model = (model_t*) malloc(sizeof(model_t)); | 51 model = (model_t*) malloc(sizeof(model_t)); |
52 model->N = N; | 52 model->N = N; |
53 model->L = L; | 53 model->L = L; |
54 model->p0 = (double*) malloc(N*sizeof(double)); | 54 model->p0 = (double*) malloc(N*sizeof(double)); |
55 model->a = (double**) malloc(N*sizeof(double*)); | 55 model->a = (double**) malloc(N*sizeof(double*)); |
56 model->mu = (double**) malloc(N*sizeof(double*)); | 56 model->mu = (double**) malloc(N*sizeof(double*)); |
57 for (i = 0; i < N; i++) | 57 for (i = 0; i < N; i++) { |
58 { | 58 model->a[i] = (double*) malloc(N*sizeof(double)); |
59 model->a[i] = (double*) malloc(N*sizeof(double)); | 59 model->mu[i] = (double*) malloc(L*sizeof(double)); |
60 model->mu[i] = (double*) malloc(L*sizeof(double)); | 60 } |
61 } | 61 model->cov = (double**) malloc(L*sizeof(double*)); |
62 model->cov = (double**) malloc(L*sizeof(double*)); | 62 for (i = 0; i < L; i++) { |
63 for (i = 0; i < L; i++) | 63 model->cov[i] = (double*) malloc(L*sizeof(double)); |
64 model->cov[i] = (double*) malloc(L*sizeof(double)); | 64 } |
65 | 65 |
66 srand(time(0)); | 66 srand(time(0)); |
67 double* global_mean = (double*) malloc(L*sizeof(double)); | 67 double* global_mean = (double*) malloc(L*sizeof(double)); |
68 | 68 |
69 /* find global mean */ | 69 /* find global mean */ |
70 for (d = 0; d < L; d++) | 70 for (d = 0; d < L; d++) { |
71 { | 71 global_mean[d] = 0; |
72 global_mean[d] = 0; | 72 for (t = 0; t < T; t++) { |
73 for (t = 0; t < T; t++) | 73 global_mean[d] += x[t][d]; |
74 global_mean[d] += x[t][d]; | 74 } |
75 global_mean[d] /= T; | 75 global_mean[d] /= T; |
76 } | 76 } |
77 | 77 |
78 /* calculate global diagonal covariance */ | 78 /* calculate global diagonal covariance */ |
79 for (d = 0; d < L; d++) | 79 for (d = 0; d < L; d++) { |
80 { | 80 for (e = 0; e < L; e++) { |
81 for (e = 0; e < L; e++) | 81 model->cov[d][e] = 0; |
82 model->cov[d][e] = 0; | 82 } |
83 for (t = 0; t < T; t++) | 83 for (t = 0; t < T; t++) { |
84 model->cov[d][d] += (x[t][d] - global_mean[d]) * (x[t][d] - global_mean[d]); | 84 model->cov[d][d] += |
85 model->cov[d][d] /= T-1; | 85 (x[t][d] - global_mean[d]) * (x[t][d] - global_mean[d]); |
86 } | 86 } |
87 | 87 model->cov[d][d] /= T-1; |
88 /* set all means close to global mean */ | 88 } |
89 for (i = 0; i < N; i++) | 89 |
90 { | 90 /* set all means close to global mean */ |
91 for (d = 0; d < L; d++) | 91 for (i = 0; i < N; i++) { |
92 { | 92 for (d = 0; d < L; d++) { |
93 /* add some random noise related to covariance */ | 93 /* add some random noise related to covariance */ |
94 /* ideally the random number would be Gaussian(0,1), as a hack we make it uniform on [-0.25,0.25] */ | 94 /* ideally the random number would be Gaussian(0,1), |
95 model->mu[i][d] = global_mean[d] + (0.5 * rand() / (double) RAND_MAX - 0.25) * sqrt(model->cov[d][d]); | 95 as a hack we make it uniform on [-0.25,0.25] */ |
96 } | 96 model->mu[i][d] = global_mean[d] + |
97 } | 97 (0.5 * rand() / (double) RAND_MAX - 0.25) |
98 | 98 * sqrt(model->cov[d][d]); |
99 /* random intial and transition probs */ | 99 } |
100 s = 0; | 100 } |
101 for (i = 0; i < N; i++) | 101 |
102 { | 102 /* random initial and transition probs */ |
103 model->p0[i] = 1 + rand() / (double) RAND_MAX; | 103 s = 0; |
104 s += model->p0[i]; | 104 for (i = 0; i < N; i++) { |
105 ss = 0; | 105 model->p0[i] = 1 + rand() / (double) RAND_MAX; |
106 for (j = 0; j < N; j++) | 106 s += model->p0[i]; |
107 { | 107 ss = 0; |
108 model->a[i][j] = 1 + rand() / (double) RAND_MAX; | 108 for (j = 0; j < N; j++) { |
109 ss += model->a[i][j]; | 109 model->a[i][j] = 1 + rand() / (double) RAND_MAX; |
110 } | 110 ss += model->a[i][j]; |
111 for (j = 0; j < N; j++) | 111 } |
112 { | 112 for (j = 0; j < N; j++) { |
113 model->a[i][j] /= ss; | 113 model->a[i][j] /= ss; |
114 } | 114 } |
115 } | 115 } |
116 for (i = 0; i < N; i++) | 116 for (i = 0; i < N; i++) { |
117 model->p0[i] /= s; | 117 model->p0[i] /= s; |
118 | 118 } |
119 free(global_mean); | 119 |
120 | 120 free(global_mean); |
121 return model; | 121 |
122 return model; | |
122 } | 123 } |
123 | 124 |
124 void hmm_close(model_t* model) | 125 void hmm_close(model_t* model) |
125 { | 126 { |
126 int i; | 127 int i; |
127 | 128 |
128 for (i = 0; i < model->N; i++) | 129 for (i = 0; i < model->N; i++) { |
129 { | 130 free(model->a[i]); |
130 free(model->a[i]); | 131 free(model->mu[i]); |
131 free(model->mu[i]); | 132 } |
132 } | 133 free(model->a); |
133 free(model->a); | 134 free(model->mu); |
134 free(model->mu); | 135 for (i = 0; i < model->L; i++) { |
135 for (i = 0; i < model->L; i++) | 136 free(model->cov[i]); |
136 free(model->cov[i]); | 137 } |
137 free(model->cov); | 138 free(model->cov); |
138 free(model); | 139 free(model); |
139 } | 140 } |
140 | 141 |
141 void hmm_train(double** x, int T, model_t* model) | 142 void hmm_train(double** x, int T, model_t* model) |
142 { | 143 { |
143 int i, t; | 144 int i, t; |
144 double loglik; /* overall log-likelihood at each iteration */ | 145 double loglik; /* overall log-likelihood at each iteration */ |
145 | 146 |
146 int N = model->N; | 147 int N = model->N; |
147 int L = model->L; | 148 int L = model->L; |
148 double* p0 = model->p0; | 149 double* p0 = model->p0; |
149 double** a = model->a; | 150 double** a = model->a; |
150 double** mu = model->mu; | 151 double** mu = model->mu; |
151 double** cov = model->cov; | 152 double** cov = model->cov; |
152 | 153 |
153 /* allocate memory */ | 154 /* allocate memory */ |
154 double** gamma = (double**) malloc(T*sizeof(double*)); | 155 double** gamma = (double**) malloc(T*sizeof(double*)); |
155 double*** xi = (double***) malloc(T*sizeof(double**)); | 156 double*** xi = (double***) malloc(T*sizeof(double**)); |
156 for (t = 0; t < T; t++) | 157 for (t = 0; t < T; t++) { |
157 { | 158 gamma[t] = (double*) malloc(N*sizeof(double)); |
158 gamma[t] = (double*) malloc(N*sizeof(double)); | 159 xi[t] = (double**) malloc(N*sizeof(double*)); |
159 xi[t] = (double**) malloc(N*sizeof(double*)); | 160 for (i = 0; i < N; i++) { |
160 for (i = 0; i < N; i++) | 161 xi[t][i] = (double*) malloc(N*sizeof(double)); |
161 xi[t][i] = (double*) malloc(N*sizeof(double)); | 162 } |
162 } | 163 } |
163 | 164 |
164 /* temporary memory */ | 165 /* temporary memory */ |
165 double* gauss_y = (double*) malloc(L*sizeof(double)); | 166 double* gauss_y = (double*) malloc(L*sizeof(double)); |
166 double* gauss_z = (double*) malloc(L*sizeof(double)); | 167 double* gauss_z = (double*) malloc(L*sizeof(double)); |
167 | 168 |
168 /* obs probs P(j|{x}) */ | 169 /* obs probs P(j|{x}) */ |
169 double** b = (double**) malloc(T*sizeof(double*)); | 170 double** b = (double**) malloc(T*sizeof(double*)); |
170 for (t = 0; t < T; t++) | 171 for (t = 0; t < T; t++) { |
171 b[t] = (double*) malloc(N*sizeof(double)); | 172 b[t] = (double*) malloc(N*sizeof(double)); |
172 | 173 } |
173 /* inverse covariance and its determinant */ | 174 |
174 double** icov = (double**) malloc(L*sizeof(double*)); | 175 /* inverse covariance and its determinant */ |
175 for (i = 0; i < L; i++) | 176 double** icov = (double**) malloc(L*sizeof(double*)); |
176 icov[i] = (double*) malloc(L*sizeof(double)); | 177 for (i = 0; i < L; i++) { |
177 double detcov; | 178 icov[i] = (double*) malloc(L*sizeof(double)); |
178 | 179 } |
179 double thresh = 0.0001; | 180 double detcov; |
180 int niter = 50; | 181 |
181 int iter = 0; | 182 double thresh = 0.0001; |
182 double loglik1, loglik2; | 183 int niter = 50; |
183 int foundnan = 0; | 184 int iter = 0; |
184 | 185 double loglik1, loglik2; |
185 while (iter < niter && !foundnan && !(iter > 1 && (loglik - loglik1) < thresh * (loglik1 - loglik2))) | 186 int foundnan = 0; |
186 { | 187 |
187 ++iter; | 188 while (iter < niter && !foundnan && |
188 /* | 189 !(iter > 1 && (loglik - loglik1) < thresh * (loglik1 - loglik2))) { |
189 fprintf(stderr, "calculating obsprobs...\n"); | 190 |
190 fflush(stderr); | 191 ++iter; |
191 */ | 192 |
192 /* precalculate obs probs */ | 193 /* precalculate obs probs */ |
193 invert(cov, L, icov, &detcov); | 194 invert(cov, L, icov, &detcov); |
194 | 195 |
195 for (t = 0; t < T; t++) | 196 for (t = 0; t < T; t++) { |
196 { | 197 for (i = 0; i < N; i++) { |
197 //int allzero = 1; | 198 b[t][i] = exp(loggauss(x[t], L, mu[i], icov, detcov, gauss_y, gauss_z)); |
198 for (i = 0; i < N; i++) | 199 } |
199 { | 200 } |
200 b[t][i] = exp(loggauss(x[t], L, mu[i], icov, detcov, gauss_y, gauss_z)); | 201 forward_backwards(xi, gamma, &loglik, &loglik1, &loglik2, |
201 | 202 iter, N, T, p0, a, b); |
202 //if (b[t][i] != 0) | 203 if (ISNAN(loglik)) { |
203 // allzero = 0; | 204 foundnan = 1; |
204 } | 205 continue; |
205 /* | 206 } |
206 if (allzero) | 207 |
207 { | 208 baum_welch(p0, a, mu, cov, N, T, L, x, xi, gamma); |
208 printf("all the b[t][i] were zero for t = %d, correcting...\n", t); | 209 } |
209 for (i = 0; i < N; i++) | 210 |
210 { | 211 /* deallocate memory */ |
211 b[t][i] = 0.00001; | 212 for (t = 0; t < T; t++) { |
212 } | 213 free(gamma[t]); |
213 } | 214 free(b[t]); |
214 */ | 215 for (i = 0; i < N; i++) { |
215 } | 216 free(xi[t][i]); |
216 /* | 217 } |
217 fprintf(stderr, "forwards-backwards...\n"); | 218 free(xi[t]); |
218 fflush(stderr); | 219 } |
219 */ | 220 free(gamma); |
220 forward_backwards(xi, gamma, &loglik, &loglik1, &loglik2, iter, N, T, p0, a, b); | 221 free(xi); |
221 /* | 222 free(b); |
222 fprintf(stderr, "iteration %d: loglik = %f\n", iter, loglik); | 223 |
223 fprintf(stderr, "re-estimation...\n"); | 224 for (i = 0; i < L; i++) { |
224 fflush(stderr); | 225 free(icov[i]); |
225 */ | 226 } |
226 if (ISNAN(loglik)) { | 227 free(icov); |
227 foundnan = 1; | 228 |
228 continue; | 229 free(gauss_y); |
229 } | 230 free(gauss_z); |
230 | 231 } |
231 baum_welch(p0, a, mu, cov, N, T, L, x, xi, gamma); | 232 |
232 | 233 void baum_welch(double* p0, double** a, double** mu, double** cov, |
233 /* | 234 int N, int T, int L, double** x, double*** xi, double** gamma) |
234 printf("a:\n"); | 235 { |
235 for (i = 0; i < model->N; i++) | 236 int i, j, t; |
236 { | 237 |
237 for (j = 0; j < model->N; j++) | 238 double* sum_gamma = (double*) malloc(N*sizeof(double)); |
238 printf("%f ", model->a[i][j]); | 239 |
239 printf("\n"); | 240 /* temporary memory */ |
240 } | 241 double* u = (double*) malloc(L*L*sizeof(double)); |
241 printf("\n\n"); | 242 double* yy = (double*) malloc(T*L*sizeof(double)); |
242 */ | 243 double* yy2 = (double*) malloc(T*L*sizeof(double)); |
243 //hmm_print(model); | 244 |
244 } | 245 /* re-estimate transition probs */ |
245 | 246 for (i = 0; i < N; i++) { |
246 /* deallocate memory */ | 247 sum_gamma[i] = 0; |
247 for (t = 0; t < T; t++) | 248 for (t = 0; t < T-1; t++) { |
248 { | 249 sum_gamma[i] += gamma[t][i]; |
249 free(gamma[t]); | 250 } |
250 free(b[t]); | 251 } |
251 for (i = 0; i < N; i++) | 252 |
252 free(xi[t][i]); | 253 for (i = 0; i < N; i++) { |
253 free(xi[t]); | 254 for (j = 0; j < N; j++) { |
254 } | 255 a[i][j] = 0; |
255 free(gamma); | 256 if (sum_gamma[i] == 0.) { |
256 free(xi); | 257 continue; |
257 free(b); | 258 } |
258 | 259 for (t = 0; t < T-1; t++) { |
259 for (i = 0; i < L; i++) | 260 a[i][j] += xi[t][i][j]; |
260 free(icov[i]); | 261 } |
261 free(icov); | 262 a[i][j] /= sum_gamma[i]; |
262 | 263 } |
263 free(gauss_y); | 264 } |
264 free(gauss_z); | 265 |
265 } | 266 /* NB: now we need to sum gamma over all t */ |
266 | 267 for (i = 0; i < N; i++) { |
267 void baum_welch(double* p0, double** a, double** mu, double** cov, int N, int T, int L, double** x, double*** xi, double** gamma) | 268 sum_gamma[i] += gamma[T-1][i]; |
268 { | 269 } |
269 int i, j, t; | 270 |
270 | 271 /* re-estimate initial probs */ |
271 double* sum_gamma = (double*) malloc(N*sizeof(double)); | 272 for (i = 0; i < N; i++) { |
272 | 273 p0[i] = gamma[0][i]; |
273 /* temporary memory */ | 274 } |
274 double* u = (double*) malloc(L*L*sizeof(double)); | 275 |
275 double* yy = (double*) malloc(T*L*sizeof(double)); | 276 /* re-estimate covariance */ |
276 double* yy2 = (double*) malloc(T*L*sizeof(double)); | 277 int d, e; |
277 | 278 double sum_sum_gamma = 0; |
278 /* re-estimate transition probs */ | 279 for (i = 0; i < N; i++) { |
279 for (i = 0; i < N; i++) | 280 sum_sum_gamma += sum_gamma[i]; |
280 { | 281 } |
281 sum_gamma[i] = 0; | 282 |
282 for (t = 0; t < T-1; t++) | 283 /* using BLAS */ |
283 sum_gamma[i] += gamma[t][i]; | 284 for (d = 0; d < L; d++) { |
284 } | 285 for (e = 0; e < L; e++) { |
285 | 286 cov[d][e] = 0; |
286 for (i = 0; i < N; i++) | 287 } |
287 { | 288 } |
288 if (sum_gamma[i] == 0) | 289 |
289 { | 290 for (j = 0; j < N; j++) { |
290 /* fprintf(stderr, "sum_gamma[%d] was zero...\n", i); */ | 291 |
291 } | 292 for (d = 0; d < L; d++) { |
292 //double s = 0; | 293 for (t = 0; t < T; t++) { |
293 for (j = 0; j < N; j++) | 294 yy[d*T+t] = x[t][d] - mu[j][d]; |
294 { | 295 yy2[d*T+t] = gamma[t][j] * (x[t][d] - mu[j][d]); |
295 a[i][j] = 0; | 296 } |
296 if (sum_gamma[i] == 0.) continue; | 297 } |
297 for (t = 0; t < T-1; t++) | 298 |
298 a[i][j] += xi[t][i][j]; | 299 cblas_dgemm(CblasColMajor, CblasTrans, CblasNoTrans, |
299 //s += a[i][j]; | 300 L, L, T, 1.0, yy, T, yy2, T, 0, u, L); |
300 a[i][j] /= sum_gamma[i]; | 301 |
301 } | 302 for (e = 0; e < L; e++) { |
302 /* | 303 for (d = 0; d < L; d++) { |
303 for (j = 0; j < N; j++) | 304 cov[d][e] += u[e*L+d]; |
304 { | 305 } |
305 a[i][j] /= s; | 306 } |
306 } | 307 } |
307 */ | 308 |
308 } | 309 for (d = 0; d < L; d++) { |
309 | 310 for (e = 0; e < L; e++) { |
310 /* NB: now we need to sum gamma over all t */ | 311 cov[d][e] /= T; /* sum_sum_gamma; */ |
311 for (i = 0; i < N; i++) | 312 } |
312 sum_gamma[i] += gamma[T-1][i]; | 313 } |
313 | 314 |
314 /* re-estimate initial probs */ | 315 //printf("sum_sum_gamma = %f\n", sum_sum_gamma); /* fine, = T IS THIS ALWAYS TRUE with pooled cov?? */ |
315 for (i = 0; i < N; i++) | 316 |
316 p0[i] = gamma[0][i]; | 317 /* re-estimate means */ |
317 | 318 for (j = 0; j < N; j++) { |
318 /* re-estimate covariance */ | 319 for (d = 0; d < L; d++) { |
319 int d, e; | 320 mu[j][d] = 0; |
320 double sum_sum_gamma = 0; | 321 for (t = 0; t < T; t++) |
321 for (i = 0; i < N; i++) | 322 mu[j][d] += gamma[t][j] * x[t][d]; |
322 sum_sum_gamma += sum_gamma[i]; | 323 mu[j][d] /= sum_gamma[j]; |
323 | 324 } |
324 /* | 325 } |
325 for (d = 0; d < L; d++) | 326 |
326 { | 327 /* deallocate memory */ |
327 for (e = d; e < L; e++) | 328 free(sum_gamma); |
328 { | 329 free(yy); |
329 cov[d][e] = 0; | 330 free(yy2); |
330 for (t = 0; t < T; t++) | 331 free(u); |
331 for (j = 0; j < N; j++) | 332 } |
332 cov[d][e] += gamma[t][j] * (x[t][d] - mu[j][d]) * (x[t][e] - mu[j][e]); | 333 |
333 | 334 void forward_backwards(double*** xi, double** gamma, |
334 cov[d][e] /= sum_sum_gamma; | 335 double* loglik, double* loglik1, double* loglik2, |
335 | 336 int iter, int N, int T, |
336 if (ISNAN(cov[d][e])) | 337 double* p0, double** a, double** b) |
337 { | 338 { |
338 printf("cov[%d][%d] was nan\n", d, e); | 339 /* forwards-backwards with scaling */ |
339 for (j = 0; j < N; j++) | 340 int i, j, t; |
340 for (i = 0; i < L; i++) | 341 |
341 if (ISNAN(mu[j][i])) | 342 double** alpha = (double**) malloc(T*sizeof(double*)); |
342 printf("mu[%d][%d] was nan\n", j, i); | 343 double** beta = (double**) malloc(T*sizeof(double*)); |
343 for (t = 0; t < T; t++) | 344 for (t = 0; t < T; t++) { |
344 for (j = 0; j < N; j++) | 345 alpha[t] = (double*) malloc(N*sizeof(double)); |
345 if (ISNAN(gamma[t][j])) | 346 beta[t] = (double*) malloc(N*sizeof(double)); |
346 printf("gamma[%d][%d] was nan\n", t, j); | 347 } |
347 exit(-1); | 348 |
348 } | 349 /* scaling coefficients */ |
349 } | 350 double* c = (double*) malloc(T*sizeof(double)); |
350 } | 351 |
351 for (d = 0; d < L; d++) | 352 /* calculate forward probs and scale coefficients */ |
352 for (e = 0; e < d; e++) | 353 c[0] = 0; |
353 cov[d][e] = cov[e][d]; | 354 for (i = 0; i < N; i++) { |
354 */ | 355 alpha[0][i] = p0[i] * b[0][i]; |
355 | 356 c[0] += alpha[0][i]; |
356 /* using BLAS */ | 357 } |
357 for (d = 0; d < L; d++) | 358 c[0] = 1 / c[0]; |
358 for (e = 0; e < L; e++) | 359 for (i = 0; i < N; i++) { |
359 cov[d][e] = 0; | 360 alpha[0][i] *= c[0]; |
360 | 361 } |
361 for (j = 0; j < N; j++) | 362 |
362 { | 363 *loglik1 = *loglik; |
363 for (d = 0; d < L; d++) | 364 *loglik = -log(c[0]); |
364 for (t = 0; t < T; t++) | 365 if (iter == 2) { |
365 { | 366 *loglik2 = *loglik; |
366 yy[d*T+t] = x[t][d] - mu[j][d]; | 367 } |
367 yy2[d*T+t] = gamma[t][j] * (x[t][d] - mu[j][d]); | 368 |
368 } | 369 for (t = 1; t < T; t++) { |
369 | 370 |
370 cblas_dgemm(CblasColMajor, CblasTrans, CblasNoTrans, L, L, T, 1.0, yy, T, yy2, T, 0, u, L); | 371 c[t] = 0; |
371 | 372 |
372 for (e = 0; e < L; e++) | 373 for (j = 0; j < N; j++) { |
373 for (d = 0; d < L; d++) | 374 alpha[t][j] = 0; |
374 cov[d][e] += u[e*L+d]; | 375 for (i = 0; i < N; i++) { |
375 } | 376 alpha[t][j] += alpha[t-1][i] * a[i][j]; |
376 | 377 } |
377 for (d = 0; d < L; d++) | 378 alpha[t][j] *= b[t][j]; |
378 for (e = 0; e < L; e++) | 379 |
379 cov[d][e] /= T; /* sum_sum_gamma; */ | 380 c[t] += alpha[t][j]; |
380 | 381 } |
381 //printf("sum_sum_gamma = %f\n", sum_sum_gamma); /* fine, = T IS THIS ALWAYS TRUE with pooled cov?? */ | 382 |
382 | 383 c[t] = 1 / c[t]; |
383 /* re-estimate means */ | 384 for (j = 0; j < N; j++) { |
384 for (j = 0; j < N; j++) | 385 alpha[t][j] *= c[t]; |
385 { | 386 } |
386 for (d = 0; d < L; d++) | 387 |
387 { | 388 *loglik -= log(c[t]); |
388 mu[j][d] = 0; | 389 } |
389 for (t = 0; t < T; t++) | 390 |
390 mu[j][d] += gamma[t][j] * x[t][d]; | 391 /* calculate backwards probs using same coefficients */ |
391 mu[j][d] /= sum_gamma[j]; | 392 for (i = 0; i < N; i++) { |
392 } | 393 beta[T-1][i] = 1; |
393 } | 394 } |
394 | 395 t = T - 1; |
395 /* deallocate memory */ | 396 |
396 free(sum_gamma); | 397 while (1) { |
397 free(yy); | 398 for (i = 0; i < N; i++) { |
398 free(yy2); | 399 beta[t][i] *= c[t]; |
399 free(u); | 400 } |
400 } | 401 |
401 | 402 if (t == 0) { |
402 void forward_backwards(double*** xi, double** gamma, double* loglik, double* loglik1, double* loglik2, int iter, int N, int T, double* p0, double** a, double** b) | 403 break; |
403 { | 404 } |
404 /* forwards-backwards with scaling */ | 405 |
405 int i, j, t; | 406 for (i = 0; i < N; i++) { |
406 | 407 beta[t-1][i] = 0; |
407 double** alpha = (double**) malloc(T*sizeof(double*)); | 408 for (j = 0; j < N; j++) { |
408 double** beta = (double**) malloc(T*sizeof(double*)); | 409 beta[t-1][i] += a[i][j] * b[t][j] * beta[t][j]; |
409 for (t = 0; t < T; t++) | 410 } |
410 { | 411 } |
411 alpha[t] = (double*) malloc(N*sizeof(double)); | 412 |
412 beta[t] = (double*) malloc(N*sizeof(double)); | 413 t--; |
413 } | 414 } |
414 | 415 |
415 /* scaling coefficients */ | 416 /* calculate posterior probs */ |
416 double* c = (double*) malloc(T*sizeof(double)); | 417 double tot; |
417 | 418 for (t = 0; t < T; t++) { |
418 /* calculate forward probs and scale coefficients */ | 419 tot = 0; |
419 c[0] = 0; | 420 for (i = 0; i < N; i++) { |
420 for (i = 0; i < N; i++) | 421 gamma[t][i] = alpha[t][i] * beta[t][i]; |
421 { | 422 tot += gamma[t][i]; |
422 alpha[0][i] = p0[i] * b[0][i]; | 423 } |
423 c[0] += alpha[0][i]; | 424 for (i = 0; i < N; i++) { |
424 | 425 gamma[t][i] /= tot; |
425 //printf("p0[%d] = %f, b[0][%d] = %f\n", i, p0[i], i, b[0][i]); | 426 } |
426 } | 427 } |
427 c[0] = 1 / c[0]; | 428 |
428 for (i = 0; i < N; i++) | 429 for (t = 0; t < T-1; t++) { |
429 { | 430 tot = 0; |
430 alpha[0][i] *= c[0]; | 431 for (i = 0; i < N; i++) { |
431 | 432 for (j = 0; j < N; j++) { |
432 //printf("alpha[0][%d] = %f\n", i, alpha[0][i]); /* OK agrees with Matlab */ | 433 xi[t][i][j] = alpha[t][i] * a[i][j] * b[t+1][j] * beta[t+1][j]; |
433 } | 434 tot += xi[t][i][j]; |
434 | 435 } |
435 *loglik1 = *loglik; | 436 } |
436 *loglik = -log(c[0]); | 437 for (i = 0; i < N; i++) { |
437 if (iter == 2) | 438 for (j = 0; j < N; j++) { |
438 *loglik2 = *loglik; | 439 xi[t][i][j] /= tot; |
439 | 440 } |
440 for (t = 1; t < T; t++) | 441 } |
441 { | 442 } |
442 c[t] = 0; | 443 |
443 for (j = 0; j < N; j++) | 444 for (t = 0; t < T; t++) { |
444 { | 445 free(alpha[t]); |
445 alpha[t][j] = 0; | 446 free(beta[t]); |
446 for (i = 0; i < N; i++) | 447 } |
447 alpha[t][j] += alpha[t-1][i] * a[i][j]; | 448 free(alpha); |
448 alpha[t][j] *= b[t][j]; | 449 free(beta); |
449 | 450 free(c); |
450 c[t] += alpha[t][j]; | |
451 } | |
452 | |
453 /* | |
454 if (c[t] == 0) | |
455 { | |
456 printf("c[%d] = 0, going to blow up so exiting\n", t); | |
457 for (i = 0; i < N; i++) | |
458 if (b[t][i] == 0) | |
459 fprintf(stderr, "b[%d][%d] was zero\n", t, i); | |
460 fprintf(stderr, "x[t] was \n"); | |
461 for (i = 0; i < L; i++) | |
462 fprintf(stderr, "%f ", x[t][i]); | |
463 fprintf(stderr, "\n\n"); | |
464 exit(-1); | |
465 } | |
466 */ | |
467 | |
468 c[t] = 1 / c[t]; | |
469 for (j = 0; j < N; j++) | |
470 alpha[t][j] *= c[t]; | |
471 | |
472 //printf("c[%d] = %e\n", t, c[t]); | |
473 | |
474 *loglik -= log(c[t]); | |
475 } | |
476 | |
477 /* calculate backwards probs using same coefficients */ | |
478 for (i = 0; i < N; i++) | |
479 beta[T-1][i] = 1; | |
480 t = T - 1; | |
481 while (1) | |
482 { | |
483 for (i = 0; i < N; i++) | |
484 beta[t][i] *= c[t]; | |
485 | |
486 if (t == 0) | |
487 break; | |
488 | |
489 for (i = 0; i < N; i++) | |
490 { | |
491 beta[t-1][i] = 0; | |
492 for (j = 0; j < N; j++) | |
493 beta[t-1][i] += a[i][j] * b[t][j] * beta[t][j]; | |
494 } | |
495 | |
496 t--; | |
497 } | |
498 | |
499 /* | |
500 printf("alpha:\n"); | |
501 for (t = 0; t < T; t++) | |
502 { | |
503 for (i = 0; i < N; i++) | |
504 printf("%4.4e\t\t", alpha[t][i]); | |
505 printf("\n"); | |
506 } | |
507 printf("\n\n");printf("beta:\n"); | |
508 for (t = 0; t < T; t++) | |
509 { | |
510 for (i = 0; i < N; i++) | |
511 printf("%4.4e\t\t", beta[t][i]); | |
512 printf("\n"); | |
513 } | |
514 printf("\n\n"); | |
515 */ | |
516 | |
517 /* calculate posterior probs */ | |
518 double tot; | |
519 for (t = 0; t < T; t++) | |
520 { | |
521 tot = 0; | |
522 for (i = 0; i < N; i++) | |
523 { | |
524 gamma[t][i] = alpha[t][i] * beta[t][i]; | |
525 tot += gamma[t][i]; | |
526 } | |
527 for (i = 0; i < N; i++) | |
528 { | |
529 gamma[t][i] /= tot; | |
530 | |
531 //printf("gamma[%d][%d] = %f\n", t, i, gamma[t][i]); | |
532 } | |
533 } | |
534 | |
535 for (t = 0; t < T-1; t++) | |
536 { | |
537 tot = 0; | |
538 for (i = 0; i < N; i++) | |
539 { | |
540 for (j = 0; j < N; j++) | |
541 { | |
542 xi[t][i][j] = alpha[t][i] * a[i][j] * b[t+1][j] * beta[t+1][j]; | |
543 tot += xi[t][i][j]; | |
544 } | |
545 } | |
546 for (i = 0; i < N; i++) | |
547 for (j = 0; j < N; j++) | |
548 xi[t][i][j] /= tot; | |
549 } | |
550 | |
551 /* | |
552 // CHECK - fine | |
553 // gamma[t][i] = \sum_j{xi[t][i][j]} | |
554 tot = 0; | |
555 for (j = 0; j < N; j++) | |
556 tot += xi[3][1][j]; | |
557 printf("gamma[3][1] = %f, sum_j(xi[3][1][j]) = %f\n", gamma[3][1], tot); | |
558 */ | |
559 | |
560 for (t = 0; t < T; t++) | |
561 { | |
562 free(alpha[t]); | |
563 free(beta[t]); | |
564 } | |
565 free(alpha); | |
566 free(beta); | |
567 free(c); | |
568 } | 451 } |
569 | 452 |
570 void viterbi_decode(double** x, int T, model_t* model, int* q) | 453 void viterbi_decode(double** x, int T, model_t* model, int* q) |
571 { | 454 { |
572 int i, j, t; | 455 int i, j, t; |
573 double max; | 456 double max; |
574 int havemax; | 457 int havemax; |
575 | 458 |
576 int N = model->N; | 459 int N = model->N; |
577 int L = model->L; | 460 int L = model->L; |
578 double* p0 = model->p0; | 461 double* p0 = model->p0; |
579 double** a = model->a; | 462 double** a = model->a; |
580 double** mu = model->mu; | 463 double** mu = model->mu; |
581 double** cov = model->cov; | 464 double** cov = model->cov; |
582 | 465 |
583 /* inverse covariance and its determinant */ | 466 /* inverse covariance and its determinant */ |
584 double** icov = (double**) malloc(L*sizeof(double*)); | 467 double** icov = (double**) malloc(L*sizeof(double*)); |
585 for (i = 0; i < L; i++) | 468 for (i = 0; i < L; i++) { |
586 icov[i] = (double*) malloc(L*sizeof(double)); | 469 icov[i] = (double*) malloc(L*sizeof(double)); |
587 double detcov; | 470 } |
588 | 471 double detcov; |
589 double** logb = (double**) malloc(T*sizeof(double*)); | 472 |
590 double** phi = (double**) malloc(T*sizeof(double*)); | 473 double** logb = (double**) malloc(T*sizeof(double*)); |
591 int** psi = (int**) malloc(T*sizeof(int*)); | 474 double** phi = (double**) malloc(T*sizeof(double*)); |
592 for (t = 0; t < T; t++) | 475 int** psi = (int**) malloc(T*sizeof(int*)); |
593 { | 476 |
594 logb[t] = (double*) malloc(N*sizeof(double)); | 477 for (t = 0; t < T; t++) { |
595 phi[t] = (double*) malloc(N*sizeof(double)); | 478 logb[t] = (double*) malloc(N*sizeof(double)); |
596 psi[t] = (int*) malloc(N*sizeof(int)); | 479 phi[t] = (double*) malloc(N*sizeof(double)); |
597 } | 480 psi[t] = (int*) malloc(N*sizeof(int)); |
598 | 481 } |
599 /* temporary memory */ | 482 |
600 double* gauss_y = (double*) malloc(L*sizeof(double)); | 483 /* temporary memory */ |
601 double* gauss_z = (double*) malloc(L*sizeof(double)); | 484 double* gauss_y = (double*) malloc(L*sizeof(double)); |
602 | 485 double* gauss_z = (double*) malloc(L*sizeof(double)); |
603 /* calculate observation logprobs */ | 486 |
604 invert(cov, L, icov, &detcov); | 487 /* calculate observation logprobs */ |
605 for (t = 0; t < T; t++) | 488 invert(cov, L, icov, &detcov); |
606 for (i = 0; i < N; i++) | 489 for (t = 0; t < T; t++) { |
607 logb[t][i] = loggauss(x[t], L, mu[i], icov, detcov, gauss_y, gauss_z); | 490 for (i = 0; i < N; i++) { |
608 | 491 logb[t][i] = loggauss |
609 /* initialise */ | 492 (x[t], L, mu[i], icov, detcov, gauss_y, gauss_z); |
610 for (i = 0; i < N; i++) | 493 } |
611 { | 494 } |
612 phi[0][i] = log(p0[i]) + logb[0][i]; | 495 |
613 psi[0][i] = 0; | 496 /* initialise */ |
614 } | 497 for (i = 0; i < N; i++) { |
615 | 498 phi[0][i] = log(p0[i]) + logb[0][i]; |
616 for (t = 1; t < T; t++) | 499 psi[0][i] = 0; |
617 { | 500 } |
618 for (j = 0; j < N; j++) | 501 |
619 { | 502 for (t = 1; t < T; t++) { |
620 max = -1000000; | 503 for (j = 0; j < N; j++) { |
621 havemax = 0; | 504 max = -1000000; |
622 | 505 havemax = 0; |
623 psi[t][j] = 0; | 506 |
624 for (i = 0; i < N; i++) | 507 psi[t][j] = 0; |
625 { | 508 for (i = 0; i < N; i++) { |
626 if (phi[t-1][i] + log(a[i][j]) > max || !havemax) | 509 if (phi[t-1][i] + log(a[i][j]) > max || !havemax) { |
627 { | 510 max = phi[t-1][i] + log(a[i][j]); |
628 max = phi[t-1][i] + log(a[i][j]); | 511 phi[t][j] = max + logb[t][j]; |
629 phi[t][j] = max + logb[t][j]; | 512 psi[t][j] = i; |
630 psi[t][j] = i; | 513 havemax = 1; |
631 havemax = 1; | 514 } |
632 } | 515 } |
633 } | 516 } |
634 } | 517 } |
635 } | 518 |
636 | 519 /* find maximising state at time T-1 */ |
637 /* find maximising state at time T-1 */ | 520 max = phi[T-1][0]; |
638 max = phi[T-1][0]; | 521 q[T-1] = 0; |
639 q[T-1] = 0; | 522 for (i = 1; i < N; i++) { |
640 for (i = 1; i < N; i++) | 523 if (phi[T-1][i] > max) { |
641 { | 524 max = phi[T-1][i]; |
642 if (phi[T-1][i] > max) | 525 q[T-1] = i; |
643 { | 526 } |
644 max = phi[T-1][i]; | 527 } |
645 q[T-1] = i; | 528 |
646 } | 529 /* track back */ |
647 } | 530 t = T - 2; |
648 | 531 while (t >= 0) { |
649 | 532 q[t] = psi[t+1][q[t+1]]; |
650 /* track back */ | 533 t--; |
651 t = T - 2; | 534 } |
652 while (t >= 0) | 535 |
653 { | 536 /* de-allocate memory */ |
654 q[t] = psi[t+1][q[t+1]]; | 537 for (i = 0; i < L; i++) { |
655 t--; | 538 free(icov[i]); |
656 } | 539 } |
657 | 540 free(icov); |
658 /* de-allocate memory */ | 541 for (t = 0; t < T; t++) { |
659 for (i = 0; i < L; i++) | 542 free(logb[t]); |
660 free(icov[i]); | 543 free(phi[t]); |
661 free(icov); | 544 free(psi[t]); |
662 for (t = 0; t < T; t++) | 545 } |
663 { | 546 free(logb); |
664 free(logb[t]); | 547 free(phi); |
665 free(phi[t]); | 548 free(psi); |
666 free(psi[t]); | 549 |
667 } | 550 free(gauss_y); |
668 free(logb); | 551 free(gauss_z); |
669 free(phi); | |
670 free(psi); | |
671 | |
672 free(gauss_y); | |
673 free(gauss_z); | |
674 } | 552 } |
675 | 553 |
676 /* invert matrix and calculate determinant using LAPACK */ | 554 /* invert matrix and calculate determinant using LAPACK */ |
677 void invert(double** cov, int L, double** icov, double* detcov) | 555 void invert(double** cov, int L, double** icov, double* detcov) |
678 { | 556 { |
679 /* copy square matrix into a vector in column-major order */ | 557 /* copy square matrix into a vector in column-major order */ |
680 double* a = (double*) malloc(L*L*sizeof(double)); | 558 double* a = (double*) malloc(L*L*sizeof(double)); |
681 int i, j; | 559 int i, j; |
682 for(j=0; j < L; j++) | 560 for (j=0; j < L; j++) { |
683 for (i=0; i < L; i++) | 561 for (i=0; i < L; i++) { |
684 a[j*L+i] = cov[i][j]; | 562 a[j*L+i] = cov[i][j]; |
685 | 563 } |
686 int M = (int) L; | 564 } |
687 int* ipiv = (int *) malloc(L*L*sizeof(int)); | 565 |
688 int ret; | 566 int M = (int) L; |
689 | 567 int* ipiv = (int *) malloc(L*L*sizeof(int)); |
690 /* LU decomposition */ | 568 int ret; |
691 ret = dgetrf_(&M, &M, a, &M, ipiv, &ret); /* ret should be zero, negative if cov is singular */ | 569 |
692 if (ret < 0) | 570 /* LU decomposition */ |
693 { | 571 ret = dgetrf_(&M, &M, a, &M, ipiv, &ret); /* ret should be zero, negative if cov is singular */ |
694 fprintf(stderr, "Covariance matrix was singular, couldn't invert\n"); | 572 if (ret < 0) { |
695 exit(-1); | 573 fprintf(stderr, "Covariance matrix was singular, couldn't invert\n"); |
696 } | 574 exit(-1); |
697 | 575 } |
698 /* find determinant */ | 576 |
699 double det = 1; | 577 /* find determinant */ |
700 for(i = 0; i < L; i++) | 578 double det = 1; |
701 det *= a[i*L+i]; | 579 for (i = 0; i < L; i++) { |
702 // TODO: get this to work!!! If detcov < 0 then cov is bad anyway... | 580 det *= a[i*L+i]; |
703 /* | 581 } |
704 int sign = 1; | 582 |
705 for (i = 0; i < L; i++) | 583 // TODO: get this to work!!! If detcov < 0 then cov is bad anyway... |
706 if (ipiv[i] != i) | 584 if (det < 0) { |
707 sign = -sign; | 585 det = -det; |
708 det *= sign; | 586 } |
709 */ | 587 *detcov = det; |
710 if (det < 0) | 588 |
711 det = -det; | 589 /* allocate required working storage */ |
712 *detcov = det; | |
713 | |
714 /* allocate required working storage */ | |
715 #ifndef HAVE_ATLAS | 590 #ifndef HAVE_ATLAS |
716 int lwork = -1; | 591 int lwork = -1; |
717 double lwbest = 0.0; | 592 double lwbest = 0.0; |
718 dgetri_(&M, a, &M, ipiv, &lwbest, &lwork, &ret); | 593 dgetri_(&M, a, &M, ipiv, &lwbest, &lwork, &ret); |
719 lwork = (int) lwbest; | 594 lwork = (int) lwbest; |
720 double* work = (double*) malloc(lwork*sizeof(double)); | 595 double* work = (double*) malloc(lwork*sizeof(double)); |
721 #endif | 596 #endif |
722 | 597 |
723 /* find inverse */ | 598 /* find inverse */ |
724 dgetri_(&M, a, &M, ipiv, work, &lwork, &ret); | 599 dgetri_(&M, a, &M, ipiv, work, &lwork, &ret); |
725 | 600 |
726 for(j=0; j < L; j++) | 601 for (j=0; j < L; j++) { |
727 for (i=0; i < L; i++) | 602 for (i=0; i < L; i++) { |
728 icov[i][j] = a[j*L+i]; | 603 icov[i][j] = a[j*L+i]; |
604 } | |
605 } | |
729 | 606 |
730 #ifndef HAVE_ATLAS | 607 #ifndef HAVE_ATLAS |
731 free(work); | 608 free(work); |
732 #endif | 609 #endif |
733 free(a); | 610 free(a); |
734 } | 611 } |
735 | 612 |
736 /* probability of multivariate Gaussian given mean, inverse and determinant of covariance */ | 613 /* probability of multivariate Gaussian given mean, inverse and determinant of covariance */ |
737 double gauss(double* x, int L, double* mu, double** icov, double detcov, double* y, double* z) | 614 double gauss(double* x, int L, double* mu, double** icov, double detcov, double* y, double* z) |
738 { | 615 { |
739 int i; | 616 int i; |
740 double s = 0; | 617 double s = 0; |
741 for (i = 0; i < L; i++) | 618 |
742 y[i] = x[i] - mu[i]; | 619 for (i = 0; i < L; i++) { |
743 for (i = 0; i < L; i++) | 620 y[i] = x[i] - mu[i]; |
744 { | 621 } |
745 //z[i] = 0; | 622 |
746 //for (j = 0; j < L; j++) | 623 for (i = 0; i < L; i++) { |
747 // z[i] += icov[i][j] * y[j]; | 624 z[i] = cblas_ddot(L, &icov[i][0], 1, y, 1); |
748 z[i] = cblas_ddot(L, &icov[i][0], 1, y, 1); | 625 } |
749 } | 626 |
750 s = cblas_ddot(L, z, 1, y, 1); | 627 s = cblas_ddot(L, z, 1, y, 1); |
751 //for (i = 0; i < L; i++) | 628 |
752 // s += z[i] * y[i]; | 629 return exp(-s/2.0) / (pow(2*PI, L/2.0) * sqrt(detcov)); |
753 | |
754 return exp(-s/2.0) / (pow(2*PI, L/2.0) * sqrt(detcov)); | |
755 } | 630 } |
756 | 631 |
757 /* log probability of multivariate Gaussian given mean, inverse and determinant of covariance */ | 632 /* log probability of multivariate Gaussian given mean, inverse and determinant of covariance */ |
758 double loggauss(double* x, int L, double* mu, double** icov, double detcov, double* y, double* z) | 633 double loggauss(double* x, int L, double* mu, double** icov, double detcov, double* y, double* z) |
759 { | 634 { |
760 int i; | 635 int i; |
761 double s = 0; | 636 double s = 0; |
762 double ret; | 637 double ret; |
763 for (i = 0; i < L; i++) | 638 |
764 y[i] = x[i] - mu[i]; | 639 for (i = 0; i < L; i++) { |
765 for (i = 0; i < L; i++) | 640 y[i] = x[i] - mu[i]; |
766 { | 641 } |
767 //z[i] = 0; | 642 |
768 //for (j = 0; j < L; j++) | 643 for (i = 0; i < L; i++) { |
769 // z[i] += icov[i][j] * y[j]; | 644 z[i] = cblas_ddot(L, &icov[i][0], 1, y, 1); |
770 z[i] = cblas_ddot(L, &icov[i][0], 1, y, 1); | 645 } |
771 } | 646 |
772 s = cblas_ddot(L, z, 1, y, 1); | 647 s = cblas_ddot(L, z, 1, y, 1); |
773 //for (i = 0; i < L; i++) | 648 |
774 // s += z[i] * y[i]; | 649 ret = -0.5 * (s + L * log(2*PI) + log(detcov)); |
775 | 650 |
776 ret = -0.5 * (s + L * log(2*PI) + log(detcov)); | 651 return ret; |
777 | |
778 /* | |
779 // TEST | |
780 if (ISINF(ret) > 0) | |
781 printf("loggauss returning infinity\n"); | |
782 if (ISINF(ret) < 0) | |
783 printf("loggauss returning -infinity\n"); | |
784 if (ISNAN(ret)) | |
785 printf("loggauss returning nan\n"); | |
786 */ | |
787 | |
788 return ret; | |
789 } | 652 } |
790 | 653 |
791 void hmm_print(model_t* model) | 654 void hmm_print(model_t* model) |
792 { | 655 { |
793 int i, j; | 656 int i, j; |
794 printf("p0:\n"); | 657 printf("p0:\n"); |
795 for (i = 0; i < model->N; i++) | 658 for (i = 0; i < model->N; i++) { |
796 printf("%f ", model->p0[i]); | 659 printf("%f ", model->p0[i]); |
797 printf("\n\n"); | 660 } |
798 printf("a:\n"); | 661 printf("\n\n"); |
799 for (i = 0; i < model->N; i++) | 662 printf("a:\n"); |
800 { | 663 for (i = 0; i < model->N; i++) { |
801 for (j = 0; j < model->N; j++) | 664 for (j = 0; j < model->N; j++) { |
802 printf("%f ", model->a[i][j]); | 665 printf("%f ", model->a[i][j]); |
803 printf("\n"); | 666 } |
804 } | 667 printf("\n"); |
805 printf("\n\n"); | 668 } |
806 printf("mu:\n"); | 669 printf("\n\n"); |
807 for (i = 0; i < model->N; i++) | 670 printf("mu:\n"); |
808 { | 671 for (i = 0; i < model->N; i++) { |
809 for (j = 0; j < model->L; j++) | 672 for (j = 0; j < model->L; j++) { |
810 printf("%f ", model->mu[i][j]); | 673 printf("%f ", model->mu[i][j]); |
811 printf("\n"); | 674 } |
812 } | 675 printf("\n"); |
813 printf("\n\n"); | 676 } |
814 printf("cov:\n"); | 677 printf("\n\n"); |
815 for (i = 0; i < model->L; i++) | 678 printf("cov:\n"); |
816 { | 679 for (i = 0; i < model->L; i++) { |
817 for (j = 0; j < model->L; j++) | 680 for (j = 0; j < model->L; j++) { |
818 printf("%f ", model->cov[i][j]); | 681 printf("%f ", model->cov[i][j]); |
819 printf("\n"); | 682 } |
820 } | 683 printf("\n"); |
821 printf("\n\n"); | 684 } |
822 } | 685 printf("\n\n"); |
823 | 686 } |
824 | 687 |
688 |