python - 拟合自定义(非顺序)有状态 RNN (GRU) 模型
问题描述
我在训练以下 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 数组列表不是模型预期的大小。预计会看到 2 个数组,用于输入 ['DENSE', 'GRU1'] 但得到以下 1 个数组的列表: [array([[0.5124772 , 0.51047856, 0.509669 , 0.50830126, 0.5070507 ]], dtype=float32 )]...
我的数据格式是否错误,或者我的图层架构是否缺少某些内容?我尝试在输入后添加一个 Flatten 层,但它没有多大意义(在我的脑海中),它也不起作用。
提前致谢。
解决方案
这里的问题是 Number ofNodes
应该等于Output Shape
. Nodes
将from的值更改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>
希望这可以帮助。快乐学习!
推荐阅读
- python - ValueError: 请在写入数据时传递 `features` 或至少一个示例
- python - 使用 Flask 从镜像凸轮网站保存图像
- docker - Jenkins 构建 docker 镜像失败,代码非零:137
- sql - 如何正确更新多对一实体 - 如何使用 OrderItem 更新 Order
- typescript - 如何在 SublimeText 中禁用下划线变量?
- android - “nativeSdkIntegration 无法安装”android 上的 sentry_flutter 错误
- html - 我在导航栏中的第一个列表项“全部”文本不像其他内容那样居中
- rust - TcpStream 解析后挂起 \u{d}\u{a}
- javascript - 将类组件转换为功能组件功能组件中的道具未正确传递且未收到查询
- rust - 我们如何控制用 serde_json 序列化的结构的显示?