| | 341 | def fix_emission_state(self, Py_ssize_t i, bint fixed=True): |
|---|
| | 342 | """ |
|---|
| | 343 | Sets the i-th emission state to be either fixed or not fixed. |
|---|
| | 344 | If it is fixed, then running the Baum-Welch algorithm will not |
|---|
| | 345 | change it. |
|---|
| | 346 | |
|---|
| | 347 | INPUT: |
|---|
| | 348 | i -- nonnegative integer < self.m.N |
|---|
| | 349 | fixed -- bool |
|---|
| | 350 | |
|---|
| | 351 | EXAMPLES: |
|---|
| | 352 | We run Baum-Welch once without fixing the emission states: |
|---|
| | 353 | sage: m = hmm.GaussianHiddenMarkovModel([[0.4,0.6],[0.1,0.9]], [(0.0,1.0),(1,1)], [1,0]) |
|---|
| | 354 | sage: m.baum_welch([0,1]) |
|---|
| | 355 | sage: m |
|---|
| | 356 | Gaussian Hidden Markov Model with 2 States |
|---|
| | 357 | Transition matrix: |
|---|
| | 358 | [0.0 1.0] |
|---|
| | 359 | [0.1 0.9] |
|---|
| | 360 | Emission parameters: |
|---|
| | 361 | [(0.0, 0.01), (1.0, 0.01)] |
|---|
| | 362 | Initial probabilities: [1.0, 0.0] |
|---|
| | 363 | |
|---|
| | 364 | Now we run Baum-Welch with the emission states fixed. Notice that they don't change. |
|---|
| | 365 | sage: m = hmm.GaussianHiddenMarkovModel([[0.4,0.6],[0.1,0.9]], [(0.0,1.0),(1,1)], [1,0]) |
|---|
| | 366 | sage: m.fix_emission_state(0); m.fix_emission_state(1) |
|---|
| | 367 | sage: m.baum_welch([0,1]) |
|---|
| | 368 | sage: m |
|---|
| | 369 | Gaussian Hidden Markov Model with 2 States |
|---|
| | 370 | Transition matrix: |
|---|
| | 371 | [0.000368587006957 0.999631412993] |
|---|
| | 372 | [ 0.1 0.9] |
|---|
| | 373 | Emission parameters: |
|---|
| | 374 | [(0.0, 1.0), (1.0, 1.0)] |
|---|
| | 375 | Initial probabilities: [1.0, 0.0] |
|---|
| | 376 | """ |
|---|
| | 377 | if i < 0 or i >= self.m.N: |
|---|
| | 378 | raise IndexError, "index out of range" |
|---|
| | 379 | self.m.s[i].e.fixed = fixed |
|---|
| | 380 | |
|---|
| | 381 | def fix_hidden_state(self, Py_ssize_t i, bint fixed=True): |
|---|
| | 382 | """ |
|---|
| | 383 | Sets the i-th hidden state to be either fixed or not fixed. |
|---|
| | 384 | If it is fixed, then running the Baum-Welch algorithm will not |
|---|
| | 385 | change it. |
|---|
| | 386 | |
|---|
| | 387 | INPUT: |
|---|
| | 388 | i -- nonnegative integer < self.m.N |
|---|
| | 389 | fixed -- bool |
|---|
| | 390 | |
|---|
| | 391 | EXAMPLES: |
|---|
| | 392 | """ |
|---|
| | 393 | if i < 0 or i >= self.m.N: |
|---|
| | 394 | raise IndexError, "index out of range" |
|---|
| | 395 | self.m.s[i].fix = fixed |
|---|
| | 396 | |
|---|
| | 777 | |
|---|
| | 778 | |
|---|
| | 779 | cdef class GaussianMixtureHiddenMarkovModel(GaussianHiddenMarkovModel): |
|---|
| | 780 | """ |
|---|
| | 781 | GaussianMixtureHiddenMarkovModel(A, B, pi, name) |
|---|
| | 782 | |
|---|
| | 783 | INPUT: |
|---|
| | 784 | A -- matrix; the transition matrix (n x n) |
|---|
| | 785 | B -- list of lists of pairs (w, (mu, sigma)) that define the |
|---|
| | 786 | Gaussian mixture associated to each state, where w is |
|---|
| | 787 | the weight, mu is the mean and sigma the standard |
|---|
| | 788 | deviation. |
|---|
| | 789 | pi -- list of floats that sums to 1.0; these are |
|---|
| | 790 | the initial probabilities of each hidden state |
|---|
| | 791 | name -- (default: None); a string |
|---|
| | 792 | """ |
|---|
| | 793 | def __init__(self, A, B, pi, name=None): |
|---|
| | 794 | """ |
|---|
| | 795 | EXAMPLES: |
|---|
| | 796 | """ |
|---|
| | 797 | # Turn B into a list of lists |
|---|
| | 798 | B = [flatten(x) for x in B] |
|---|
| | 799 | m = max([len(x) for x in B]) |
|---|
| | 800 | if m == 0: |
|---|
| | 801 | raise ValueError, "number of Gaussian mixtures must be positive" |
|---|
| | 802 | B = [x + [0]*(m-len(x)) for x in B] |
|---|
| | 803 | GaussianHiddenMarkovModel.__init__(self, A, B, pi) |
|---|
| | 804 | print m//3 |
|---|
| | 805 | self.m.M = m//3 |
|---|
| | 806 | # Set number of outputs. |
|---|
| | 807 | |
|---|
| | 808 | def _initialize_state(self, pi): |
|---|
| | 809 | # Allocate and initialize states |
|---|
| | 810 | cdef ghmm_cstate* states = <ghmm_cstate*> safe_malloc(sizeof(ghmm_cstate) * self.m.N) |
|---|
| | 811 | cdef ghmm_cstate* state |
|---|
| | 812 | cdef ghmm_c_emission* e |
|---|
| | 813 | cdef Py_ssize_t i, j, k, M, n |
|---|
| | 814 | |
|---|
| | 815 | for i in range(self.m.N): |
|---|
| | 816 | # Parameters of Gaussian distributions |
|---|
| | 817 | v = self.B[i] |
|---|
| | 818 | M = len(v)//3 # number of distinct Gaussians |
|---|
| | 819 | |
|---|
| | 820 | # Get a reference to the i-th state for convenience of the notation below. |
|---|
| | 821 | state = &(states[i]) |
|---|
| | 822 | state.M = M |
|---|
| | 823 | state.pi = pi[i] |
|---|
| | 824 | state.desc = NULL |
|---|
| | 825 | state.fix = 0 |
|---|
| | 826 | e = <ghmm_c_emission*> safe_malloc(sizeof(ghmm_c_emission)*M) |
|---|
| | 827 | weights = [] |
|---|
| | 828 | |
|---|
| | 829 | for n in range(M): |
|---|
| | 830 | e[n].type = 0 # Gaussian |
|---|
| | 831 | e[n].dimension = 1 |
|---|
| | 832 | mu = v[n*3+1] |
|---|
| | 833 | sigma = v[n*3+2] |
|---|
| | 834 | weights.append( v[n*3] ) |
|---|
| | 835 | e[n].mean.val = mu |
|---|
| | 836 | e[n].variance.val = sigma*sigma # variance! not standard deviation |
|---|
| | 837 | |
|---|
| | 838 | # fixing of emissions is deactivated by default |
|---|
| | 839 | e[n].fixed = 0 |
|---|
| | 840 | e[n].sigmacd = NULL |
|---|
| | 841 | e[n].sigmainv = NULL |
|---|
| | 842 | |
|---|
| | 843 | state.e = e |
|---|
| | 844 | state.c = to_double_array(weights) |
|---|
| | 845 | |
|---|
| | 846 | ######################################################### |
|---|
| | 847 | # Initialize state transition data. |
|---|
| | 848 | # NOTE: This code is similar to a block of code in hmm.pyx. |
|---|
| | 849 | |
|---|
| | 850 | # Set "out" probabilities, i.e., the probabilities to |
|---|
| | 851 | # transition to another hidden state from this state. |
|---|
| | 852 | v = self.A[i] |
|---|
| | 853 | k = self.m.N |
|---|
| | 854 | state.out_states = k |
|---|
| | 855 | state.out_id = <int*> safe_malloc(sizeof(int)*k) |
|---|
| | 856 | state.out_a = ighmm_cmatrix_alloc(1, k) |
|---|
| | 857 | for j in range(k): |
|---|
| | 858 | state.out_id[j] = j |
|---|
| | 859 | state.out_a[0][j] = v[j] |
|---|
| | 860 | |
|---|
| | 861 | # Set "in" probabilities |
|---|
| | 862 | v = self.A.column(i) |
|---|
| | 863 | state.in_states = k |
|---|
| | 864 | state.in_id = <int*> safe_malloc(sizeof(int)*k) |
|---|
| | 865 | state.in_a = ighmm_cmatrix_alloc(1, k) |
|---|
| | 866 | for j in range(k): |
|---|
| | 867 | state.in_id[j] = j |
|---|
| | 868 | state.in_a[0][j] = v[j] |
|---|
| | 869 | |
|---|
| | 870 | ######################################################### |
|---|
| | 871 | # Set states |
|---|
| | 872 | self.m.s = states |
|---|
| | 873 | |
|---|
| | 874 | def emission_parameters(self): |
|---|
| | 875 | """ |
|---|
| | 876 | Return the emission parameters list. |
|---|
| | 877 | |
|---|
| | 878 | OUTPUT: |
|---|
| | 879 | list of lists of tuples (weight, (mu, sigma)) |
|---|
| | 880 | p |
|---|
| | 881 | EXAMPLES: |
|---|
| | 882 | sage: m = hmm.GaussianMixtureHiddenMarkovModel([[0.5,0.5],[0.5,0.5]], [[(0.5,(0.0,1.0)), (0.1,(1,10000))],[(1,(1,1))]], [1,0]) |
|---|
| | 883 | sage: m.emission_parameters() |
|---|
| | 884 | [[(0.5, (0.0, 1.0)), (0.10000000000000001, (1.0, 10000.0))], |
|---|
| | 885 | [(1.0, (1.0, 1.0)), (0.0, (0.0, 0.0))]] |
|---|
| | 886 | """ |
|---|
| | 887 | cdef Py_ssize_t i,j |
|---|
| | 888 | |
|---|
| | 889 | return [[(self.m.s[i].c[j], (self.m.s[i].e[j].mean.val, sqrt(self.m.s[i].e[j].variance.val))) |
|---|
| | 890 | for j in range(self.m.s[i].M)] for i in range(self.m.N)] |
|---|
| | 891 | |
|---|
| | 892 | |