comparison experiment-reverb/code/supervised_training_hmms_higher_orderpy @ 0:246d5546657c

initial commit, needs cleanup
author Emmanouil Theofanis Chourdakis <e.t.chourdakis@qmul.ac.uk>
date Wed, 14 Dec 2016 13:15:48 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:246d5546657c
1 #!/usr/bin/python2
2 # -*- coding: utf-8 -*-
3 """
4 Created on Thu Apr 23 11:53:17 2015
5
6 @author: mmxgn
7 """
8
9 # This file does the cluster estimation and the removal of outliers
10
11 from sys import argv, exit
12 from essentia.standard import YamlInput, YamlOutput
13 from essentia import Pool
14 from pca import *
15
16 from numpy import *
17 from sklearn import cluster
18 from sklearn.metrics import pairwise_distances
19 from sklearn.cluster import KMeans, MiniBatchKMeans
20 from matplotlib.pyplot import *
21 #from sklearn.mixture import GMM
22 from sklearn.naive_bayes import GaussianNB, MultinomialNB
23 from scipy.signal import decimate
24 from sklearn import cross_validation
25
26 #from hmmlearn import hmm
27 from hmmlearn.hmm import GMM
28 from hmmlearn import hmm
29 #from adpcm import adm, adm_reconstruct
30
31
32 mse = lambda A,B: ((array(A)-array(B)) ** 2).mean()
33
34
35 def smooth_matrix_1D(X):
36 window = scipy.signal.gaussian(51,4)
37 window = window/sum(window)
38 intermx = zeros((X.shape[0],X.shape[1]+100))
39 intermx[:, 50:-50] = X
40
41 for m in range(0, X.shape[0]):
42 # print intermx.shape
43 intermx[m,:] = convolve(ravel(intermx[m,:]), window,'same')
44
45 return intermx[:,50:-50]
46
47 def adm_reconstruct(codeword, h, dmin=.01, dmax=.28):
48 x = zeros((1, codeword.shape[1]))
49
50 delta1 = dmin
51 delta2 = dmin
52 Sum = h
53
54 x[0] = h
55 for i in range(0, codeword.shape[1]):
56 if codeword[0,i] == 0:
57 delta1 = dmin
58 delta2 = dmin
59
60 elif codeword[0,i] == 1:
61 delta2 = dmin
62 Sum += delta1
63 delta1 *= 2
64 if delta1 > dmax:
65 delta1 = dmax
66
67 elif codeword[0,i] == -1:
68 delta1 = dmin
69 Sum -= delta2
70 delta2 *= 2
71 if delta2 > dmax:
72 delta2 = dmax
73 x[0,i] = Sum
74 return x
75
76 def adm(x, dmin=.01, dmax=.28, tol=0.0001):
77
78 # Adaptive delta modulation adapted by code:
79 # (adeltamod.m)
80 #
81 # Adaptive Delta Modulator
82 # by Gandhar Desai (gdesai)
83 # BITS Pilani Goa Campus
84 # Date: 28 Sept, 2013
85
86 xsig = x
87
88 Lx = len(x)
89
90 ADMout = zeros((1, Lx))
91 codevec = zeros((1, Lx))
92
93
94 Sum = x[0]
95 delta1 = dmin
96 delta2 = dmin
97 mult1 = 2
98 mult2 = 2
99 for i in range(0, Lx):
100 #print abs(xsig[i] - Sum)
101 if (abs(xsig[i] - Sum) < tol):
102 bit = 0
103 delta2 = dmin
104 delta1 = dmin
105
106
107 elif (xsig[i] >= Sum):
108 bit = 1
109 delta2 = dmin
110 Sum += delta1
111 delta1 *= mult1
112 if delta1 > dmax:
113 delta1 = dmax
114
115
116 else:
117 bit = -1
118 delta1 = dmin
119 Sum -= delta2
120 delta2 *= mult2
121 if delta2 > dmax:
122 delta2 = dmax
123
124
125
126 ADMout[0, i] = Sum
127 codevec[0, i]= bit
128
129 return ADMout,codevec, x[0]
130
131 if __name__=="__main__":
132 if len(argv) != 2:
133 print "[EE] Wrong number of arguments"
134 print "[II] Correct syntax is:"
135 print "[II] \t%s <training_file>"
136 print "[II] where <training_file> is a .yaml file containing the"
137 print "[II] features of the dataset (try output2_stage/fulltraining-last.yaml)"
138 exit(-1)
139
140
141 n_clusters = 25
142 UpsamplingFactor = 10
143 dmin = 0.001
144 dmax = 0.28
145 tol = 0.001
146
147 infile = argv[1]
148
149 features_pool = YamlInput(filename = infile)()
150
151
152
153 feature_captions = features_pool.descriptorNames()
154 parameter_captions = []
155
156
157 for c in features_pool.descriptorNames():
158 if c.split('.')[0] == 'parameter':
159 parameter_captions.append(c)
160 if c.split('.')[0] == 'metadata' or c.split('.')[0] == 'parameter':
161 feature_captions.remove(c)
162
163
164
165 # close('all')
166
167 print "[II] Loaded training data from %s (%s) " % (infile, features_pool['metadata.date'][0])
168 print "[II] %d Features Available: " % len(feature_captions)
169
170
171
172 print str(feature_captions).replace("', ","\n").replace('[','').replace("'","[II]\t ")[:-7]
173
174 nfeatures_in = len(feature_captions)
175 nparameters_in = len(parameter_captions)
176 features_vector = zeros((nfeatures_in, len(features_pool[feature_captions[0]])))
177
178 parameters_vector = zeros((nparameters_in, len(features_pool[parameter_captions[0]])))
179
180
181 for i in range(0, nfeatures_in):
182 features_vector[i, :] = features_pool[feature_captions[i]].T
183 for i in range(0, nparameters_in):
184 parameters_vector[i, :] = features_pool[parameter_captions[0]].T
185
186 print "[II] %d parameters used:" % len(parameter_captions)
187 print str(parameter_captions).replace("', ","\n").replace('[','').replace("'","[II]\t ")[:-7].replace('parameter.','')
188
189 print "[II] Marking silent parts"
190
191 silent_parts = zeros((1, len(features_pool[feature_captions[i]].T)))
192
193 rms = features_vector[feature_captions.index('rms'), :]
194
195 # Implementing Hysteresis Gate -- High threshold is halfway between
196 # the mean and the max and Low is halfway between the mean dn the min
197
198 rms_threshold_mean = mean(rms)
199
200 rms_threshold_max = max(rms)
201 rms_threshold_min = min(rms)
202
203 rms_threshold_high = 0.1 * rms_threshold_mean
204 rms_threshold_low = 0.01 * rms_threshold_mean
205
206 for n in range(1, len(rms)):
207 prev = rms[n-1]
208 curr = rms[n]
209
210 if prev >= rms_threshold_high:
211 if curr < rms_threshold_low:
212 silent_parts[0,n] = 1
213 else:
214 silent_parts[0,n] = 0
215 elif prev <= rms_threshold_low:
216 if curr > rms_threshold_high:
217 silent_parts[0,n] = 0
218 else:
219 silent_parts[0,n] = 1
220 else:
221 silent_parts[0,n] = silent_parts[0,n-1]
222
223
224 if silent_parts[0,1] == 1:
225 silent_parts[0, 0] = 1
226
227
228
229 active_index = invert(silent_parts.flatten().astype(bool))
230
231 # Keep only active parts
232
233 # Uncomment this
234 features_vector = features_vector[:, active_index]
235
236 moments_vector = zeros((features_vector.shape[0], 2))
237
238 print "[II] Storing moments vector"
239 for i in range(0, features_vector.shape[0]):
240 mean_ = mean(features_vector[i,:])
241 std_ = std(features_vector[i,:], ddof=1)
242 moments_vector[i,0] = mean_
243 moments_vector[i,1] = std_
244
245 features_vector[i,:] = (features_vector[i,:] - mean_)/std_
246
247 features_vector_original = features_vector
248
249
250 print "[II] Extracting PCA configuration "
251
252 kernel, q, featurelist = extract_pca_configuration_from_data(features_vector)
253
254 print "[II] Optimal number of PCs to keep: %d" % q
255
256 feature_captions_array = array(feature_captions)
257
258 features_to_keep = list(feature_captions_array[featurelist])
259 print "[II] Decided to keep %d features:" % len(features_to_keep)
260 print str(features_to_keep).replace("', ","\n").replace('[','').replace("'","[II]\t ")[:-7]
261
262
263 features_kept_data = features_vector[featurelist,:]
264
265 features_vector = (kernel.T*features_kept_data)[0:q,:]
266
267 parameters_k_means = KMeans(init='k-means++', n_init=10, max_iter=300, tol=0.0000001, verbose = 0)
268
269 print "[II] Trying ADM-coded parameters"
270 print "[II] Upsampling features and parameters by a factor of %d" % UpsamplingFactor
271
272
273 # Upsampled features and parameters
274 features_vector_upsampled = smooth_matrix_1D(repeat(features_vector,UpsamplingFactor, axis=1))
275
276 # feature_labels_upsampled = repeat(features_clustering_labels,UpsamplingFactor, axis=0)
277 parameters_vector_upsampled = repeat(parameters_vector,UpsamplingFactor, axis=1)
278
279 # parameters_vector_upsampled = smooth_matrix_1D(parameters_vector_upsampled)
280
281 parameters_vector_upsampled_adm = matrix(zeros(shape(parameters_vector_upsampled)))
282 parameters_vector_upsampled_code = matrix(zeros(shape(parameters_vector_upsampled)))
283 parameters_vector_upsampled_firstval = matrix(zeros((parameters_vector_upsampled.shape[0],1)))
284
285 # Reconstructed parameters
286
287 parameters_vector_upsampled_reconstructed = matrix(zeros(shape(parameters_vector_upsampled)))
288
289
290
291
292 def adm_matrix(X, dmin=0.001,dmax=0.28,tol=0.001):
293
294 out = matrix(zeros(shape(X)))
295 code = matrix(zeros(shape(X)))
296 firstval = matrix(zeros((X.shape[0], 1)))
297
298 for i in range(0, X.shape[0]):
299 out[i,:], code[i,:], firstval[i,0] = adm(X[i,:],dmin=dmin,dmax=dmax,tol=tol)
300
301 return out,code,firstval
302
303 # parameters_vector_upsampled_reconstructed[i,:] = adm_reconstruct(parameters_vector_upsampled_code[i,:],parameters_vector_upsampled_firstval[i,0], dmin=dmin,dmax=dmax)
304
305 def adm_matrix_reconstruct(code, firstval, dmin=0.001, dmax=0.28):
306 X = matrix(zeros(shape(code)))
307 for i in range(0, code.shape[0]):
308 X[i,:] = adm_reconstruct(code[i,:], firstval[i,0], dmin=dmin, dmax=dmax)
309
310 return X
311
312
313 parameters_vector_upsampled_adm, parameters_vector_upsampled_code, parameters_vector_upsampled_firstval = adm_matrix(parameters_vector_upsampled, dmin, dmax, tol)
314
315
316 def diff_and_pad(X):
317 return concatenate((
318 zeros((
319 shape(X)[0],
320 1
321 )),
322 diff(X, axis=1)),
323 axis=1)
324
325
326 print "[II] Clustering features."
327 #
328 features_clustering = GMM(n_components = n_clusters, covariance_type='diag')
329 #
330 features_clustering.fit( features_vector_upsampled.T, y=parameters_vector_upsampled_code)
331 #
332 features_clustering_means = features_clustering.means_
333 features_clustering_labels = features_clustering.predict(features_vector_upsampled.T)
334 features_clustering_sigmas = features_clustering.covars_
335 #
336 features_vector_upsampled_estimated = zeros(shape(features_vector_upsampled))
337 #
338 #
339 for n in range(0, len(features_vector_upsampled_estimated[0])):
340 features_vector_upsampled_estimated[:,n] = features_clustering_means[features_clustering_labels[n]]
341 #
342 #
343 print "[II] Features MSE for %d clusters: %.3f" % (n_clusters, mse(features_vector_upsampled, features_vector_upsampled_estimated))
344
345
346
347
348 def cross_validate_classification(data, classes, estimator):
349 print "[II] Crossvalidating... "
350 from copy import deepcopy
351 estimator_fulldata = deepcopy(estimator)
352 estimator_fulldata.fit(data, classes)
353
354 percents = arange(0.1,0.9,0.1)
355 MSEs = []
356 labels = estimator.predict(data)
357
358 print "[II] for full training-testing: %.2f" % (sum(array(classes==labels).astype(float))/len(labels))
359
360 for p in percents:
361 train,test,trainlabels,testlabels = cross_validation.train_test_split(data,classes,test_size=p,random_state=0)
362 estimator_ = deepcopy(estimator)
363 estimator_.fit(train, trainlabels)
364 labels = estimator.predict(test)
365 print "[II] for training(%.2f)-testing(%.2f): %.2f" % ((1-p),p,sum(array(testlabels==labels).astype(float))/len(labels))
366
367 return MSEs
368
369 def cross_validate_clustering(data, estimator):
370 print "[II] Crossvalidating... "
371 estimator_fulldata = estimator
372 estimator_fulldata.fit(data)
373
374 # labels = estimator_fulldata.predict(data)
375 means = estimator_fulldata.means_
376 # print means
377
378 percents = arange(0.1,0.6,0.1)
379 MSEs = []
380 reconstructed = zeros(shape(data))
381 labels = estimator.predict(data)
382 for n in range(0, len(reconstructed)):
383 reconstructed[n,:] = means[labels[n]]
384
385 MSEs.append(mse(data,reconstructed))
386 for p in percents:
387 train,test = cross_validation.train_test_split(data,test_size=p,random_state=0)
388 train = matrix(train)
389 test = matrix(test)
390
391 estimator.fit(train)
392 means = estimator.means_
393 labels = estimator.predict(test)
394 reconstructed = zeros(shape(test))
395 for n in range(0, len(reconstructed)):
396 reconstructed[n,:] = means[labels[n]]
397
398 m = mse(test,reconstructed)
399
400 print "[II] MSE for clustering crossvalidated data %.2f-%.2f: %.5f" % ((1-p), p, m)
401 MSEs.append(m)
402
403 print "[II] Crossvalidation complete"
404
405 return MSEs
406
407
408
409
410 # Construct parameters alphabet, each symbol is going to be a different column vector
411 # in parameter code matrix
412
413
414 def vector_to_states(X):
415 """
416 Input: a vector MxN with N samples and M variables
417 Output: a codeword dictionary `parameters_alphabet',
418 state_seq, inverse `parameters_alphabet_inv' """
419
420
421 parameters_alphabet = {}
422 n = 0
423
424 for i in range(0, X.shape[1]):
425 vec = tuple(ravel(X[:,i]))
426 if vec not in parameters_alphabet:
427 parameters_alphabet[vec] = n
428 n += 1
429
430 parameters_alphabet_inv = dict([(parameters_alphabet[m],m) for m in parameters_alphabet])
431
432 state_seq = array([parameters_alphabet[tuple(ravel(X[:,m]))] for m in range(0, parameters_vector_upsampled_code.shape[1])] )
433
434 return state_seq, parameters_alphabet, parameters_alphabet_inv
435
436
437 def states_to_vector(predicted, parameters_alphabet_inv):
438 estimated = matrix(zeros((len(parameters_alphabet_inv[0]), len(predicted))))
439 for i in range(0, len(state_seq)):
440 estimated[:, i] = matrix(parameters_alphabet_inv[predicted[i]]).T
441
442 return estimated
443
444 state_seq, parameters_alphabet, parameters_alphabet_inv = vector_to_states(parameters_vector_upsampled_code)
445
446
447 parameters_change_variable = matrix(diff_and_pad(parameters_vector_upsampled)!=0).astype(int)
448
449 changes_state_seq, changes_parameters_alphabet, changes_parameters_alphabet_inv = vector_to_states(parameters_change_variable)
450
451
452 # This is an hmm that just codes the changes"
453 # We have only two states, change and stay the same.
454
455
456 parameters_state, parameter_state_alphabet, parameter_state_alphabet_inv = vector_to_states(parameters_vector_upsampled)
457
458
459 print "[II] Testing Gaussian Naive Bayes Classifier"
460 gnb = GaussianNB()
461 gnb.fit(features_vector_upsampled.T, parameters_state)
462
463 parameters_state_estimated = gnb.predict(features_vector_upsampled.T)
464
465 output = states_to_vector(parameters_state_estimated, parameter_state_alphabet_inv)
466
467 figure()
468 subplot(211)
469 plot(parameters_vector_upsampled.T)
470 title('Parameter value upsampled by a factor of %d' % UpsamplingFactor)
471 ylabel('value')
472 xlabel('frame #')
473 subplot(212)
474 #plot(smooth_matrix_1D(output).T)
475 plot(output.T)
476 ylabel('value')
477 xlabel('frame #')
478 cross_validate_classification(features_vector_upsampled.T, parameters_state, gnb)
479
480 print "[II] Trying Multinomial HMM"
481
482 # In order to do classification with HMMs, we need to:
483 # 1. Split the parameters into classes
484 # 2. Train one model per class
485 # 3. Feed our data to all the models
486 # 4. Check which has a better score and assig,n to M
487
488
489 class HmmClassifier:
490 def __init__(self, N=2, n_components = 1):
491 self.n_components = n_components
492 self.chain_size = N
493 self.hmms_ = []
494 self.N = N
495
496 def fit(self, X, states):
497 self.n_states = len(unique(states))
498
499 for n in range(0, self.n_states):
500 hmm_ = hmm.GaussianHMM(n_components = self.n_components, covariance_type = 'full')
501
502 # Get training data for each class
503 vector = X[states == n,:]
504
505 # Fit the HMM
506 # print vector
507 hmm_.fit([vector])
508
509 # And append to the list
510 self.hmms_.append(hmm_)
511
512 def predict(self,X):
513 labels = zeros((X.shape[0],))
514 N = self.N
515
516 m = 0
517
518 scores = zeros((1, self.n_states))
519
520
521 while m*N < X.shape[0]:
522 if (m+1)*N > X.shape[0]:
523 testdata = X[m*N:,:]
524 else:
525 testdata = X[m*N:(m+1)*N,:]
526
527 # print testdata
528
529 for i in range(0, self.n_states):
530 scores[0,i] = self.hmms_[i].score(testdata)
531
532 if (m+1)*N > X.shape[0]:
533 labels[m*N:] = argmax(scores)
534 else:
535 labels[m*N:(m+1)*N] = argmax(scores)
536
537 m+= 1
538
539 return labels
540
541 N = 150
542 n_components = 1
543
544 hmmc = HmmClassifier(N = N, n_components = n_components)
545 hmmc.fit(features_vector_upsampled.T, parameters_state)
546
547 cross_validate_classification(features_vector_upsampled.T, parameters_state, hmmc)
548
549
550
551
552 # hmms_ = []
553 #
554 # for n in range(0, len(parameter_state_alphabet)):
555 # #hmm_ = hmm.GMMHMM(n_components = 1, n_mix = 2)
556 # hmm_ = hmm.GaussianHMM(n_components = 1,covariance_type = 'full')
557 #
558 # # Get training data for each class
559 # vector = features_vector_upsampled[:,parameters_state == n]
560 #
561 # #if vector.shape[1] < n_clusters:
562 # # hmms_.append(None)
563 # #else:
564 #
565 # hmm_.fit([vector.T])
566 #
567 # # Append to the list
568 #
569 # hmms_.append(hmm_)
570 #
571 # labels = zeros((features_vector_upsampled.shape[1],))
572 #
573 # N = 20
574 # m = 0
575 #
576 # while m*N < features_vector_upsampled.shape[1]:
577 #
578 # scores = zeros((1, len(parameter_state_alphabet)))
579 #
580 # if (m+1)*N > features_vector_upsampled.shape[1]:
581 # testdata = features_vector_upsampled[:,m*N:]
582 # else:
583 # testdata = features_vector_upsampled[:,m*N:(m+1)*N]
584 #
585 # for i in range(0, len(parameter_state_alphabet)):
586 # if hmms_[i] is not None:
587 # scores[0,i] = hmms_[i].score(testdata.T)
588 # else:
589 # scores[0,i] = -100000 # Very large negative score
590 # if (m+1)*N >= features_vector_upsampled.shape[1]:
591 # labels[m*N:] = argmax(scores)
592 # else:
593 # labels[m*N:(m+1)*N] = argmax(scores)
594 #
595 # m += 1
596
597
598 # figure()
599 #plot(labels.T)
600
601
602 labels = hmmc.predict(features_vector_upsampled.T)
603 estimated = states_to_vector(labels,parameter_state_alphabet_inv)
604 plot(estimated.T,'r--')
605
606 title('Estimated parameter values')
607 legend(['Naive Bayes Classifier', 'HMM chain size %d (%.1fms)' % (N, float(N)/UpsamplingFactor*23.0)])
608
609 ylabel('value')
610 xlabel('frame #')