Keras简单RNN实现

6
我在尝试编译一个带有一层循环的网络时遇到了问题。似乎第一层的维度存在问题,这影响了我对Keras中RNN层工作原理的理解。
以下是我的代码示例:
model.add(Dense(8,
                input_dim = 2,
                activation = "tanh",
                use_bias = False))
model.add(SimpleRNN(2,
                    activation = "tanh",
                    use_bias = False))
model.add(Dense(1,
                activation = "tanh",
                use_bias = False))

错误信息为:
ValueError: Input 0 is incompatible with layer simple_rnn_1: expected ndim=3, found ndim=2

无论 input_dim 值为何,都会返回此错误。我错过了什么吗?
1个回答

4
那个消息的意思是:输入进入RNN具有2个维度,但RNN层期望3个维度。对于RNN层,您需要输入的形状为 (BatchSize,TimeSteps,FeaturesPerStep)。这些是期望的3个维度。在keras 2中,Dense层可以使用2个或3个维度。我们可以看到你使用了2个,因为你传递了一个input_dim而不是传递一个input_shape=(Steps, Features)。有许多可能的解决方案,但最有意义和合乎逻辑的情况应该是您的输入数据是一个带有时间步长的序列。
解决方案1 - 您的训练数据是序列: 如果您的训练数据是序列,则将其形状设置为(NumberOfSamples, TimeSteps, Features),并将其传递给您的模型。确保在第一层中使用input_shape=(TimeSteps,Features),而不是使用input_dim。
解决方案2 - 重新调整第一个密集层的输出,使其具有额外的维度:
model.add(Reshape((TimeSteps,Features)))

请确保您的第一个密集层的输出为 8,即产品 TimeSteps*Features 等于 8


太棒了,谢谢,还有一个问题。第一个解决方案完美地运行,但是如果我想要无限的时间步(这是理论上的问题,我知道,无限的时间步是愚蠢的)?那么,我必须使用您的第二个解决方案并从第一层重新塑造输出。但是,我用XOR的序列进行了简单的测试,并且当我洗牌时,网络未能像我预期的那样做出反应。更确切地说,它返回与洗牌之前相同的输出。当与第一个解决方案进行比较时,重塑如何影响递归层的工作? - dev1223
1
重塑只需要数据(任何数据),它不过是一串被分段的数字序列。假设你有300个元素。当你将它们重塑为(30,10,1)时,你只是以不同的方式分离了这300个元素。因此,如果你为了序列目的而进行重塑,你必须知道你想要实现什么以及你的数据格式是什么,这样你才能以有意义的方式进行重塑。 - Daniel Möller
对于您的无限序列,您应该使用仅1个样本的输入进行工作(BatchSize=1,TimeSteps,Features),并将递归层标记为stateful=True。这意味着层将保持其内存,并且下一批将被视为在一个单一序列中继续前一批。在这种情况下,当您决定一个序列结束并且您将开始提供另一个序列时,必须手动“清除内存”(称为“重置状态”)。 - Daniel Möller
Daniel Möller 谢谢。 - dev1223

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接