-
Notifications
You must be signed in to change notification settings - Fork 590
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples, more comments, cleaned up code
- Loading branch information
Jacob Schreiber
committed
Jan 4, 2015
1 parent
70e589f
commit 815f123
Showing
14 changed files
with
1,305 additions
and
161 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ) ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 model.forward(sequence)[ len(sequence), model.end_index ] | ||
print model.backward(sequence)[0,model.start_index] | ||
trans, ems = model.forward_backward(sequence) | ||
print trans | ||
print ems | ||
model.train( [ sequence ] ) | ||
|
||
print model.forward(sequence)[ len(sequence), model.end_index ] | ||
print model.backward(sequence)[0,model.start_index] | ||
trans, ems = model.forward_backward(sequence) | ||
print trans | ||
print ems | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 "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 "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 |
Oops, something went wrong.