Qu'est-ce qu'une intégration dans Keras?

97

La documentation Keras n'est pas claire de quoi il s'agit. Je comprends que nous pouvons l'utiliser pour compresser l'espace des fonctionnalités d'entrée dans un espace plus petit. Mais comment cela se fait-il du point de vue de la conception neuronale? Est-ce un autoenocder, RBM?


la source
7
C'est une table de consultation qui peut être entraînée
gokul_uf
1
Il crée et indexe simplement une matrice de poids; voir ma réponse détaillée ci-dessous ( stackoverflow.com/a/53101566/9024698 ).
Paria
3
Bien que la réponse la plus votée dise qu'il s'agit d'une multiplication matricielle, le code source et d'autres réponses montrent qu'en fait ce ne sont qu'une matrice entraînable. Les mots d'entrée choisissent simplement la ligne respective dans cette matrice.
Daniel Möller

Réponses:

66

Autant que je sache, la couche Embedding est une simple multiplication matricielle qui transforme les mots en leurs embeddings de mots correspondants.

Les poids de la couche Embedding sont de la forme (vocabulary_size, embedding_dimension). Pour chaque échantillon d'apprentissage, ses entrées sont des entiers, qui représentent certains mots. Les nombres entiers sont dans la plage de la taille du vocabulaire. La couche Embedding transforme chaque entier i en la ième ligne de la matrice des poids d'incorporation.

Afin d'effectuer rapidement cette opération sous forme de multiplication matricielle, les entiers d'entrée ne sont pas stockés sous forme de liste d'entiers mais sous forme de matrice à un instantané. Par conséquent, la forme d'entrée est (nb_words, vocabulary_size) avec une valeur non nulle par ligne. Si vous multipliez cela par les poids d'incorporation, vous obtenez la sortie sous la forme

(nb_words, vocab_size) x (vocab_size, embedding_dim) = (nb_words, embedding_dim)

Ainsi, avec une simple multiplication matricielle, vous transformez tous les mots d'un échantillon dans les embeddings de mots correspondants.

Lorrit
la source
3
Certainement une approche valide (voir Apprentissage de séquence semi-supervisé ). Vous pouvez également apprendre les embeddings avec un auto-encodeur, puis les utiliser comme initialisation de la couche Embedding pour réduire la complexité de votre réseau neuronal (je suppose que vous faites autre chose après la couche Embedding).
Lorrit
3
Voici un joli article de blog sur les intégrations de mots et leurs avantages.
sietschie
3
Dans le cas que j'ai présenté, chaque entrée de formation est un ensemble de mots (peut être une phrase). Chaque mot est représenté comme un vecteur unique et intégré dans un vecteur dense. L'inconvénient de cette approche est que, puisque l'entrée doit être de longueur constante, toutes vos phrases doivent avoir le même nombre de mots. Une alternative serait les vecteurs de paragraphe , qui peuvent incorporer des phrases, des paragraphes ou même des documents dans des vecteurs.
Lorrit
4
La couche Embedding optimisera simplement ses poids afin de minimiser la perte. Peut-être que cela signifie qu'il prendra en compte la similitude sémantique, peut-être que ce ne sera pas le cas. On ne sait jamais avec les réseaux de neurones. Si vous voulez être sûr que l'incorporation suit une certaine formule (par exemple w2v), utilisez la formule. Si vous disposez de suffisamment de données, vous pouvez utiliser le calque Incorporation et entraîner les incorporations. Essayez-le et vérifiez si vous aimez les résultats.
Lorrit
2
Je suis d'accord avec user36624 (réponse ci-dessous). Ce n'est PAS une simple multiplication matricielle.
Daniel Möller
21

La Keras Embeddingcouche n'effectue aucune multiplication matricielle mais seulement:

1. crée une matrice de poids de (vocabulary_size) x (embedding_dimension) dimensions

2. indexe cette matrice de poids


Il est toujours utile de jeter un œil au code source pour comprendre ce que fait une classe. Dans ce cas, nous allons jeter un œil à l' class incorporation qui hérite de la couche de base classappelée Layer .

(1) - Création d'une matrice de poids de dimensions (vocabulary_size) x (embedding_dimension) :

Cela se produit au niveau de la buildfonction d' incorporation :

def build(self, input_shape):
    self.embeddings = self.add_weight(
        shape=(self.input_dim, self.output_dim),
        initializer=self.embeddings_initializer,
        name='embeddings',
        regularizer=self.embeddings_regularizer,
        constraint=self.embeddings_constraint,
        dtype=self.dtype)
    self.built = True

Si vous regardez la classe de base Layer, vous verrez que la fonction add_weightci-dessus crée simplement une matrice de poids entraînables (dans ce cas de dimensions (vocabulary_size) x (embedding_dimension) ):

def add_weight(self,
               name,
               shape,
               dtype=None,
               initializer=None,
               regularizer=None,
               trainable=True,
               constraint=None):
    """Adds a weight variable to the layer.
    # Arguments
        name: String, the name for the weight variable.
        shape: The shape tuple of the weight.
        dtype: The dtype of the weight.
        initializer: An Initializer instance (callable).
        regularizer: An optional Regularizer instance.
        trainable: A boolean, whether the weight should
            be trained via backprop or not (assuming
            that the layer itself is also trainable).
        constraint: An optional Constraint instance.
    # Returns
        The created weight variable.
    """
    initializer = initializers.get(initializer)
    if dtype is None:
        dtype = K.floatx()
    weight = K.variable(initializer(shape),
                        dtype=dtype,
                        name=name,
                        constraint=constraint)
    if regularizer is not None:
        with K.name_scope('weight_regularizer'):
            self.add_loss(regularizer(weight))
    if trainable:
        self._trainable_weights.append(weight)
    else:
        self._non_trainable_weights.append(weight)
    return weight

(2) - Indexation de cette matrice de poids

Cela se produit au niveau de la callfonction d' incorporation :

def call(self, inputs):
    if K.dtype(inputs) != 'int32':
        inputs = K.cast(inputs, 'int32')
    out = K.gather(self.embeddings, inputs)
    return out

Cette fonction renvoie la sortie de la Embeddingcouche qui est K.gather(self.embeddings, inputs). Ce que fait exactement tf.keras.backend.gather est d'indexer la matrice de poids self.embeddings(voir la buildfonction ci-dessus) en fonction de ce inputsqui devrait être des listes d'entiers positifs.

Ces listes peuvent être récupérées par exemple si vous passez vos entrées texte / mots à la fonction one_hot de Keras qui encode un texte dans une liste d'index de mots de taille n (ce n'est PAS un encodage à chaud - voir aussi cet exemple pour plus d'informations: https://machinelearningmastery.com/use-word-embedding-layers-deep-learning-keras/ ).


Par conséquent, c'est tout. Il n'y a pas de multiplication matricielle.

Au contraire, la Keras Embeddingcouche n'est utile que parce qu'elle évite justement d'effectuer une multiplication matricielle et donc elle économise certaines ressources de calcul.

Sinon, vous pouvez simplement utiliser une couche Keras dense (après avoir encodé vos données d'entrée) pour obtenir une matrice de poids pouvant être entraînés (de dimensions (vocabulary_size) x (embedding_dimension) ) et ensuite simplement faire la multiplication pour obtenir la sortie qui sera exactement la même chose avec la sortie de la Embeddingcouche.

Banni
la source
5

Pour mieux comprendre une fonction, c'est une bonne habitude de regarder le code source. Voici pour l' intégration Donc, fondamentalement, c'est une table de consultation entraînable.

Andrey Nikishaev
la source
4

Dans Keras, la Embeddingcouche n'est PAS une simple couche de multiplication matricielle, mais une couche de table de consultation (voir la fonction d'appel ci-dessous ou la définition d' origine ).

def call(self, inputs):
    if K.dtype(inputs) != 'int32':
        inputs = K.cast(inputs, 'int32')
    out = K.gather(self.embeddings, inputs)
    return out

Ce qu'il fait est de cartographier chacun un nombre entier connu ndans inputsun vecteur de caractéristique trainable W[n], dont la dimension est la longueur de fonction intégrée que l' on appelle.

piège
la source
Eh bien, lorsque vous multipliez un ensemble de vecteurs représentés à chaud avec une matrice, le produit devient une recherche. La Embeddingcouche est donc bien une multiplication matricielle.
yannis
Sauf que nulle part keras n'effectue cette multiplication. Il définit simplement "embeddings = a trainable matrix" et utilise les indices d'entrée pour rassembler les mots de la matrice.
Daniel Möller
Ainsi, cette intégration économise beaucoup de mémoire en ne créant simplement aucune version unique des entrées.
Daniel Möller
1

En termes simples (du point de vue de la fonctionnalité), il s'agit d'un encodeur unique et d' une couche entièrement connectée . Les poids des couches peuvent être entraînés.

Ali Mirzaei
la source