Я пытаюсь реализовать модель предиктора Seq2Seq в DL4J. В конечном итоге я хочу использовать временной ряд из INPUT_SIZE
точек данных, чтобы предсказать следующий временной ряд из OUTPUT_SIZE
точек данных с использованием этого типа модели. Каждая точка данных имеет numFeatures
функций. Теперь у DL4J есть некоторый пример кода, объясняющий, как реализовать очень простую модель Seq2Seq. Я добился некоторого прогресса в распространении их примера на мои собственные потребности; приведенная ниже модель компилируется, но ее прогнозы бессмысленны.
ComputationGraphConfiguration configuration = new
NeuralNetConfiguration.Builder()
.weightInit(WeightInit.XAVIER)
.updater(new Adam(0.25))
.seed(42)
.graphBuilder()
.addInputs("in_data", "last_in")
.setInputTypes(InputType.recurrent(numFeatures), InputType.recurrent(numFeatures))
//The inputs to the encoder will have size = minibatch x featuresize x timesteps
//Note that the network only knows of the feature vector size. It does not know how many time steps unless it sees an instance of the data
.addLayer("encoder", new LSTM.Builder().nIn(numFeatures).nOut(hiddenLayerWidth).activation(Activation.LEAKYRELU).build(), "in_data")
//Create a vertex indicating the very last time step of the encoder layer needs to be directed to other places in the comp graph
.addVertex("lastTimeStep", new LastTimeStepVertex("in_data"), "encoder")
//Create a vertex that allows the duplication of 2d input to a 3d input
//In this case the last time step of the encoder layer (viz. 2d) is duplicated to the length of the timeseries "sumOut" which is an input to the comp graph
//Refer to the javadoc for more detail
.addVertex("duplicateTimeStep", new DuplicateToTimeSeriesVertex("last_in"), "lastTimeStep")
//The inputs to the decoder will have size = size of output of last timestep of encoder (numHiddenNodes) + size of the other input to the comp graph,sumOut (feature vector size)
.addLayer("decoder", new LSTM.Builder().nIn(numFeatures + hiddenLayerWidth).nOut(hiddenLayerWidth).activation(Activation.LEAKYRELU).build(), "last_in","duplicateTimeStep")
.addLayer("output", new RnnOutputLayer.Builder().nIn(hiddenLayerWidth).nOut(numFeatures).activation(Activation.LEAKYRELU).lossFunction(LossFunctions.LossFunction.MSE).build(), "decoder")
.setOutputs("output")
.build();
ComputationGraph net = new ComputationGraph(configuration);
net.init();
net.setListeners(new ScoreIterationListener(1));
То, как я структурирую свои входные / помеченные данные, заключается в том, что у меня есть входные данные, разделенные между первыми наблюдениями INPUT_SIZE - 1
временных рядов (соответствующими вводу in_data
в ComputationGraph) и последними наблюдениями временных рядов (соответствующими на вход lastIn
). Этикетки - это единственный временной шаг в будущем; чтобы делать прогнозы, я просто звоню net.output()
OUTPUT_SIZE
раз, чтобы получить все прогнозы, которые я хочу. Чтобы лучше это увидеть, вот как я инициализирую свои входные данные / метки:
INDArray[] input = new INDArray[] {Nd4j.zeros(batchSize, numFeatures, INPUT_SIZE - 1), Nd4j.zeros(batchSize, numFeatures, 1)};
INDArray[] labels = new INDArray[] {Nd4j.zeros(batchSize, numFeatures, 1)};
Я полагаю, что моя ошибка связана с ошибкой в архитектуре моего графика вычислений, а не с тем, как я готовлю свои данные / делаю прогнозы / что-то еще, так как я делал другие мини-проекты с более простой архитектурой и у меня не было проблем ,
Мои данные нормализованы, чтобы иметь среднее значение 0 и стандартное значение. отклонение 1. Таким образом, большинство записей должно быть около 0, однако, большинство предсказаний, которые я получаю, являются значениями с абсолютным значением, намного большим нуля (порядка 10–100 с). Это явно не правильно. Я работал над этим в течение некоторого времени и не смог найти проблему; Любые предложения о том, как это исправить, будут очень благодарны.
Другие ресурсы, которые я использовал:
Пример модели Seq2Seq можно найти здесь , начиная со строки 88.
Документацию по ComputationGraph можно найти здесь ; Я внимательно прочитал это, чтобы узнать, смогу ли я найти ошибку безрезультатно.