Was ist eine Einbettung in Keras?

97

Die Keras-Dokumentation ist nicht klar, was dies tatsächlich ist. Ich verstehe, dass wir dies verwenden können, um den Eingabe-Feature-Bereich in einen kleineren zu komprimieren. Aber wie geht das aus neuronaler Sicht? Ist es ein Autoenocder, RBM?


quelle
7
Es ist eine Nachschlagetabelle, die trainiert werden kann
gokul_uf
1
Es wird einfach eine Gewichtsmatrix erstellt und indiziert. Siehe meine ausführliche Antwort unten ( stackoverflow.com/a/53101566/9024698 ).
Ausgestoßener
3
Obwohl die am häufigsten gewählte Antwort besagt, dass es sich um eine Matrixmultiplikation handelt, zeigen der Quellcode und andere Antworten, dass es sich tatsächlich nur um eine trainierbare Matrix handelt. Die Eingabewörter wählen einfach die entsprechende Zeile in dieser Matrix aus.
Daniel Möller

Antworten:

66

Soweit ich weiß, ist die Einbettungsschicht eine einfache Matrixmultiplikation, die Wörter in ihre entsprechenden Worteinbettungen umwandelt.

Die Gewichte der Einbettungsebene haben die Form (Vokabulargröße, Einbettungsdimension). Für jedes Trainingsmuster sind seine Eingaben Ganzzahlen, die bestimmte Wörter darstellen. Die ganzen Zahlen liegen im Bereich der Vokabulargröße. Die Einbettungsschicht transformiert jede ganze Zahl i in die i-te Zeile der Einbettungsgewichtungsmatrix.

Um dies schnell als Matrixmultiplikation zu tun, werden die Eingabe-Ganzzahlen nicht als Liste von Ganzzahlen, sondern als One-Hot-Matrix gespeichert. Daher ist die Eingabeform (nb_words, vocabulary_size) mit einem Wert ungleich Null pro Zeile. Wenn Sie dies mit den Einbettungsgewichten multiplizieren, erhalten Sie die Ausgabe in der Form

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

Mit einer einfachen Matrixmultiplikation transformieren Sie also alle Wörter in einem Beispiel in die entsprechenden Worteinbettungen.

Lorrit
quelle
3
Auf jeden Fall ein gültiger Ansatz (siehe Semi-Supervised Sequence Learning ). Sie können die Einbettungen auch mit einem Autoencoder lernen und sie dann als Initialisierung der Einbettungsschicht verwenden, um die Komplexität Ihres neuronalen Netzwerks zu verringern (ich gehe davon aus, dass Sie nach der Einbettungsschicht etwas anderes tun).
Lorrit
3
Hier ist ein schöner Blogpost über Worteinbettungen und ihre Vorteile.
Sietschie
3
In dem Fall, den ich vorgestellt habe, besteht jede Trainingseingabe aus einer Reihe von Wörtern (kann ein Satz sein). Jedes Wort wird als One-Hot-Vektor dargestellt und in einen dichten Vektor eingebettet. Der Nachteil dieses Ansatzes besteht darin, dass alle Ihre Sätze die gleiche Anzahl von Wörtern haben müssen, da die Eingabe von konstanter Länge sein muss. Eine Alternative wären Absatzvektoren , die Sätze, Absätze oder sogar Dokumente in Vektoren einbetten können.
Lorrit
4
Die Einbettungsschicht optimiert nur ihre Gewichte, um den Verlust zu minimieren. Vielleicht bedeutet das, dass die semantische Ähnlichkeit berücksichtigt wird, vielleicht auch nicht. Man weiß nie mit neuronalen Netzen. Wenn Sie sicherstellen möchten, dass die Einbettung einer bestimmten Formel folgt (z. B. w2v), verwenden Sie die Formel. Wenn Sie über genügend Daten verfügen, können Sie die Einbettungsebene verwenden und die Einbettungen trainieren. Probieren Sie es einfach aus und prüfen Sie, ob Ihnen die Ergebnisse gefallen.
Lorrit
2
Ich stimme user36624 zu (Antwort unten). Es ist KEINE einfache Matrixmultiplikation.
Daniel Möller
21

Die Keras EmbeddingSchicht führt keine Matrixmultiplikation durch, sondern nur:

1. Erstellt eine Gewichtsmatrix mit (Vokabulargröße) x (Einbettungsdimension) Dimensionen

2. indiziert diese Gewichtsmatrix


Es ist immer nützlich, einen Blick auf den Quellcode zu werfen, um zu verstehen, was eine Klasse tut. In diesem Fall sehen wir uns die class Einbettung an, die von der Basisschicht classnamens Layer erbt .

(1) - Erstellen einer Gewichtsmatrix mit (Vokabulargröße) x (Einbettungsdimension) Dimensionen:

Dies geschieht bei der buildFunktion des Einbetten :

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

Wenn Sie sich die Basisklasse Layer ansehen, werden Sie sehen, dass die add_weightobige Funktion einfach eine Matrix trainierbarer Gewichte erstellt (in diesem Fall von (vocabulary_size) x (embeddedding_dimension) Dimensionen):

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) - Indizierung dieser Gewichtsmatrix

Dies geschieht bei der callFunktion des Einbetten :

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

Diese Funktion gibt die Ausgabe der EmbeddingEbene zurück, die ist K.gather(self.embeddings, inputs). Was tf.keras.backend.gather genau tut, ist die Indizierung der Gewichtungsmatrix self.embeddings(siehe buildFunktion oben) gemäß der inputsListe der positiven ganzen Zahlen.

Diese Listen können beispielsweise abgerufen werden, wenn Sie Ihre Text- / Worteingaben an die one_hot- Funktion von Keras übergeben, die einen Text in eine Liste von Wortindizes der Größe n codiert (dies ist KEINE Hot-Codierung - siehe auch dieses Beispiel für weitere Informationen: https://machinelearningmastery.com/use-word-embedding-layers-deep-learning-keras/ ).


Das ist also alles. Es gibt keine Matrixmultiplikation.

Im Gegenteil, die Keras EmbeddingSchicht ist nur deshalb nützlich, weil sie genau die Durchführung einer Matrixmultiplikation vermeidet und daher einige Rechenressourcen spart.

Andernfalls können Sie einfach eine Keras dichte Ebene verwenden (nachdem Sie Ihre Eingabedaten codiert haben), um eine Matrix trainierbarer Gewichte (mit (Vokabulargröße) x (Einbettungsdimension) Dimensionen zu erhalten) und dann einfach die Multiplikation durchführen, um die Ausgabe zu erhalten, die genau ist das gleiche mit der Ausgabe der EmbeddingEbene.

Ausgestoßene
quelle
5

Um eine Funktion besser zu verstehen, ist es eine gute Angewohnheit, sich den Quellcode anzusehen. Hier ist für das Einbetten. Im Grunde ist es also ein trainierbarer Nachschlagetisch.

Andrey Nikishaev
quelle
4

In Keras ist die EmbeddingEbene KEINE einfache Matrixmultiplikationsschicht, sondern eine Nachschlagetabellenebene (siehe Aufruffunktion unten oder die ursprüngliche Definition ).

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

Was sie tut , ist jeweils eine bekannte ganze Zahl ist zur Karte nin inputszu einem trainierbar Merkmalsvektor W[n], deren Dimension ist die sogenannte eingebettete Feature - Länge.

Falle
quelle
Wenn Sie einen mit einer heißen Darstellung dargestellten Satz von Vektoren mit einer Matrix multiplizieren, wird das Produkt zu einer Suche. Die EmbeddingSchicht ist also tatsächlich eine Matrixmultiplikation.
Yannis
Nur dass Keras nirgends diese Multiplikation durchführen. Es definiert lediglich "Einbettungen = eine trainierbare Matrix" und verwendet die Eingabeindizes, um Wörter aus der Matrix zu sammeln.
Daniel Möller
Somit spart diese Einbettung viel Speicher, indem einfach keine One-Hot-Version der Eingaben erstellt wird.
Daniel Möller
1

In einfachen Worten (aus Sicht der Funktionalität) handelt es sich um einen One-Hot-Encoder und eine vollständig verbundene Schicht . Die Schichtgewichte sind trainierbar.

Ali Mirzaei
quelle