自定义BahdanauAttention层时Keras load_model报W1参数错误
解决自定义BahdanauAttention层加载失败的问题
这个错误的根源出在你的get_config方法上——你把已经创建的子层W1、W2、V直接加入了配置字典,但Keras在加载模型时,会把这些配置键当作自定义层__init__方法的参数来传递,而你的__init__根本没有接收W1这类参数,自然就会抛出"Keyword argument not understood"的错误。
正确的做法是:get_config只需要保存创建自定义层时必须的初始化参数,也就是你的output_dim,内部的子层(比如Dense层)Keras会自动帮你序列化和加载,不需要手动处理。
修改后的BahdanauAttention层代码如下:
class BahdanauAttention(layers.Layer): def __init__(self, output_dim=30, **kwargs): super(BahdanauAttention, self).__init__(**kwargs) self.output_dim = output_dim # 先把参数存为实例属性 self.W1 = tf.keras.layers.Dense(output_dim) self.W2 = tf.keras.layers.Dense(output_dim) self.V = tf.keras.layers.Dense(1) def call(self, inputs, **kwargs): query = inputs[0] values = inputs[1] query_with_time_axis = tf.expand_dims(query, 1) score = self.V(tf.nn.tanh( self.W1(query_with_time_axis) + self.W2(values))) attention_weights = tf.nn.softmax(score, axis=1) context_vector = attention_weights * values context_vector = tf.reduce_sum(context_vector, axis=1) return context_vector, attention_weights def get_config(self): config = super(BahdanauAttention, self).get_config() # 只保存初始化时需要的参数,而不是子层实例 config.update({ 'output_dim': self.output_dim, }) return config
为什么这样修改就能解决问题?
- 当Keras加载模型时,会先通过
get_config拿到的配置参数,调用BahdanauAttention(**config)创建层实例,这时候output_dim是__init__能识别的参数,不会报错。 - 层内部的
W1、W2、V这些子层的权重会被Keras自动序列化到模型文件中,创建完层实例后,Keras会自动把这些权重加载回来,不需要你手动在get_config里处理。
之后你原来的保存和加载代码可以继续使用,不需要额外修改:
# 保存模型(原有代码不变) path = os.path.join(self.dir, 'model_{}'.format(self.timestamp)) callbacks.append(ModelCheckpoint(path, save_best_only=True, monitor='val_loss', mode='min')) # 加载模型(原有代码不变) self.model = load_model(path, custom_objects={'BahdanauAttention': BahdanauAttention, 'custom_loss': self.custom_loss})
这样修改后,模型就能正常保存和加载了。
内容的提问来源于stack exchange,提问作者bcsta
相关产品推荐
相关产品推荐

