LSTM Regression Example

January 12 Update

I experimented with CSVVariableSlidingWindowRecordReader and was able to complete a training round (after some data format changes), but ultimately didn’t think it was the correct choice since it iterates up to a maximum window size and I expect a fixed window size of 12.

I have switched to using CSVSequenceRecordReader similar to the UCISequenceClassification example. I also changed my data format such that custom/train/features/0.csv contains the integers 0 to 11, each on a new line. The label associated with that sequence (12) is stored in custom/train/labels/0.csv. I hope this new data format works for regression problems, though I can’t say for sure yet. If you know better @treo, I’d welcome your feedback. I was hoping to have a single file with a moving window to avoid duplicating time series segments across multiple files (i.e. 0 to 11 => 12 and 1 to 12 => 13 both contain the segment 1 to 12), but I just couldn’t figure it out, so I’m falling back to this more verbose data format.

val baseDir = new File("src/main/resources/custom/")
val baseTrainDir = new File(baseDir, "train")
val featuresDirTrain = new File(baseTrainDir, "features")
val labelsDirTrain = new File(baseTrainDir, "labels")
val trainFeatures = new CSVSequenceRecordReader
trainFeatures.initialize(new NumberedFileInputSplit(featuresDirTrain.getAbsolutePath + "/%d.csv", 0, 1))
val trainLabels = new CSVSequenceRecordReader
trainLabels.initialize(new NumberedFileInputSplit(labelsDirTrain.getAbsolutePath + "/%d.csv", 0, 1))

val miniBatchSize = 1
val regression = true
val numPossibleLabels = -1
val labelIndex = 0
val dataSetIterator =
  new SequenceRecordReaderDataSetIterator(trainFeatures, trainLabels, miniBatchSize, numPossibleLabels, regression)

while (dataSetIterator.hasNext)
  println(dataSetIterator.next)
dataSetIterator.reset()

The dataSetIterator seems to have the expected contents:

===========INPUT===================
[[[         0,    1.0000,    2.0000,    3.0000,    4.0000,    5.0000,    6.0000,    7.0000,    8.0000,    9.0000,   10.0000,   11.0000]]]
=================OUTPUT==================
[[[12.0000]]]

The new exception I’m hunting down occurs during training:

val hiddenLayerWidth = 30
val net = new MultiLayerNetwork(
  new NeuralNetConfiguration.Builder()
    .optimizationAlgo(STOCHASTIC_GRADIENT_DESCENT)
    .seed(123)
    .weightInit(XAVIER)
    .list
    .layer(
      new LSTM.Builder()
        .activation(TANH)
        .nIn(1)
        .nOut(hiddenLayerWidth)
        .build)
    .layer(
      new RnnOutputLayer.Builder(MSE)
        .activation(IDENTITY)
        .nIn(hiddenLayerWidth)
        .nOut(1)
        .lossFunction(MSE)
        .build()
    )
    .build)
net.init()
logger.info("Starting training...")
net.setListeners(new ScoreIterationListener(1))
net.fit(dataSetIterator, 50)

The exception is:

Sequence lengths do not match for RnnOutputLayer input and labels:Arrays should be rank 3 with shape [minibatch, size, sequenceLength] - mismatch on dimension 2 (sequence length) - input=[1, 30, 12] vs. label=[1, 1, 1]

The error message is fairly clear, though I don’t know how to resolve it yet. Help would be welcomed. I’ll come back again tomorrow with another status update.