hmm_example.py

#

Example code for Hidden Markov Model (HMM). Specific example and some code taken from Wikipedia. This code is limited to generating hidden states and their corresponding emissions. We'll return to the more interesting and advanced questions of finding the most likely hidden states, parameters, and likely number of hidden states on the basis of a given observable sequence

import random
#

Make a random selection from a dictionary with weighted keys

def weighted_choice(transitions):
    prob = random.random()

    for state, value in transitions.items():
        if prob <= value:
            return state
        else:
            prob -= value
    return None
#

Generate sequence of hidden states

def generate_states(states, start_probability, transition_probability, length):
    start_state = weighted_choice(start_probability)
    chain = [start_state]
    for i in range(1, length):
        next_state = weighted_choice(transition_probability[start_state])
        chain.append(next_state)
        start_state = next_state
    return chain
#

Generate sequence of emissions based on the sequence of hidden states.

def generate_emissions(state_sequence, emission_probability):
    emissions = []
    for state in sequence:
        emission = weighted_choice(emission_probability[state])
        emissions.append(emission)
    return emissions
#

Tuples of (hidden) states and observations

states = ('Rainy', 'Sunny')
observations = ('walk', 'shop', 'clean')
#

Dictionaries of start probabilities. Keys are states and values are their respective probabilities.

start_probability = {'Rainy': 0.6, 'Sunny': 0.4}
#

Dictionaries of transition and emission probabilities with states as keys. Values of these keys are another dictionary with possible next states or emissions as keys and their respective transition probabilities as values.

transition_probability = {
   'Rainy' : {'Rainy': 0.7, 'Sunny': 0.3},
   'Sunny' : {'Rainy': 0.4, 'Sunny': 0.6},
   }
 
emission_probability = {
   'Rainy' : {'walk': 0.1, 'shop': 0.4, 'clean': 0.5},
   'Sunny' : {'walk': 0.6, 'shop': 0.3, 'clean': 0.1},
   }
#

Generate sequence of hidden states.

sequence = generate_states(states, start_probability,
                           transition_probability, 10)
print('Sequence of hidden states:', sequence, '\n')
#

Generate sequence of emissions based on the sequence of hidden states.

emissions = generate_emissions(sequence, emission_probability)
print('Observed emissions:', emissions)