Модель Seq2Seq (DL4J) делает абсурдные прогнозы - PullRequest
1 голос
/ 28 марта 2019

Я пытаюсь реализовать модель предиктора 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 можно найти здесь ; Я внимательно прочитал это, чтобы узнать, смогу ли я найти ошибку безрезультатно.

...