Seq2Seq模型(DL4J)做出荒谬的预测

时间:2019-03-28 04:03:30

标签: java machine-learning seq2seq dl4j computation-graph

我正在尝试在DL4J中实现Seq2Seq预测器模型。我最终要使用的是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个时间序列观察值(对应于ComputationGraph中的in_data输入)和最后一个时间系列观察(对应于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左右,但是,我得到的大多数预测都是绝对值远大于零(约10s-100s)的值。这显然是不正确的。我已经为此工作了一段时间,却找不到问题。任何解决此问题的建议将不胜感激。

我使用过的其他资源: 可以从{88行开始} here找到示例Seq2Seq模型。 可以在here中找到ComputationGraph文档;我已经仔细阅读了这篇文章,以查看是否可以找到错误。

0 个答案:

没有答案