tf2.0 Keras:使用 RNN 的自定义张量流代码时无法保存权重
Posted
技术标签:
【中文标题】tf2.0 Keras:使用 RNN 的自定义张量流代码时无法保存权重【英文标题】:tf2.0 Keras: unable to save weights when using custom tensorflow code for RNN 【发布时间】:2019-12-21 18:47:35 【问题描述】:我正在使用 Keras API 在 tf2 中编写一个 Encoder-Recurrent Decoder 模型。在解码阶段,我想将一些自定义函数应用于模型输出。但是,一旦我开始将 tensorflow 代码“嵌入”到我的功能性 Keras 模型中,我就无法再保存权重了 - 而是出现了 ValueError
异常:
ValueError: Unable to create group (name already exists)
模型可以被训练并且损失正在减少,正如我所期望的那样。唯一的问题是事后存储权重。
整个错误信息:
ValueError Traceback (most recent call last)
<ipython-input-4-5edae36ba5fe> in <module>()
57 model.compile(loss='MSE', optimizer='adam')
58
---> 59 model.save_weights('/tmp/dummy.h5')
60 print('saved')
2 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/network.py in save_weights(self, filepath, overwrite, save_format)
1310 if save_format == 'h5':
1311 with h5py.File(filepath, 'w') as f:
-> 1312 saving.save_weights_to_hdf5_group(f, self.layers)
1313 else:
1314 if context.executing_eagerly():
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/saving/hdf5_format.py in save_weights_to_hdf5_group(f, layers)
617
618 for layer in layers:
--> 619 g = f.create_group(layer.name)
620 weights = _legacy_weights(layer)
621 weight_values = K.batch_get_value(weights)
/usr/local/lib/python3.6/dist-packages/h5py/_hl/group.py in create_group(self, name, track_order)
58 name, lcpl = self._e(name, lcpl=True)
59 gcpl = Group._gcpl_crt_order if track_order else None
---> 60 gid = h5g.create(self.id, name, lcpl=lcpl, gcpl=gcpl)
61 return Group(gid)
62
h5py/_objects.pyx in h5py._objects.with_phil.wrapper()
h5py/_objects.pyx in h5py._objects.with_phil.wrapper()
h5py/h5g.pyx in h5py.h5g.create()
ValueError: Unable to create group (name already exists)
到目前为止我尝试过的事情:
tf 1.14.0 也会出现错误 在有问题的代码部分周围添加named_scope
也无济于事:with tf.name_scope('something' + str(step)):
明确命名tf.reshape
操作没有帮助:outputs = tf.reshape(..., name='custom_reshape1_' + str(step))
该错误可以在 Google Colab 中重现
这不是权重文件的问题,因为我在运行代码之前删除了所有数据。此外,在删除有问题的 tensorflow 代码时,该代码可以正常工作
import tensorflow as tf
print('version=', tf.__version__)
import numpy as np
keras = tf.keras # pylint: disable=no-member
KL = keras.layers
KM = keras.models
K = keras.backend
KR = keras.regularizers
# GRU = tf.compat.v1.keras.layers.CuDNNGRU
GRU = KL.GRU
n_in = 20
n_out = 10
dim = 128
hidden_units = 1024
encoder_inputs = KL.Input(shape=(n_in, dim))
encoder = GRU(hidden_units,
return_state=True)
_, state_h = encoder(encoder_inputs)
decoder_gru = GRU(hidden_units,
return_sequences=True,
return_state=True)
decoder_dense = KL.Dense(dim)
last_pose = KL.Lambda(lambda a: a[:, -1, :],
output_shape=(None, dim))(encoder_inputs)
last_pose = KL.Reshape((1, dim))(last_pose)
all_outputs = []
inputs = last_pose
for step in range(n_out):
outputs, state_h = decoder_gru(inputs, initial_state=state_h)
outputs = decoder_dense(outputs)
# ~~~~~~~~~~~~~~~~~~~~~~~~ comment out to "fix" issue
# -- problem cause (start)
n_batch = tf.shape(outputs)[0]
outputs = tf.reshape(outputs, (n_batch * 32, 4))
# ... custom function stuff
outputs = tf.reshape(outputs, (n_batch, 1, 32*4))
# -- problem cause (end)
# ~~~~~~~~~~~~~~~~~~~~~~~~
all_outputs.append(outputs)
inputs = outputs
decoder_outputs = KL.Concatenate()(all_outputs)
decoder_outputs = KL.Reshape((n_out, dim))(decoder_outputs)
model = KM.Model(inputs=encoder_inputs,
outputs=decoder_outputs)
model = KM.Model(inputs=encoder_inputs, outputs=state_h)
model.compile(loss='MSE', optimizer='adam')
model.save_weights('/tmp/dummy.h5')
print('saved')
我不确定出了什么问题,我希望能够节省重量!该模型可以被训练并且它的损失正在减少,仅存储权重会导致问题。
【问题讨论】:
文件 /tmp/dummy.h5 是否已经存在?如果文件已存在,则保存模型可能会出现问题。在运行此代码之前尝试将其删除。 @MatiasValdenegro 感谢您的意见。在构建模型之前,我已经清除了所有创建的数据。我将更新“尝试过的东西”部分。另外:删除有问题的 tf 代码后,代码可以正常工作! 您是否尝试为所有 keras 图层添加名称?我知道这不是问题的核心,但它确实创建了一些名称范围(只是一种尝试)。 【参考方案1】:看来tf.shape
电话是罪魁祸首。在没有它的情况下重新编写代码允许模型按预期存储。我仍然很好奇为什么会发生这种情况..
import tensorflow as tf
print('version=', tf.__version__)
import numpy as np
keras = tf.keras # pylint: disable=no-member
KL = keras.layers
KM = keras.models
K = keras.backend
KR = keras.regularizers
# GRU = tf.compat.v1.keras.layers.CuDNNGRU
GRU = KL.GRU
n_in = 20
n_out = 10
dim = 128
hidden_units = 1024
encoder_inputs = KL.Input(shape=(n_in, dim))
encoder = GRU(hidden_units,
return_state=True)
_, state_h = encoder(encoder_inputs)
decoder_gru = GRU(hidden_units,
return_sequences=True,
return_state=True)
decoder_dense = KL.Dense(dim)
last_pose = KL.Lambda(lambda a: a[:, -1, :],
output_shape=(None, dim))(encoder_inputs)
last_pose = KL.Reshape((1, dim))(last_pose)
all_outputs = []
inputs = last_pose
for step in range(n_out):
outputs, state_h = decoder_gru(inputs, initial_state=state_h)
outputs = decoder_dense(outputs)
# ~~~~~~~~~~~~~~~~~~~~~~~~ comment out to "fix" issue
# -- problem cause (start)
# n_batch = tf.shape(outputs)[0]
outputs = tf.reshape(outputs, (-1, 4))
# ... custom function stuff
outputs = tf.reshape(outputs, (-1, 1, 32*4))
# -- problem cause (end)
# ~~~~~~~~~~~~~~~~~~~~~~~~
all_outputs.append(outputs)
inputs = outputs
decoder_outputs = KL.Concatenate()(all_outputs)
decoder_outputs = KL.Reshape((n_out, dim))(decoder_outputs)
model = KM.Model(inputs=encoder_inputs,
outputs=decoder_outputs)
model = KM.Model(inputs=encoder_inputs, outputs=state_h)
model.compile(loss='MSE', optimizer='adam')
model.save_weights('/tmp/dummy.h5')
print('saved')
【讨论】:
以上是关于tf2.0 Keras:使用 RNN 的自定义张量流代码时无法保存权重的主要内容,如果未能解决你的问题,请参考以下文章
什么是使用Keras的RNN Layer的return_state输出
访问在 TF 2.0 中未显式公开为层的 Keras 模型的中间张量
如何在 Keras 中为循环神经网络 (RNN) 使用嵌入层