-
Notifications
You must be signed in to change notification settings - Fork 174
/
test_hmm_likelihood.py
150 lines (124 loc) · 4.95 KB
/
test_hmm_likelihood.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
from __future__ import division
import numpy as np
from numpy import newaxis as na
from inspect import getargspec
from functools import wraps
import itertools
from nose.plugins.attrib import attr
from pyhsmm import models as m, distributions as d
##########
# util #
##########
def likelihood_check(obs_distns,trans_matrix,init_distn,data,target_val):
for cls in [m.HMMPython, m.HMM]:
hmm = cls(alpha=6.,init_state_concentration=1, # placeholders
obs_distns=obs_distns)
hmm.trans_distn.trans_matrix = trans_matrix
hmm.init_state_distn.weights = init_distn
hmm.add_data(data)
# test default log_likelihood method
assert np.isclose(target_val, hmm.log_likelihood())
# manual tests of the several message passing methods
states = hmm.states_list[-1]
states.clear_caches()
states.messages_forwards_normalized()
assert np.isclose(target_val,states._normalizer)
states.clear_caches()
states.messages_forwards_log()
assert np.isinf(target_val) or np.isclose(target_val,states._normalizer)
states.clear_caches()
states.messages_backwards_log()
assert np.isinf(target_val) or np.isclose(target_val,states._normalizer)
# test held-out vs in-model
assert np.isclose(target_val, hmm.log_likelihood(data))
def compute_likelihood_enumeration(obs_distns,trans_matrix,init_distn,data):
N = len(obs_distns)
T = len(data)
Al = np.log(trans_matrix)
aBl = np.hstack([o.log_likelihood(data)[:,na] for o in obs_distns])
tot = -np.inf
for stateseq in itertools.product(range(N),repeat=T):
loglike = 0.
loglike += np.log(init_distn[stateseq[0]])
for a,b in zip(stateseq[:-1],stateseq[1:]):
loglike += Al[a,b]
for t,a in enumerate(stateseq):
loglike += aBl[t,a]
tot = np.logaddexp(tot,loglike)
return tot
def random_model(nstates):
init_distn = np.random.dirichlet(np.ones(nstates))
trans_matrix = np.vstack([np.random.dirichlet(np.ones(nstates)) for i in range(nstates)])
return dict(init_distn=init_distn,trans_matrix=trans_matrix)
def runmultiple(n):
def dec(fn):
@wraps(fn)
def wrapper():
for i in range(n):
yield fn
return wrapper
return dec
###########
# tests #
###########
@attr('hmm','likelihood','messages','basic')
def like_hand_test_1():
likelihood_check(
obs_distns=[d.Categorical(weights=row) for row in np.eye(2)],
trans_matrix=np.eye(2),
init_distn=np.array([1.,0.]),
data=np.zeros(10,dtype=int),
target_val=0.)
@attr('hmm','likelihood','messages','basic','robust')
def like_hand_test_2():
likelihood_check(
obs_distns=[d.Categorical(weights=row) for row in np.eye(2)],
trans_matrix=np.eye(2),
init_distn=np.array([0.,1.]),
data=np.zeros(10,dtype=int),
target_val=np.log(0.))
@attr('hmm','likelihood','messages','basic')
def like_hand_test_3():
likelihood_check(
obs_distns=[d.Categorical(weights=row) for row in np.eye(2)],
trans_matrix=np.array([[0.,1.],[1.,0.]]),
init_distn=np.array([1.,0.]),
data=np.tile([0,1],5).astype(int),
target_val=0.)
@attr('hmm','likelihood','messages','basic')
def like_hand_test_4():
likelihood_check(
obs_distns=[d.Categorical(weights=row) for row in np.eye(2)],
trans_matrix=np.array([[0.,1.],[1.,0.]]),
init_distn=np.array([1.,0.]),
data=np.tile([0,1],5).astype(int),
target_val=0.)
@attr('hmm','likelihood','messages','basic')
def like_hand_test_5():
likelihood_check(
obs_distns=[d.Categorical(weights=row) for row in np.eye(2)],
trans_matrix=np.array([[0.9,0.1],[0.2,0.8]]),
init_distn=np.array([1.,0.]),
data=np.tile((0,1),5),
target_val=5*np.log(0.1) + 4*np.log(0.2))
@attr('hmm','slow','likelihood','messages')
@runmultiple(3)
def discrete_exhaustive_test():
model = random_model(2)
obs_distns = [d.Categorical(K=3,alpha_0=1.),d.Categorical(K=3,alpha_0=1.)]
stateseq = np.random.randint(2,size=10)
data = np.array([obs_distns[a].rvs() for a in stateseq])
target_val = compute_likelihood_enumeration(obs_distns=obs_distns,data=data,**model)
likelihood_check(target_val=target_val,data=data,obs_distns=obs_distns,**model)
@attr('hmm','slow','likelihood','messages')
@runmultiple(3)
def gaussian_exhaustive_test():
model = random_model(3)
obs_distns = [
d.Gaussian(mu=np.random.randn(2),sigma=np.eye(2)),
d.Gaussian(mu=np.random.randn(2),sigma=np.eye(2)),
d.Gaussian(mu=np.random.randn(2),sigma=np.eye(2))]
stateseq = np.random.randint(3,size=10)
data = np.vstack([obs_distns[a].rvs() for a in stateseq])
target_val = compute_likelihood_enumeration(obs_distns=obs_distns,data=data,**model)
likelihood_check(target_val=target_val,data=data,obs_distns=obs_distns,**model)