4

I would like to predict hidden states using Hidden Markov Model (decoding problem). The data is categorical. The hidden states include Hungry, Rest, Exercise and Movie. The observation set include Food, Home, Outdoor & Recreation and Arts & Entertainment. My program is first to train the HMM based on the observation sequence (Baum-Welch algorithm). And then I do the decoding (Viterbi algorithm) to predict the hidden state sequence.

My question is that how I can map the result (non-negative integers) to their corresponding categories like Hungry or Rest. Because of the non-deterministic property of the training algorithm , the parameters are different for every training of the same data. Therefore the hidden state sequence is different every time if I do the map like the following code.

The code is as follows:

from __future__ import division
import numpy as np
from hmmlearn import hmm

states = ["Hungry", "Rest", "Exercise", "Movie"]
n_states = len(states)

observations = ["Food", "Home", "Outdoor & Recreation", "Arts & Entertainment"]

# The number in this sequence is the index of observation
category_sequence = [1, 0, 1, 2, 1, 3, 1]
Location = np.array([category_sequence]).T
model = hmm.MultinomialHMM(n_components=n_states).fit(Location)

logprob, result = model.decode(Location)
print "Category:", ", ".join(map(lambda x: observations[x], Location.T[0]))
print "Intent:", ", ".join(map(lambda x: states[x], result))
Isaiah
  • 607
  • 1
  • 5
  • 9

1 Answers1

5

This is known as label-switching problem. The log-likelihood of the model sums over all of the states and is therefore independent of the particular ordering.

As far as I know, there is no general recipe for dealing with it. Among the things you might try are:

  • Find a partially labelled dataset, run predict on it and use the predictions to map the state indices to the corresponding labels.
  • Come up with heuristics for possible parameter values in each state. This could be tricky to do for Multinomials, but is possible if you model e.g. accelerometer data.

Update: An ad-hoc version of guessing state to label mapping from labelled data.

def guess_labels(hmm, X, labels):
    result = [None] * hmm.n_components
    for label, y_t in zip(labels, hmm.predict(X)):
        assigned = result[y_t]
        if assigned is not None:
            # XXX clearly for any real data there might be
            #     (and there will be) conflicts. Here we just blindly
            #     hope the ``assert`` never fires.
            assert assigned == label
        else:
            result[y_t] = label
    return result
Sergei Lebedev
  • 2,659
  • 20
  • 23
  • Hi Sergei, it is nice to hear from you. For the first one, I am a little confused about how can I do it in a semi-supervised manner in hmmlearn module. When I call function fit, the input is only observations. Can you tell me more about it? Thanks. – Isaiah Sep 29 '16 at 18:07
  • `hmmlearn` does not currently have a way of doing this automatically, because all of the problems I've used HMMs are unsupervised (i.e. no labelled data are available at all) and thus require the second approach. Anyway, I've updated the answer, please do let me know if the output of `guess_labels` makes any sense for your data. – Sergei Lebedev Sep 29 '16 at 20:51
  • Thanks Sergei, I just switch to LSTM to train my data and it seems OK for me. – Isaiah Oct 12 '16 at 23:19
  • Yeah, for supervised data LSTM might be a better choice. – Sergei Lebedev Oct 14 '16 at 08:59