Keras/Tensorflow RNN 层的输入

Keras/Tensorflow Input to RNN layers

我正在尝试在 Keras 中构建 RNN。我不太了解所需的输入格式。我可以毫无问题地构建密集网络,但我认为 RNN 层需要输入维度 x 批次 x 时间步长?谁能验证一下?

这是我要更新的代码:

原代码:

def get_generative(G_in, dense_dim=200, out_dim=50, lr=1e-3):
   x = Dense(dense_dim)(G_in)
   x = Activation('tanh')(x)
   G_out = Dense(out_dim, activation='tanh')(x)
   G = Model(G_in, G_out)
   opt = SGD(lr=lr)
   G.compile(loss='binary_crossentropy', optimizer=opt)
   return G, G_out

G_in = Input(shape=[10])
G, G_out = get_generative(G_in)
G.summary()

修改了 GRU 层和一些略有不同的维度:

def get_generative(G_in, dense_dim=10, out_dim=37, lr=1e-3):
   clear_session()
   x = GRU(dense_dim, activation='tanh',return_state=True)(G_in)
   G_out = GRU(out_dim, return_state=True)(x)
   G = Model(G_in, G_out)
   opt = SGD(lr=lr)
   G.compile(loss='binary_crossentropy', optimizer=opt)
   return G, G_out

G_in = Input(shape=(None,3))
G, G_out = get_generative(G_in)
G.summary()

我在这段代码中看到的错误是:

ValueError: Tensor("gru_1/strided_slice:0", shape=(3, 10), dtype=float32) must be from the same graph as Tensor("strided_slice_1:0", shape=(?, 3), dtype=float32).

如果我删除上面的 None,我得到:

ValueError: Input 0 is incompatible with layer gru_1: expected ndim=3, found ndim=2

在这里任何解释都会有所帮助。

您收到错误,因为您在创建输入张量后清除了会话。这就是为什么输入张量与网络的其余部分不来自同一个图的原因。要解决此问题,只需省略行 clear_session().

您的代码的另一个问题:第二个 GRU 层需要序列输入,因此您应该在第一个 GRU 层内使用 return_sequences=True。您可能希望省略参数 return_state=True,因为这会使层 return 成为张量元组(输出和状态),而不仅仅是一个输出张量。

总而言之,下面的代码应该可以做到:

def get_generative(G_in, dense_dim=10, out_dim=37, lr=1e-3):
   x = GRU(dense_dim, activation='tanh', return_sequences=True)(G_in)
   G_out = GRU(out_dim)(x)
   G = Model(G_in, G_out)
   opt = SGD(lr=lr)
   G.compile(loss='binary_crossentropy', optimizer=opt)
   return G, G_out

这里的问题是 RNN 层期望 3D 张量输入的形式:[num samples, time steps, features]。

所以我们可以将上面的代码修改为:

def get_generative(G_in, dense_dim=10, out_dim=37, lr=1e-3):
   x = GRU(dense_dim, activation='tanh',return_state=True)(G_in)
   G_out = GRU(out_dim, return_state=True)(x)
   G = Model(G_in, G_out)
   opt = SGD(lr=lr)
   G.compile(loss='binary_crossentropy', optimizer=opt)
   return G, G_out

G_in = Input(shape=(1,3))
G, G_out = get_generative(G_in)
G.summary()

所以我们的意思是我们期望输入任意数量的样本,每个样本具有 1 个时间步长和 3 个特征。

Anna 是正确的,clear_session() 不应该在生成器函数中。

最后,如果你真的想把数据输入网络,它的形状也应该符合我们刚才讨论的。您可以使用 numpy reshape 来做到这一点:

X = np.reshape(X, (X.shape[0], 1, X.shape[1]))