Bases: object
A graph that supports BW training (and perhaps other types later). The graph is made up of Hmm units, connected in terms of their inputs and outputs, so that the entire graph is also a hidden Markov model.
See the __init__function for more complete documentation on building UttLattices.
graph is a FrozenGraph object with non-negative integer label pairs, (node_label, model_label), on the nodes. No node_label may appear more than once. hmm_mgr is a HmmMgr indexed by model_label. Arc labels are not used. graph.is_lattice must be True. graph.has_self_loop must be False. All hmms must be using the same GmmMgr to store their models. split_prob_dict is a mapping from pairs of labels (t1, t2) to a Numpy array of floats between 0 and 1. For a given pair, the array must have a length equal to the number of outputs in the model indicated by t1 (which must also be equal to the number of inputs in the model indicated by t2). Each number gives the probability of making a transition from t1 through an output state to the corresponding input state of t2. The dict must obey the following restrictions: All nodes t1 with more than one successor must have entries for every successor. For a given t1 with multiple sucessors, summing the values element-wise for all successors must give an array with all values equal to 1.0 (OK, very close to 1.0).
>>> gmm_mgr = make_gmm_mgr(20)
Here’s a trivial case of a graph with only one node, containing one model:
>>> gb = GraphBuilder()
>>> node_id = gb.new_node((0,0))
>>> gr0 = FrozenGraph(gb)
Make an Hmm with 8 states and order 3 (self loop, forward 1, forward 2)
>>> hmm = make_forward_hmm(gmm_mgr, 8, 3)
>>> hmm_mgr = HmmMgr((hmm,))
>>> tg0 = UttLattice(gr0, hmm_mgr, dict())
>>> gmm_mgr.set_adaptation_state("INITIALIZING")
>>> gmm_mgr.clear_all_accumulators()
>>> tg0.begin_training()
>>> gmm_mgr.set_adaptation_state("ACCUMULATING")
Perturb things a bit to avoid numerical problems
>>> seed(0)
>>> obs_seq = list(imap(np.array, repeat((3 + 0.1*random(), 2 + 0.1*random()), 20) ))
>>> tg0.train_one_sequence(obs_seq)
>>> obs_seq = list(imap(np.array, repeat((3 + 0.1*random(), 2 + 0.1*random()), 20) ))
>>> tg0.train_one_sequence(obs_seq)
>>> obs_seq = list(imap(np.array, repeat((3 + 0.1*random(), 2 + 0.1*random()), 20) ))
>>> tg0.train_one_sequence(obs_seq)
>>> with DebugPrint("gaussian_numeric_error"):
... gmm_mgr.set_adaptation_state("APPLYING")
... gmm_mgr.apply_all_accumulators()
... tg0.end_training()
... gmm_mgr.set_adaptation_state("NOT_ADAPTING")
>>> gb = GraphBuilder()
>>> node_ids = []
>>> for label in xrange(7):
... node_ids.append(gb.new_node((label,label)))
>>> for s, e in ((0, 1), (1, 2), (1, 3), (2, 4), (3, 4), (4, 5), (5, 6)):
... arc_id = gb.new_arc(node_ids[s], node_ids[e])
>>> gr0 = FrozenGraph(gb)
>>> gr0.is_lattice
True
>>> gr0.has_self_loop
False
>>> gmm_mgr = make_gmm_mgr(20)
>>> hmms = tuple(make_forward_hmm(gmm_mgr, 8, 3, exact=True) for i in xrange(7))
>>> hmm_mgr = HmmMgr(hmms)
Split-prob dictionary
>>> spd = {}
Keys are pairs of (pred_node_label, succ_node_label). NB that the summing-to-one condition is across tuple positions from a given predeccessor.
>>> spd[(1,2)] = (0.5, 0.5, 0.5)
>>> spd[(1,3)] = (0.5, 0.5, 0.5)
>>> tg = UttLattice(gr0, hmm_mgr, spd)
>>> gmm_mgr.set_adaptation_state("INITIALIZING")
>>> hmm_mgr.set_adaptation_state("INITIALIZING")
>>> gmm_mgr.clear_all_accumulators()
>>> tg.begin_training()
>>> gmm_mgr.set_adaptation_state("ACCUMULATING")
>>> hmm_mgr.set_adaptation_state("ACCUMULATING")
>>> obs_seq1 = list(chain(imap(np.array, repeat((1.0 + 0.1*random(), 0.5 + 0.1*random()), 20)) ,
... imap(np.array, repeat((3.0 + 0.1*random(), 4.0 + 0.1*random()), 10)) ))
>>> tg.train_one_sequence(obs_seq1)
>>> obs_seq1 = list(chain(imap(np.array, repeat((1.0 + 0.1*random(), 0.5 + 0.1*random()), 20)) ,
... imap(np.array, repeat((3.0 + 0.1*random(), 4.0 + 0.1*random()), 10)) ))
>>> tg.train_one_sequence(obs_seq1)
>>> obs_seq1 = list(chain(imap(np.array, repeat((1.0 + 0.1*random(), 0.5 + 0.1*random()), 20)) ,
... imap(np.array, repeat((3.0 + 0.1*random(), 4.0 + 0.1*random()), 10)) ))
>>> tg.train_one_sequence(obs_seq1)
>>> with DebugPrint("gaussian_numeric_error"):
... gmm_mgr.set_adaptation_state("APPLYING")
... hmm_mgr.set_adaptation_state("APPLYING")
... gmm_mgr.apply_all_accumulators()
... hmm_mgr.apply_all_accumulators()
... tg.end_training()
... gmm_mgr.set_adaptation_state("NOT_ADAPTING")
... hmm_mgr.set_adaptation_state("NOT_ADAPTING")
>>> print tg
UttLattice with 7 nodes:
>>> hmm_conv = tg.convert_to_standalone_hmm()
>>> hmm_conv.to_string()
'Hmm: num_states = 56, log_domain = False, model dim = 2'
Set up this UttLattice for training.
Convert a UttLattice instance into a standalone Hmm. Returns the new Hmm. If alt_gmm_mgr is not None, it will be used as the GmmMgr of the resulting Hmm. This allows the result to avoid sharing models with the original UttLattice.
Display a dot-generated representation of the UttLattice. Returns the name of the temporary file that the display tool is working from. The caller is responsible for removing this file.
Optional temp_file_prefix is the prefix used for the filename.
Optional display_tool_format is formatting string, with %s where the filename goes, used to generate the command that will display the file. By default it assumes you’re on a Mac and have Graphviz.app installed in the /Applications directory.
Remaining keyword arguments are handed to the dot_iter function.
Returns a generator that yields lines of text, including newlines. The text represents the UttLattice in the DOT language for which there are many displayers. See also dot_display().
Optional argument bwt_label is a string label for the UttLattice. Optional argument graph_type defaults to ‘digraph’, can also be ‘graph’ and ‘subgraph’
Optional globals is an iterable that yields strings to put in the globals section of the DOT file.
End training on this UttLattice, which does the actual adaptation of split-probabilities, but not of the Hmms in this graph. To adapt Hmms, call apply_all_accumulators on the relevant HmmMgr.
Train the graph on one iterable of observations. This call only accumulates; changes to models are only made by end_training.
random() -> x in the interval [0, 1).