You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:33:13