拟合自定义(非顺序)有状态 RNN (GRU) 模型

Posted

技术标签:

【中文标题】拟合自定义(非顺序)有状态 RNN (GRU) 模型【英文标题】:Fitting a custom (non-sequential) stateful RNN (GRU) model 【发布时间】:2020-09-22 04:47:03 【问题描述】:

我在训练以下 GRU 模型时遇到了一些问题,它必须是有状态的并输出隐藏状态。

import numpy as np
import tensorflow as tf #2.1.0
from tensorflow import keras

BATCH_SIZE = 1
nfeatures = 3
history = 30 # shapes input array
horizon = 5 # shapes output array
nodes = 32

input_layer = tf.keras.layers.Input(batch_shape=(1,30,3),name="INPUT")

output, state_h = tf.keras.layers.GRU(nodes,
                                  return_sequences=True,
                                  stateful=True,
                                  return_state=True,
                                  batch_input_shape=(1,history,3), name='GRU1')(input_layer)

output_layer = tf.keras.layers.GRU(nodes, activation='tanh', name='GRU2')(output, state_h)

output_dense = tf.keras.layers.Dense(5, name='DENSE')(output_layer)

model = tf.keras.Model(input_layer, [output_dense, state_h])

model.compile(optimizer=tf.keras.optimizers.Adam(clipvalue=2.0),
              loss='mse',
              metrics=['mean_absolute_error', 'mean_squared_error'])

由于我需要模型来输出隐藏状态,所以我不使用顺序模型。 (我训练有状态的顺序模型没有问题。)

输入到网络的特征形状为np.shape(x)=(30,3),目标为np.shape(y)=(5,)

如果我调用model.predict(x),其中 x 是具有上述形状的 numpy 数组,它会如预期的那样引发错误,因为输入形状与预期输入不匹配。因此,我通过调用np.expand_dims(x,axis=0) 对输入数组进行整形,使其具有(1,30,3) 的输入形状。之后,它工作正常,即我得到一个输出。

我面临的问题是当我尝试训练模型时。调用

model.fit(x, y,epochs=1,steps_per_epoch=STEPS_PER_EPOCH)

抛出同样的错误,关于数据的形状

ValueError: 检查输入时出错:预期输入为 3 维,但得到的数组形状为 (30, 3)

像我为预测所做的那样重新调整数据并没有帮助

model.fit(np.expand_dims(x,axis=0), np.expand_dims(y,axis=0),epochs=1,steps_per_epoch=STEPS_PER_EPOCH)

ValueError: 样本数1不能被30步整除。请将步数改为可以消耗所有样本的值。

这是一个新的错误,设置steps_per_epoch=1抛出一个新的

ValueError:检查模型目标时出错:您传递给模型的 Numpy 数组列表不是模型预期的大小。预计会看到 2 个数组,用于输入 ['DENSE', 'GRU1'] 但得到以下 1 个数组列表:[array([[0.5124772, 0.51047856, 0.509669, 0.50830126, 0.5070507]], dtype=float32)]...

我的数据格式是否错误,或者我的图层架构是否缺少某些内容?我尝试在输入之后添加一个 Flatten 层,但它没有多大意义(在我的脑海中)并且它也不起作用。

提前致谢。

【问题讨论】:

【参考方案1】:

这里的问题是Nodes 的数量应该等于Output Shape。将Nodes 的值从32 更改为5,以及其他小的更改,将修复Error

完整的工作代码如下所示:

import numpy as np
import tensorflow as tf #2.1.0
from tensorflow import keras

BATCH_SIZE = 1
nfeatures = 3
history = 30 # shapes input array
horizon = 5 # shapes output array
nodes = 5

x = np.ones(shape = (30,3))
x = np.expand_dims(x, axis = 0)

y = np.ones(shape = (5,))
y = np.expand_dims(y, axis = 0)

print(x.shape) #(1, 30, 3)

print(y.shape) #(1, 5)

input_layer = tf.keras.layers.Input(batch_shape=(1,30,3),name="INPUT")

output, state_h = tf.keras.layers.GRU(nodes,
                                  return_sequences=True,
                                  stateful=True,
                                  return_state=True,
                                  batch_input_shape=(1,history,3), name='GRU1')(input_layer)

output_layer = tf.keras.layers.GRU(nodes, activation='tanh', name='GRU2')(output, state_h)

output_dense = tf.keras.layers.Dense(5, name='DENSE')(output_layer)

model = tf.keras.Model(input_layer, [output_dense, state_h])

model.compile(optimizer=tf.keras.optimizers.Adam(clipvalue=2.0),
              loss='mse',
              metrics=['mean_absolute_error', 'mean_squared_error'])

STEPS_PER_EPOCH = 1

model.fit(x, y,epochs=1,steps_per_epoch=STEPS_PER_EPOCH)

以上代码的输出为:

(1, 30, 3)

(1, 5)

1/1 [==============================] - 0s 3ms/step - loss: 1.8172 - DENSE_loss: 1.1737 - GRU1_loss: 0.6435 - DENSE_mean_absolute_error: 1.0498 - DENSE_mean_squared_error: 1.1737 - GRU1_mean_absolute_error: 0.7157 - GRU1_mean_squared_error: 0.6435
<tensorflow.python.keras.callbacks.History at 0x7f698bf8ac50>

希望这会有所帮助。快乐学习!

【讨论】:

您好,抱歉回复晚了。你确定你的代码可以运行吗?我按原样尝试了,但仍然收到错误 Error when checking model target: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 2 array(s), for inputs ['DENSE', 'GRU1'] but instead got the following list of 1 arrays: [array([[1., 1., 1., 1., 1.]])]... 如果我理解正确的话,通过为网络的输出层定义两个输出,我应该在拟合模型时提供两个数组作为目标,不是吗?所以我可能需要另一种方法来做到这一点。如果我误解了什么,请纠正我。

以上是关于拟合自定义(非顺序)有状态 RNN (GRU) 模型的主要内容,如果未能解决你的问题,请参考以下文章

了解RNN模型的基础单元LSTM、GRU、RQNN 与 SRU

几句话总结一个算法之RNNLSTM和GRU

快速理解RNN(LSTM,GRU)结构原理

lstm和GRU推导

几种常见的循环神经网络结构RNN、LSTM、GRU

lstm和gru结构的再理解