it-swarm.com.de

Hinzufügen neuer Einbettungen für unbekannte Wörter in Tensorflow (Training & Voreinstellung zum Testen)

Ich bin neugierig, wie ich einen normal-randomisierten 300-Dimensionsvektor (elements 'type = tf.float32) hinzufügen kann, wenn ein Wort gefunden wird, das dem zuvor trainierten Vokabular nicht bekannt ist. Ich verwende vorgelernte GloVe Word-Einbettungen, aber in manchen Fällen stelle ich fest, dass ich unbekannten Wörtern begegne, und ich möchte einen normal-randomisierten Word-Vektor für dieses neu gefundene unbekannte Wort erstellen. 

Das Problem ist, dass ich mit meinem aktuellen Setup tf.contrib.lookup.index_table_from_tensor verwende, um Wörter basierend auf dem bekannten Vokabular in Ganzzahlen zu konvertieren. Diese Funktion kann neue Token erstellen und sie für eine bestimmte Anzahl von Wörtern aus Vokabeln verwenden, aber meine embed enthält keine Einbettung für diesen neuen unbekannten Hashwert. Ich bin mir nicht sicher, ob ich einfach eine randomisierte Einbettung an das Ende der embed-Liste anhängen kann.

Ich möchte dies auch auf eine effiziente Art und Weise tun, so dass wahrscheinlich eine vorgefertigte Tensorflow-Funktion oder -Verfahren mit Tensorflow-Funktionen am effizientesten wäre. Ich definiere vorbekannte spezielle Token wie ein Satzende-Token und einen Standard-Unbekannten als leere Zeichenfolge ("am Index 0"), aber dies ist in seiner Fähigkeit begrenzt, für verschiedene verschiedene unbekannte Wörter zu lernen. Ich benutze derzeit tf .nn.embedding_lookup () als abschließender Einbettungsschritt.

Ich möchte in der Lage sein, neue zufällige 300d-Vektoren für jedes unbekannte Wort in den Trainingsdaten hinzuzufügen, und ich möchte auch vorgefertigte zufällige Wortvektoren für unbekannte Token hinzufügen, die nicht im Training zu sehen sind und möglicherweise während des Testens angetroffen werden. Was ist der effizienteste Weg, dies zu tun?

def embed_tensor(string_tensor, trainable=True):
    """    
    Convert List of strings into list of indicies then into 300d vectors
    """
    # ordered lists of vocab and corresponding (by index) 300d vector
    vocab, embed = load_pretrained_glove()

    # Set up tensorflow look up from string Word to unique integer
    vocab_lookup = tf.contrib.lookup.index_table_from_tensor(
        mapping=tf.constant(vocab),
        default_value = 0)
    string_tensor = vocab_lookup.lookup(string_tensor)

    # define the Word embedding 
    embedding_init = tf.Variable(tf.constant(np.asarray(embed),
                                 dtype=tf.float32),
                                 trainable=trainable,
                                 name="embed_init")

    # return the Word embedded version of the sentence (300d vectors/Word)
    return tf.nn.embedding_lookup(embedding_init, string_tensor)
17
prijatelj

Das folgende Codebeispiel passt Ihre embed_tensor-Funktion so an, dass Wörter wie folgt eingebettet werden:

  • Bei Wörtern, die eine vorbereitete Einbettung haben, wird die Einbettung mit der vorbereiteten Einbettung initialisiert. Die Einbettung kann während des Trainings unverändert bleiben, wenn trainableFalse ist.
  • Für Wörter in den Trainingsdaten, die keine vorbereitete Einbettung aufweisen, wird die Einbettung zufällig initialisiert. Die Einbettung kann während des Trainings unverändert bleiben, wenn trainableFalse ist.
  • Für Wörter in den Testdaten, die nicht in den Trainingsdaten vorkommen und keine vorbereitete Einbettung aufweisen, wird ein einzelner zufällig initialisierter Einbettungsvektor verwendet. Dieser Vektor kann nicht trainiert werden.
import tensorflow as tf
import numpy as np

EMB_DIM = 300
def load_pretrained_glove():
    return ["a", "cat", "sat", "on", "the", "mat"], np.random.Rand(6, EMB_DIM)

def get_train_vocab():
    return ["a", "dog", "sat", "on", "the", "mat"]

def embed_tensor(string_tensor, trainable=True):
  """
  Convert List of strings into list of indices then into 300d vectors
  """
  # ordered lists of vocab and corresponding (by index) 300d vector
  pretrained_vocab, pretrained_embs = load_pretrained_glove()
  train_vocab = get_train_vocab()
  only_in_train = list(set(train_vocab) - set(pretrained_vocab))
  vocab = pretrained_vocab + only_in_train

  # Set up tensorflow look up from string Word to unique integer
  vocab_lookup = tf.contrib.lookup.index_table_from_tensor(
    mapping=tf.constant(vocab),
    default_value=len(vocab))
  string_tensor = vocab_lookup.lookup(string_tensor)

  # define the Word embedding
  pretrained_embs = tf.get_variable(
      name="embs_pretrained",
      initializer=tf.constant_initializer(np.asarray(pretrained_embs), dtype=tf.float32),
      shape=pretrained_embs.shape,
      trainable=trainable)
  train_embeddings = tf.get_variable(
      name="embs_only_in_train",
      shape=[len(only_in_train), EMB_DIM],
      initializer=tf.random_uniform_initializer(-0.04, 0.04),
      trainable=trainable)
  unk_embedding = tf.get_variable(
      name="unk_embedding",
      shape=[1, EMB_DIM],
      initializer=tf.random_uniform_initializer(-0.04, 0.04),
      trainable=False)

  embeddings = tf.concat([pretrained_embs, train_embeddings, unk_embedding], axis=0)

  return tf.nn.embedding_lookup(embeddings, string_tensor)

Zu Ihrer Information: Um eine sinnvolle, nicht zufällige Repräsentation für Wörter zu haben, die nicht in den Trainingsdaten vorkommen und keine vorgefertigte Einbettung haben, können Sie in Betracht ziehen, Wörter mit einer geringen Häufigkeit in Ihren Trainingsdaten einem Unk-Token zuzuordnen (das steht nicht in Ihrem Vokabular) und machen den unk_embedding trainierbar. Auf diese Weise lernen Sie einen Prototyp für Wörter, die in den Trainingsdaten nicht sichtbar sind.

9
GeertH

Ich habe es nie ausprobiert, aber ich kann versuchen, einen möglichen Weg zu finden, indem Sie die gleichen Maschinen Ihres Codes verwenden, aber ich werde später darüber nachdenken.

Die index_table_from_tensor-Methode akzeptiert einen num_oov_buckets-Parameter, der alle Ihre Oov-Wörter in eine vordefinierte Anzahl von Buckets umsetzt. 

Wenn Sie diesen Parameter auf einen bestimmten "ausreichend großen" Wert setzen, werden Ihre Daten zwischen diesen Buckets verteilt (jeder Bucket hat eine ID> ID des letzten Vokabular-Wortes).

So,

  • if (bei jeder Suche) Sie setzen (d. h. assign) die letzten Zeilen (die den Buckets entsprechen) Ihrer embedding_init-Variablen auf einen zufälligen Wert
  • wenn Sie num_oov_buckets genug groß machen, werden Kollisionen minimiert

sie können ein Verhalten erhalten, das (eine Annäherung an) auf sehr effiziente Weise ist.

Das zufällige Verhalten kann durch eine ähnliche Theorie wie die Hash-Tabelle begründet werden: Wenn die Anzahl der Buckets groß genug ist, ordnet die Hash-Methode der Zeichenfolgen jedes Oov-Word mit hoher Wahrscheinlichkeit einem anderen Bucket zu (dh Kollisionen werden auf das gleiche reduziert Eimer). Da Sie jedem anderen Bucket eine andere Zufallszahl zuweisen, können Sie eine (fast) andere Zuordnung jedes einzelnen Oov-Wortes erhalten.

3
Giuseppe Marra

Ich hatte die Idee, die neuen Wörter für die vorgelernte Einbettung einzufangen, indem ich für jedes neue Wort eine neue Dimension hinzufüge (im Wesentlichen die One-Hot-Natur dieser Wörter beibehalten). 

Angenommen, die Anzahl neuer Wörter ist klein, aber sie sind wichtig. Sie könnten beispielsweise die Dimensionen Ihrer eingebetteten Ergebnisse von 300 auf 300 + Anzahl neuer Wörter erhöhen, wobei jedes neue Word alle Nullen außer 1 in seiner Dimension erhalten würde.

0
Alex Schokking