Onyx logo

Previous topic

onyx.am.modelmgr – Model managers at various levels.

Next topic

onyx.am.classifier – Classifiers using GaussianMixtureModels

This Page

onyx.am.hmm_mgr – A manager for Hmms. Also read and write functions for acoustic models.

Here’s a simple round-trip test starting from an HTK model file.

XXX need to make this use build dir when SCons is running things

>>> model_dirname = path.normpath(path.join(onyx.home, 'py/onyx/htkfiles'))
>>> model_filename = path.join(model_dirname, 'monophones.mmf')
>>> with open(model_filename) as f:
...     model_dict, hmm_mgr, gmm_mgr = htkmmf.read_htk_mmf_file(f)

Write this model out to a file

>>> # with opentemp('wb', suffix='.tmp', prefix='onyx_hmm_mgr_test') as (filename, outfile):
# ...     write_acoustic_model(model_dict, gmm_mgr, hmm_mgr, outfile)

Now read it back in

>>> # with open(filename, 'rb') as infile:
# ...     model_dict2, gmm_mgr2, hmm_mgr2 = read_acoustic_model(infile, log_domain=True)
>>> # os.remove(filename)

Now compare

>>> # model_dict == model_dict2
True
>>> # gmm_mgr == gmm_mgr2
True
>>> # hmm_mgr == hmm_mgr2
True
class onyx.am.hmm_mgr.HmmMgr(arg)

Bases: onyx.am.modelmgr.ModelManager

A container and manager for Hmms.

E.g., UttLattices use this class to hold the models which comprise the graph. Models must all have the same dimension, covariance type, and gmm_mgr. Accumulation and adaptation of transition probabilities is handled here.

Initialization can take three forms. First, an int argument constructs an empty HmmMgr for models with the given dimension (number of features). Second, another HmmMgr can be passed in, in which case the new HmmMgr is a deep copy of the argument. Third, an iterable of models can be passed in, in which case the new HmmMgr will have those models, in the order iterated. In this case, the iterable should return instances of Hmm.

add_epsilon_model(gmm_mgr, arity, log_domain=False)

Add an epsilon model with the given arity if it doesn’t already exist.

arity is an int with value > 0. Returns the index of the model added. This call can only be made when the adaptation state is NOT_ADAPTING.

>>> dim = 12
>>> covar_type = gaussian.GaussianModelBase.DIAGONAL_COVARIANCE
>>> gmm0 = gaussian.GaussianMixtureModel(dim, covar_type, num_components=3)
>>> gmm0.init_models()
>>> gmm1 = gmm0.copy()
>>> gmm_mgr1 = modelmgr.GmmMgr((gmm0, gmm1))
>>> hmm_mgr0 = HmmMgr(12)
>>> hmm_mgr0.has_epsilon_model(1)
False
>>> hmm_mgr0.add_epsilon_model(gmm_mgr1, 1)
0
>>> hmm_mgr0.has_epsilon_model(1)
True
>>> hmm_mgr0.add_epsilon_model(gmm_mgr1, 1)
0
>>> hmm_mgr0.add_epsilon_model(gmm_mgr1, 2)
1
>>> hmm_mgr0.add_epsilon_model(gmm_mgr1, 4)
2
>>> print hmm_mgr0
HmmMgr with 3 models
>>> hmm_mgr0.input_arity_set
set([1, 2, 4])
>>> hmm_mgr0.output_arity_set
set([1, 2, 4])
>>> idx = hmm_mgr0.get_epsilon_model_index(2)
>>> # hmm_mgr0[idx].dot_display()
>>> hmm_mgr0.add_epsilon_model(None, -4)
Traceback (most recent call last):
  ...
ValueError: expected arity to be > 0, but got -4
add_models(models)

Add some models to this manager

models is an iterable returning instances of Hmm. Returns the indices of the models added. This call can only be made when the adaptation state is NOT_ADAPTING.

apply_all_accumulators()

Apply the accumulators for all models. This call can only be made when the adaptation state is APPLYING.

clear_all_accumulators()

Clear the accumulators for all models. This call can only be made when the adaptation state is INITIALIZING.

dimension
ensure_accumulators(models)

Construct and initialize accumulators for the given models if they don’t already have them. If a model has accumulators, this call doesn’t do anything. This call can only be made when the adaptation state is INITIALIZING.

get_adaptation_state()
get_epsilon_model_index(arity)

Get the index of an epsilon model with the given arity or None if there isn’t one.

get_model(index)
has_epsilon_model(arity)

See if this HmmMgr has an epsilon model with the given arity.

input_arity_set
log_domain
num_models
output_arity_set
score_alignment(alignment, data, start_probs=None)

Score the given alignment against data. data should be a numpy array of feature data in the usual form. alignment should be an iterable of pairs (model, state) which gives the model and state for each frame. The return is a sequence of pairs of scores (acoustic, transition) for each frame which gives the score of the underlying GMM and the transition penalty. If any adjacent states have transition probability 0, the corresponding pair will have a 0 score. If start_probs is not None, it should be a Numpy array with shape (n_inputs,) giving the starting probabilities across the inputs of the first HMM in the sequence. If start_probs is None, a uniform distribution across inputs is used.

If any adjacent HMMs have different numbers of inputs and outputs or if start_probs is not the correct shape, an error is raised.

>>> dummies = ( gaussian.DummyModel(2, 0.125), gaussian.DummyModel(2, 0.25), gaussian.DummyModel(2, 0.375), gaussian.DummyModel(2, 0.625) )
>>> mm = modelmgr.GmmMgr(dummies)
>>> models1 = range(3)
>>> models2 = range(1,4)
>>> hmm0 = hmm.build_forward_hmm_compact(3, mm, models1, 2, ((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)))
>>> hmm1 = hmm.build_forward_hmm_compact(3, mm, models2, 2, ((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)))

# >>> hmm0.dot_display() # >>> hmm1.dot_display()

>>> hmm_mgr0 = HmmMgr((hmm0, hmm1))
>>> alignment = ((0, 0),  (0, 0),  (0, 0),  (0, 0),  (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (1, 2))
>>> data = np.zeros((1, 2, 10))
>>> scores0 = hmm_mgr0.score_alignment(alignment, data)
>>> scores0
((0.125, 1.0), (0.125, 0.5), (0.125, 0.5), (0.125, 0.5), (0.25, 0.5), (0.375, 0.5), (0.25, 0.5), (0.375, 0.5), (0.625, 0.5), (0.625, 0.5))
>>> hmm2 = hmm.build_forward_hmm_exact(3, mm, models1, 3, ((0.5, 0.5, 0.5), (0.25, 0.25, 0.25), (0.25, 0.25, 0.25)))
>>> hmm3 = hmm.build_forward_hmm_exact(3, mm, models2, 3, ((0.5, 0.5, 0.5), (0.25, 0.25, 0.25), (0.25, 0.25, 0.25)))

# >>> hmm2.dot_display() # >>> hmm3.dot_display()

>>> start_probs = np.array((0.25, 0.25, 0.5))
>>> hmm_mgr1 = HmmMgr((hmm2, hmm3))
>>> scores1 = hmm_mgr1.score_alignment(alignment, data, start_probs=start_probs)
>>> scores1
((0.125, 0.5), (0.125, 0.5), (0.125, 0.5), (0.125, 0.5), (0.25, 0.25), (0.375, 0.25), (0.25, 0.25), (0.375, 0.25), (0.625, 0.25), (0.625, 0.5))
>>> hmm4 = hmm.build_forward_hmm_compact(3, mm, models1, 3, ((0.5, 0.5, 0.5), (0.25, 0.25, 0.25), (0.25, 0.25, 0.25)))
>>> hmm5 = hmm.build_forward_hmm_compact(3, mm, models2, 3, ((0.5, 0.5, 0.5), (0.25, 0.25, 0.25), (0.25, 0.25, 0.25)))

# >>> hmm4.dot_display() # >>> hmm5.dot_display()

>>> hmm_mgr2 = HmmMgr((hmm4, hmm5))
>>> scores2 = hmm_mgr2.score_alignment(alignment, data)
>>> scores2
((0.125, 0.5), (0.125, 0.5), (0.125, 0.5), (0.125, 0.5), (0.25, 0.25), (0.375, 0.25), (0.25, 0.25), (0.375, 0.25), (0.625, 0.25), (0.625, 0.5))
>>> scores2_1 = hmm_mgr2.score_alignment(alignment, data, np.array((0.25, 0.75)))
>>> scores2_1
((0.125, 0.25), (0.125, 0.5), (0.125, 0.5), (0.125, 0.5), (0.25, 0.25), (0.375, 0.25), (0.25, 0.25), (0.375, 0.25), (0.625, 0.25), (0.625, 0.5))

Errors:

>>> hmm_mgr3 = HmmMgr((hmm3, hmm4))
>>> scores3 = hmm_mgr3.score_alignment(alignment, data)
Traceback (most recent call last):
...
ValueError: expected number of outputs (3) for model 0 to match number of inputs (2) for model 1
>>> hmm_mgr4 = HmmMgr((hmm4,))
>>> scores4 = hmm_mgr4.score_alignment(alignment, data, start_probs)
Traceback (most recent call last):
...
ValueError: expected start probs with shape (2,), got (3,)
set_adaptation_state(new_state)
to_string(full=False)
onyx.am.hmm_mgr.read_acoustic_model(file, log_domain=False)

Read a complete acoustic model from a file.

file should be open for reading. Returns a tuple (model_dict, gmm_mgr, hmm_mgr). If log_domain is True, the hmm_mgr will use the log domain for scoring.

onyx.am.hmm_mgr.read_hmm_mgr(file, gmm_mgr)
onyx.am.hmm_mgr.write_acoustic_model(model_dict, gmm_mgr, hmm_mgr, file)

Write a complete acoustic model to a file.

file should be open for writing. model_dict, gmm_mgr and hmm_mgr comprise the model.

onyx.am.hmm_mgr.write_hmm_mgr(hmm_mgr, file)
>>> dummies = ( gaussian.DummyModel(2, 0.1), gaussian.DummyModel(2, 0.2), gaussian.DummyModel(2, 0.4), gaussian.DummyModel(2, 0.4) )
>>> mm = modelmgr.GmmMgr(dummies)
>>> models = range(3)
>>> hmm0 = hmm.build_forward_hmm_compact(3, mm, models, 2, ((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)))
>>> hmm1 = hmm.build_forward_hmm_compact(3, mm, models, 2, ((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)))
>>> hmm_mgr0 = HmmMgr((hmm0, hmm1))
>>> f = cStringIO.StringIO()
>>> write_hmm_mgr(hmm_mgr0, f)

# Round-trip test

>>> f.seek(0)  # rewind
>>> hmm_mgr1 = read_hmm_mgr(f, mm)
>>> hmm_mgr0 == hmm_mgr1
True