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

时间:2020-06-03 13:09:04

标签: python python-3.x tensorflow recurrent-neural-network tf.keras

在训练以下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数组,则它会如预期的那样引发错误,因为输入形状与预期的输入不匹配。因此,我通过调用(1,30,3)将输入数组整形为np.expand_dims(x,axis=0)的输入形状。之后,它可以正常工作,即我得到了输出。

我面临的问题是当我尝试训练模型时。打电话

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数组列表不是模型期望的大小。对于输入['DENSE','GRU1'],预期会看到2个数组,但得到了以下1个数组的列表:[array([[[0.5124772,0.51047856,0.509669,0.50830126,0.5070507]], dtype = float32)] ...

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

谢谢。

1 个答案:

答案 0 :(得分:0)

这里的问题是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>

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