Hidden Markov Models Java Library by adrianulbona (original) (raw)

HMM abstractions in Java 8

Build Status

Besides the basic abstractions, a most probable state sequence solution is implemented based on the Viterbi algorithm.

The library is hosted on Maven Central:

Maven

io.github.adrianulbona hmm 0.1.0

Gradle

compile 'io.github.adrianulbona:hmm:0.1.0'

How to use it:

Getting the most probable sequence of states based on a sequence of observations:

Model<MedicalState, Symptom> model = WikipediaViterbi.INSTANCE.model; List symptoms = asList(NORMAL, COLD, DIZZY); List evolution = new MostProbableStateSequenceFinder<>(model).basedOn(symptoms);

How to define a model:

public enum WikipediaViterbi { INSTANCE;

public final Model<MedicalState, Symptom> model;

WikipediaViterbi() {
    model = new Model<>(probabilityCalculator(), reachableStatesFinder());
}

public enum MedicalState implements State {
    HEALTHY,
    FEVER;
}

public enum Symptom implements Observation {
    NORMAL,
    COLD,
    DIZZY;
}

private ProbabilityCalculator<MedicalState, Symptom> probabilityCalculator() {
    return new ProbabilityCalculator<>(StartProbabilities.INSTANCE.data::get,
            EmissionProbabilities.INSTANCE.data::get, 
            TransitionProbabilities.INSTANCE.data::get);
}

private ReachableStateFinder<MedicalState, Symptom> reachableStatesFinder() {
    return observation -> asList(MedicalState.values());
}

private enum StartProbabilities {
    INSTANCE;

    public final Map<MedicalState, Double> data;

    StartProbabilities() {
        data = new HashMap<>();
        data.put(MedicalState.HEALTHY, 0.6);
        data.put(MedicalState.FEVER, 0.4);
    }
}

private enum TransitionProbabilities {
    INSTANCE;

    public final Map<Transition<MedicalState>, Double> data;

    TransitionProbabilities() {
        data = new HashMap<>();
        data.put(new Transition<>(MedicalState.HEALTHY, MedicalState.HEALTHY), 0.7);
        data.put(new Transition<>(MedicalState.HEALTHY, MedicalState.FEVER), 0.3);
        data.put(new Transition<>(MedicalState.FEVER, MedicalState.HEALTHY), 0.4);
        data.put(new Transition<>(MedicalState.FEVER, MedicalState.FEVER), 0.6);
    }
}

private enum EmissionProbabilities {
    INSTANCE;

    public final Map<Emission<MedicalState, Symptom>, Double> data;

    EmissionProbabilities() {
        data = new HashMap<>();
        data.put(new Emission<>(MedicalState.HEALTHY, Symptom.NORMAL), 0.5);
        data.put(new Emission<>(MedicalState.HEALTHY, Symptom.COLD), 0.4);
        data.put(new Emission<>(MedicalState.HEALTHY, Symptom.DIZZY), 0.1);
        data.put(new Emission<>(MedicalState.FEVER, Symptom.NORMAL), 0.1);
        data.put(new Emission<>(MedicalState.FEVER, Symptom.COLD), 0.3);
        data.put(new Emission<>(MedicalState.FEVER, Symptom.DIZZY), 0.6);
    }
}

}