Skip to content

Commit

Permalink
v0.0.2 push
Browse files Browse the repository at this point in the history
examples, more comments, cleaned up code
  • Loading branch information
Jacob Schreiber committed Jan 4, 2015
1 parent 70e589f commit 815f123
Show file tree
Hide file tree
Showing 14 changed files with 1,305 additions and 161 deletions.
80 changes: 80 additions & 0 deletions examples/asia_bayes_net.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Asia Bayes Net
# Contact: Jacob Schreiber
# [email protected]

'''
The Asia Bayesian Network. See a description here:
http://www.norsys.com/tutorials/netica/secA/tut_A1.htm
'''

from pomegranate import *

# Create the distributions
asia = DiscreteDistribution({ 'True' : 0.5, 'False' : 0.5 })
tuberculosis = ConditionalDiscreteDistribution({
'True' : DiscreteDistribution({ 'True' : 0.2, 'False' : 0.80 }),
'False' : DiscreteDistribution({ 'True' : 0.01, 'False' : 0.99 })
}, [asia])

smoking = DiscreteDistribution({ 'True' : 0.5, 'False' : 0.5 })
lung = ConditionalDiscreteDistribution({
'True' : DiscreteDistribution({ 'True' : 0.75, 'False' : 0.25 }),
'False' : DiscreteDistribution({ 'True' : 0.02, 'False' : 0.98 })
}, [smoking] )
bronchitis = ConditionalDiscreteDistribution({
'True' : DiscreteDistribution({ 'True' : 0.92, 'False' : 0.08 }),
'False' : DiscreteDistribution({ 'True' : 0.03, 'False' : 0.97})
}, [smoking] )

tuberculosis_or_cancer = ConditionalDiscreteDistribution({
'True' : { 'True' : DiscreteDistribution({ 'True' : 1.0, 'False' : 0.0 }),
'False' : DiscreteDistribution({ 'True' : 1.0, 'False' : 0.0 }),
},
'False' : { 'True' : DiscreteDistribution({ 'True' : 1.0, 'False' : 0.0 }),
'False' : DiscreteDistribution({ 'True' : 0.0, 'False' : 1.0 })
}
}, [tuberculosis, lung] )

xray = ConditionalDiscreteDistribution({
'True' : DiscreteDistribution({ 'True' : .885, 'False' : .115 }),
'False' : DiscreteDistribution({ 'True' : 0.04, 'False' : 0.96 })
}, [tuberculosis_or_cancer] )

dyspnea = ConditionalDiscreteDistribution({
'True' : { 'True' : DiscreteDistribution({ 'True' : 0.96, 'False' : 0.04 }),
'False' : DiscreteDistribution({ 'True' : 0.89, 'False' : 0.11 })
},
'False' : { 'True' : DiscreteDistribution({ 'True' : 0.82, 'False' : 0.18 }),
'False' : DiscreteDistribution({ 'True' : 0.4, 'False' : 0.6 })
}
}, [tuberculosis_or_cancer, bronchitis])

# Make the states. Note the name can be different than the name of the state
# can be different than the name of the distribution
s0 = State( asia, name="asia" )
s1 = State( tuberculosis, name="tuberculosis" )
s2 = State( smoking, name="smoker" )
s3 = State( lung, name="cancer" )
s4 = State( bronchitis, name="bronchitis" )
s5 = State( tuberculosis_or_cancer, name="TvC" )
s6 = State( xray, name="xray" )
s7 = State( dyspnea, name='dyspnea' )

# Create the Bayesian network
network = BayesianNetwork( "asia" )
network.add_states([ s0, s1, s2, s3, s4, s5, s6, s7 ])
network.add_transition( s0, s1 )
network.add_transition( s1, s5 )
network.add_transition( s2, s3 )
network.add_transition( s2, s4 )
network.add_transition( s3, s5 )
network.add_transition( s5, s6 )
network.add_transition( s5, s7 )
network.add_transition( s4, s7 )
network.bake()

print "Has tuberculosis, is not a smoker, 80-20 chance he has bronchitis"
observations = { 'tuberculosis' : 'True', 'smoker' : 'False',
'bronchitis' : DiscreteDistribution({ 'True' : 0.8, 'False' : 0.2 }) }
beliefs = map( str, network.forward_backward( observations ) )
print "\n".join( "{}\t\t{}".format( state.name, belief ) for state, belief in zip( network.states, beliefs ) )
43 changes: 43 additions & 0 deletions examples/fsm_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# FSM test
# Contact: Jacob Schreiber
# [email protected]

from pomegranate import *

# Create the states in the same way as you would an HMM
a = State( NormalDistribution( 5, 1 ), "a" )
b = State( NormalDistribution( 23, 1 ), "b" )
c = State( NormalDistribution( 100, 1 ), "c" )

# Create a FiniteStateMachine object
model = FiniteStateMachine( "test" )

# Add the states in the same way
model.add_states( [a, b, c] )

# Add the transitions in the same manner
model.add_transition( model.start, a, 1.0 )
model.add_transition( a, a, 0.33 )
model.add_transition( a, b, 0.33 )
model.add_transition( b, b, 0.5 )
model.add_transition( b, a, 0.5 )
model.add_transition( a, c, 0.33 )
model.add_transition( c, a, 0.5 )
model.add_transition( c, c, 0.5 )

# Bake the model in the same way
model.bake( verbose=True )

# Take a sequence of observations
seq = [ 5, 5, 5, 5, 23, 23, 5, 23, 23, 100, 23, 23, 23, 23, 5, 5, 100, 5, 23 ]

# Print out the model
print "\n".join( state.name for state in model.states )

# Print out where you start in the model
print model.current_state.name

# Print out where the model is for each step
for symbol in seq:
model.step( symbol )
print symbol, model.current_state.name
54 changes: 54 additions & 0 deletions examples/hmm_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python2.7
# example.py: Yet Another Hidden Markov Model library
# Contact: Jacob Schreiber ( [email protected] )

"""
A simple example highlighting how to build a model using states, add
transitions, and then run the algorithms, including showing how training
on a sequence improves the probability of the sequence.
"""

import random
from pomegranate import *
from pomegranate import HiddenMarkovModel as Model

random.seed(0)
model = Model(name="ExampleModel")
distribution = UniformDistribution(0.0, 1.0)
state = State(distribution, name="uniform")
state2 = State(NormalDistribution(0, 2), name="normal")
silent = State(None, name="silent")
model.add_state(state)
model.add_state(state2)

model.add_transition(state, state, 0.4)
model.add_transition(state, state2, 0.4)
model.add_transition(state2, state2, 0.4)
model.add_transition(state2, state, 0.4)

model.add_transition(model.start, state, 0.5)
model.add_transition(model.start, state2, 0.5)
model.add_transition(state, model.end, 0.2)
model.add_transition(state2, model.end, 0.2)

model.bake()
sequence = model.sample()
print sequence
print
print model.forward(sequence)[ len(sequence), model.end_index ]
print model.backward(sequence)[0,model.start_index]
print
trans, ems = model.forward_backward(sequence)
print trans
print ems
print
model.train( [ sequence ] )

print
print model.forward(sequence)[ len(sequence), model.end_index ]
print model.backward(sequence)[0,model.start_index]
print
trans, ems = model.forward_backward(sequence)
print trans
print ems
print
85 changes: 85 additions & 0 deletions examples/infinite_hmm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# infinite_hmm_sampling.py
# Contact: Jacob Schreiber
# [email protected]

'''
This example shows how to use yahmm to sample from an infinite HMM. The premise
is that you have an HMM which does not have transitions to the end state, and
so can continue on forever. This is done by not adding transitions to the end
state. If you bake a model with no transitions to the end state, you get an
infinite model, with no extra work! This change is passed on to all the
algorithms.
'''

from pomegranate import *
from pomegranate import HiddenMarkovModel as Model
import itertools as it
import numpy as np

# Define the states
s1 = State( NormalDistribution( 5, 2 ), name="S1" )
s2 = State( NormalDistribution( 15, 2 ), name="S2" )
s3 = State( NormalDistribution( 25, 2 ), name="S3 ")

# Define the transitions
model = Model( "infinite" )
model.add_transition( model.start, s1, 0.7 )
model.add_transition( model.start, s2, 0.2 )
model.add_transition( model.start, s3, 0.1 )
model.add_transition( s1, s1, 0.6 )
model.add_transition( s1, s2, 0.1 )
model.add_transition( s1, s3, 0.3 )
model.add_transition( s2, s1, 0.4 )
model.add_transition( s2, s2, 0.4 )
model.add_transition( s2, s3, 0.2 )
model.add_transition( s3, s1, 0.05 )
model.add_transition( s3, s2, 0.15 )
model.add_transition( s3, s3, 0.8 )
model.bake()

sequence = [ 4.8, 5.6, 24.1, 25.8, 14.3, 26.5, 15.9, 5.5, 5.1 ]


print model.is_infinite()

print "Algorithms On Infinite Model"
sequence = [ 4.8, 5.6, 24.1, 25.8, 14.3, 26.5, 15.9, 5.5, 5.1 ]
print "Forward"
print model.forward( sequence )

print "\n".join( state.name for state in model.states )
print "Backward"
print model.backward( sequence )

print "Forward-Backward"
trans, emissions = model.forward_backward( sequence )
print trans
print emissions

print "Viterbi"
prob, states = model.viterbi( sequence )
print "Prob: {}".format( prob )
print "\n".join( state[1].name for state in states )
print
print "MAP"
prob, states = model.maximum_a_posteriori( sequence )
print "Prob: {}".format( prob )
print "\n".join( state[1].name for state in states )

print "Showing that sampling can reproduce the original transition probs."
print "Should produce a matrix close to the following: "
print " [ [ 0.60, 0.10, 0.30 ] "
print " [ 0.40, 0.40, 0.20 ] "
print " [ 0.05, 0.15, 0.80 ] ] "
print
print "Tranition Matrix From 100000 Samples:"
sample, path = model.sample( 100000, path=True )
trans = np.zeros((3,3))

for state, n_state in it.izip( path[1:-2], path[2:-1] ):
state_name = float( state.name[1:] )-1
n_state_name = float( n_state.name[1:] )-1
trans[ state_name, n_state_name ] += 1

trans = (trans.T / trans.sum( axis=1 )).T
print trans
Loading

0 comments on commit 815f123

Please sign in to comment.