Question

I am trying to create an HMM to predict chords based on played melodies in Java, using the Jahmm library here. I am following along with the example that they provide on their page, though I made several changes. For my purposes all I need is the following:

Hmm<ObservationInteger> learntHmm = buildInitHmm();

List<List<ObservationInteger>> sequences = generateSequences();
BaumWelchLearner learner = new BaumWelchLearner();

for (int i = 0; i < 10; i++) {
    learntHmm = learner.iterate(learntHmm, sequences);
}

The initial HMM I have basically everything set to (1/7), for the 7 chords and 7 notes in a key.

My generateSequences() method is the following:

List<List<ObservationInteger>> sequences = new ArrayList<List<ObservationInteger>>();

try {
    BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("trainingData.txt")));
    String currentLine;
    Random generator = new Random();
    while ((currentLine = bufferedReader.readLine()) != null) {
        String data[] = currentLine.split(" ");
        List<ObservationInteger> observations = new ArrayList<ObservationInteger>();
        for (int i = 0; i < data.length; i++) {
            int dataValue = ((Integer.parseInt(data[i])) % 7);
            ObservationInteger observationInteger = new ObservationInteger(dataValue);
            observations.add(observationInteger);
        }
        sequences.add(observations);
    }
    bufferedReader.close();
} catch (FileNotFoundException e) {
    System.out.println("File not found.");
} catch (IOException e) {
    e.printStackTrace();
}
return sequences;

This reads the values from a .txt file into the List<List<ObservationInteger>> that is then used to learn the HMM. However, if I run this, I get a Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1 on the line learntHmm = learner.iterate(learntHmm, sequences);.

Fair enough, however when I change this

ObservationInteger observationInteger = new ObservationInteger(dataValue)

to instead be

ObservationInteger(Random.nextInt(7))

this works perfectly fine. I don't understand why this would be the case: in both of these cases I am providing the sequences with observations valued as integers between 0-6. In both cases the dimensions are exactly the same, but only when the integers are randomly generated instead of read in from my file does this work. Any ideas why?

Observation Integer Class

Full Stack Trace:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at be.ac.ulg.montefiore.run.jahmm.OpdfInteger.probability(OpdfInteger.java:85)
at be.ac.ulg.montefiore.run.jahmm.OpdfInteger.probability(OpdfInteger.java:1)
at be.ac.ulg.montefiore.run.jahmm.ForwardBackwardCalculator.computeAlphaStep(ForwardBackwardCalculator.java:124)
at be.ac.ulg.montefiore.run.jahmm.ForwardBackwardCalculator.computeAlpha(ForwardBackwardCalculator.java:102)
at be.ac.ulg.montefiore.run.jahmm.ForwardBackwardCalculator.<init>(ForwardBackwardCalculator.java:63)
at be.ac.ulg.montefiore.run.jahmm.learn.BaumWelchLearner.generateForwardBackwardCalculator(BaumWelchLearner.java:133)
at be.ac.ulg.montefiore.run.jahmm.learn.BaumWelchLearner.iterate(BaumWelchLearner.java:73)
at HiddenMarkovModel.main(HiddenMarkovModel.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Was it helpful?

Solution

As someone pointed out, some of the values being read into the sequences were not properly valued. For this set up to work HMM needed to take values between 0-6. I am not entirely sure why modulo did not account for this, but I wrote my own little method that guaranteed all values read in from .txt file were between 0 and 6 and that fixed it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top