我正在尝试在 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
时间序列观察(对应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 左右,但是,我得到的大多数预测都是绝对值远大于零的值(大约 10s-100s)。这显然是不正确的。我已经为此工作了一段时间,但一直无法找到问题;任何有关如何解决此问题的建议将不胜感激。
我使用的其他资源:示例 Seq2Seq 模型可以在这里找到,从第 88 行开始。计算图文档可以在这里找到;我已经广泛阅读了这篇文章,看看我是否能找到一个无济于事的错误。