0
votes

add_weight () a obtenu plusieurs valeurs pour l'argument 'nom' tout en utilisant une attention personnalisée (couche) dans Keras

(Je pense que c'est à cause du conflit de version car les auteurs ont utilisé keras.engine.topology.Layer )

Avec tensorflow == 2.2.0 et keras == 2.4.3 , j'essaie d'apprendre le mécanisme d'attention et j'ai importé le code de quelque part comme:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-25-1ab1f1ef1ed7> in <module>
      5 x = lstm_layer(embedding)
      6 x = Dropout(0.25)(x)
----> 7 merged = Attention(maxlen)(x)
      8 merged = Dense(256, activation='relu')(merged)
      9 merged = Dropout(0.25)(merged)

/opt/conda/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py in __call__(self, *args, **kwargs)
    895           # Build layer if applicable (if the `build` method has been
    896           # overridden).
--> 897           self._maybe_build(inputs)
    898           cast_inputs = self._maybe_cast_inputs(inputs)
    899 

/opt/conda/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py in _maybe_build(self, inputs)
   2414         # operations.
   2415         with tf_utils.maybe_init_scope(self):
-> 2416           self.build(input_shapes)  # pylint:disable=not-callable
   2417       # We must set also ensure that the layer is marked as built, and the build
   2418       # shape is stored since user defined build functions may not be calling

<ipython-input-20-86a01469b2e5> in build(self, input_shape)
     23                                  name='{}_W'.format(self.name),
     24                                  regularizer=self.W_regularizer,
---> 25                                  constraint=self.W_constraint)
     26         self.features_dim = input_shape[-1]
     27         if self.bias:

TypeError: add_weight() got multiple values for argument 'name'

Le problème est quand j'essaye d'utiliser,

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()

il renvoie une erreur comme TypeError: add_weight () a obtenu plusieurs valeurs pour l'argument 'nom'

Le traçage complet de l'erreur est:

from keras import backend as K
from keras.engine.topology import Layer
from keras import initializers, regularizers, constraints

from keras.layers import Dense, Input, LSTM, Bidirectional, Activation, Conv1D, GRU, TimeDistributed
from keras.layers import Dropout, Embedding, GlobalMaxPooling1D, MaxPooling1D, Add, Flatten, SpatialDropout1D
from keras.layers import GlobalAveragePooling1D, BatchNormalization, concatenate
from keras.layers import Reshape, merge, Concatenate, Lambda, Average
from keras.models import Sequential, Model
from keras.initializers import Constant
from keras.layers.merge import add


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 = initializers.get('glorot_uniform')
        self.W_regularizer = regularizers.get(W_regularizer)
        self.b_regularizer = regularizers.get(b_regularizer)
        self.W_constraint = constraints.get(W_constraint)
        self.b_constraint = constraints.get(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
        self.W = self.add_weight((input_shape[-1],),
                                 initializer=self.init,
                                 name='{}_W'.format(self.name),
                                 regularizer=self.W_regularizer,
                                 constraint=self.W_constraint)
        self.features_dim = input_shape[-1]
        if self.bias:
            self.b = self.add_weight((input_shape[1],),
                                     initializer='zero',
                                     name='{}_b'.format(self.name),
                                     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


2 commentaires

J'ai le même problème sur TF version 2.2.0 et Keras 2.3.1


Avez-vous trouvé une solution pour résoudre ce problème?


4 Réponses :


1
votes

Le problème vient car la fonction add_weight prend la valeur des tuples de forme. Essayez d'écrire " shape = shape (YOUR INPUT)". Cela devrait résoudre le problème.


3 commentaires

Bonjour Jayesh, ce n'est pas une information très utile. Pourriez-vous s'il vous plaît rapporter le code ci-dessus avec les modules appropriés importés et le "shape = shape (input)" correctement placé dans votre version? Cela nous aiderait beaucoup plus. Bienvenue dans la communauté.


Désolé pour la confusion, mais je pense que vous avez déjà examiné cette question et y avez parfaitement répondu.


Ouais Jayesh, j'ai en fait utilisé une partie de votre réponse. :)



1
votes

J'ai partiellement résolu le problème. Au moins pour la partie add_weight ():

  • Étape 1: Remplacez la classe Attention (Layer) -> class Attention (keras.layers.Layer)
  • Étape 2: Ajouter shape = (...) à l'intérieur des méthodes add_weights

Voir ci-dessous,

from keras import backend as K
from keras.engine.topology import Layer
from keras import initializers, regularizers, constraints

from keras.layers import Dense, Input, LSTM, Bidirectional, Activation, Conv1D, GRU, TimeDistributed
from keras.layers import Dropout, Embedding, GlobalMaxPooling1D, MaxPooling1D, Add, Flatten, SpatialDropout1D
from keras.layers import GlobalAveragePooling1D, BatchNormalization, concatenate
from keras.layers import Reshape, merge, Concatenate, Lambda, Average
from keras.models import Sequential, Model
from keras.initializers import Constant
from keras.layers.merge import add


class Attention(keras.layers.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 = initializers.get('glorot_uniform')
        self.W_regularizer = regularizers.get(W_regularizer)
        self.b_regularizer = regularizers.get(b_regularizer)
        self.W_constraint = constraints.get(W_constraint)
        self.b_constraint = constraints.get(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
        self.W = self.add_weight(shape=(input_shape[-1],),
                                 name='{}_W'.format(self.name),
                                 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((input_shape[1],),
                                     name='{}_b'.format(self.name),
                                     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

En apportant les modifications ci-dessus, j'obtiens les sorties suivantes:

  • Je reçois un avertissement de Tensorflow
    "WARNING:tensorflow:Model failed to serialize as JSON. Ignoring... Layer AttentionWithContext has arguments in `__init__` and therefore must override `get_config`".

  • Lorsque j'essaie d'évaluer l'algorithme sur l'ensemble de données de test, j'obtiens l'erreur suivante:

entrez la description de l'image ici

Je ne sais pas comment résoudre ces deux problèmes, donc je publierai probablement une question différente parce qu'elle sort du cadre de celle-ci.


3 commentaires

Je pense que cela est dû à un conflit de version. Veuillez partager une fois que vous l'aurez découvert. J'ai essayé de le faire et j'ai échoué car en raison du changement de version, le flux de travail a changé.


@Deshwal vous parlez de la dernière erreur? de la fonction de test?


Lorsque vous modifiez la structure comme vous l'avez fait, une nouvelle erreur générera de temps en temps à cause du flux de travail modifié de 1.15 à 2.0



0
votes

J'ai eu le même problème et j'ai changé d'environnement. mon venv comme suit:

absl-py==0.11.0
astor==0.8.1
cached-property==1.5.2
certifi==2020.6.20
click==7.1.2
cycler==0.10.0
gast==0.4.0
google-pasta==0.2.0
grpcio==1.33.2
h5py==3.0.0
importlib-metadata==2.0.0
joblib==0.17.0
Keras==2.2.4
Keras-Applications==1.0.8
Keras-Preprocessing==1.1.2
kiwisolver==1.3.1
Markdown==3.3.3
matplotlib==3.3.2
nltk==3.5
numpy==1.18.1
pandas==0.25.3
Pillow==8.0.1
protobuf==3.13.0
pyparsing==2.4.7
python-dateutil==2.8.1
pytz==2020.4
PyYAML==5.3.1
regex==2020.10.28
scikit-learn==0.23.2
scipy==1.5.4
six==1.15.0
sklearn==0.0
tensorboard==1.14.0
tensorflow==1.14.0
tensorflow-estimator==1.14.0
termcolor==1.1.0
threadpoolctl==2.1.0
tqdm==4.51.0
Werkzeug==1.0.1
wrapt==1.12.1
zipp==3.4.0


0 commentaires

0
votes

La méthode add_weights est appelée trois fois dans le code, essayez de la corriger avec 'shape ='.


0 commentaires