| 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 | |