Keras自定义Attention层报错:add_weight()参数name重复赋值
解决TensorFlow 2.2.0 + Keras 2.4.3中自定义Attention层的
TypeError: add_weight() got multiple values for argument 'name'错误 你猜的没错,这个问题确实是版本兼容差异导致的。你用的是旧版独立Keras的自定义层写法(继承keras.engine.topology.Layer),但TensorFlow 2.x集成的Keras(也就是你当前环境里的Keras 2.4.3,它和TF 2.2.0绑定)在add_weight方法的参数顺序上和旧版独立Keras完全不同,直接沿用旧代码就会触发参数冲突错误。
解决方案:适配TF 2.x的tf.keras API修改自定义Attention层
下面是修改后的可运行代码,我会标注关键改动点:
# 关键改动1:改用tf.keras的API导入,而非旧版keras.engine.topology from tensorflow.keras import backend as K from tensorflow.keras.layers import Layer, Dense, Input, LSTM, Bidirectional, Activation, Conv1D, GRU, TimeDistributed from tensorflow.keras.layers import Dropout, Embedding, GlobalMaxPooling1D, MaxPooling1D, Add, Flatten, SpatialDropout1D from tensorflow.keras.layers import GlobalAveragePooling1D, BatchNormalization, concatenate from tensorflow.keras.layers import Reshape, Concatenate, Lambda, Average from tensorflow.keras.models import Sequential, Model from tensorflow.keras.initializers import Constant, glorot_uniform from tensorflow.keras.regularizers import get as get_regularizer from tensorflow.keras.constraints import get as get_constraint class Attention(Layer): def __init__(self, step_dim, W_regularizer=None, b_regularizer=None, W_constraint=None, b_constraint=None, bias=True, **kwargs): self.supports_masking = True self.init = glorot_uniform() # 直接调用初始化器,而非通过get方法(可选,但更符合TF 2.x风格) self.W_regularizer = get_regularizer(W_regularizer) self.b_regularizer = get_regularizer(b_regularizer) self.W_constraint = get_constraint(W_constraint) self.b_constraint = get_constraint(b_constraint) self.bias = bias self.step_dim = step_dim self.features_dim = 0 super(Attention, self).__init__(**kwargs) def build(self, input_shape): assert len(input_shape) == 3 # 关键改动2:TF 2.x的add_weight第一个参数是name,形状通过shape参数传递 self.W = self.add_weight( name='{}_W'.format(self.name), shape=(input_shape[-1],), initializer=self.init, regularizer=self.W_regularizer, constraint=self.W_constraint ) self.features_dim = input_shape[-1] if self.bias: self.b = self.add_weight( name='{}_b'.format(self.name), shape=(input_shape[1],), initializer='zero', regularizer=self.b_regularizer, constraint=self.b_constraint ) else: self.b = None self.built = True def compute_mask(self, input, input_mask=None): return None def call(self, x, mask=None): features_dim = self.features_dim step_dim = self.step_dim eij = K.reshape(K.dot(K.reshape(x, (-1, features_dim)), K.reshape(self.W, (features_dim, 1))), (-1, step_dim)) if self.bias: eij += self.b eij = K.tanh(eij) a = K.exp(eij) if mask is not None: a *= K.cast(mask, K.floatx()) a /= K.cast(K.sum(a, axis=1, keepdims=True) + K.epsilon(), K.floatx()) a = K.expand_dims(a) weighted_input = x * a return K.sum(weighted_input, axis=1) def compute_output_shape(self, input_shape): return input_shape[0], self.features_dim
模型构建部分可以保持不变(注意确保embedding_layer已经正确定义):
# 假设你已经定义了embedding_layer lstm_layer = LSTM(300, dropout=0.25, recurrent_dropout=0.25, return_sequences=True) inp = Input(shape=(maxlen,), dtype='int32') embedding = embedding_layer(inp) x = lstm_layer(embedding) x = Dropout(0.25)(x) merged = Attention(maxlen)(x) merged = Dense(256, activation='relu')(merged) merged = Dropout(0.25)(merged) merged = BatchNormalization()(merged) outp = Dense(len(int_category), activation='softmax')(merged) AttentionLSTM = Model(inputs=inp, outputs=outp) AttentionLSTM.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc']) AttentionLSTM.summary()
错误原因详解
在旧版独立Keras(比如Keras 2.3.x及更早)中,add_weight的参数顺序是:
add_weight(shape, initializer, name=None, regularizer=None, constraint=None, ...)
但在TensorFlow 2.x集成的tf.keras中,add_weight的参数顺序被调整为:
add_weight(name=None, shape=None, initializer='glorot_uniform', regularizer=None, constraint=None, ...)
你原来的代码把shape作为第一个参数传递,同时又显式指定了name参数,这就导致了参数冲突——TF认为你同时通过位置参数和关键字参数传递了name,所以抛出TypeError: add_weight() got multiple values for argument 'name'。
内容的提问来源于stack exchange,提问作者Deshwal
相关产品推荐
相关产品推荐

