Je suis curieux de savoir comment ajouter un vecteur de dimension 300 aléatoire normal (éléments de type = tf.float32) chaque fois qu'un mot inconnu du vocabulaire pré-formé est rencontré. J'utilise des systèmes GloVe Word pré-formés, mais dans certains cas, je me rends compte que je rencontre des mots inconnus et que je souhaite créer un vecteur Word normal-aléatoire pour ce nouveau mot inconnu.
Le problème est qu'avec ma configuration actuelle, j'utilise tf.contrib.lookup.index_table_from_tensor pour convertir des mots en entiers en fonction du vocabulaire connu. Cette fonction peut créer de nouveaux jetons et les hacher pour un nombre prédéfini de mots hors vocabulaire, mais ma embed
ne contiendra pas d'incorporation de cette nouvelle valeur de hachage inconnue. Je ne sais pas si je peux simplement ajouter une incorporation aléatoire à la fin de la liste embed
.
Je voudrais aussi le faire de manière efficace, de sorte qu'une fonction ou une méthode de tensorflow prédéfinie impliquant des fonctions de tensorflow serait probablement la plus efficace. Je définis des jetons spéciaux pré-connus tels qu'un jeton de fin de phrase et un inconnu par défaut comme étant la chaîne vide ("à l'index 0), mais son pouvoir d'apprentissage est limité pour différents mots inconnus. J'utilise actuellement tf .nn.embedding_lookup () en tant que dernière étape d'intégration.
J'aimerais pouvoir ajouter de nouveaux vecteurs 300d aléatoires pour chaque mot inconnu dans les données de formation, ainsi que des vecteurs de mot aléatoires prédéfinis pour tous les jetons inconnus non vus au cours de la formation et éventuellement rencontrés lors des tests. Quel est le moyen le plus efficace de le faire?
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)
L'exemple de code ci-dessous adapte votre fonction embed_tensor
de sorte que les mots soient incorporés comme suit:
trainable
est False
.trainable
est False
.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)
Pour votre information, afin d’obtenir une représentation raisonnable et non aléatoire des mots qui ne figurent pas dans les données d’entraînement et qui n’ont pas une incorporation pré-entraînée, vous pouvez envisager de mapper des mots avec une faible fréquence dans vos données d’entraînement sur un jeton unk. (ce n'est pas dans votre vocabulaire) et rendre le unk_embedding
apte à être entraîné. De cette façon, vous apprenez un prototype pour les mots qui ne sont pas vus dans les données d'apprentissage.
Je n'ai jamais essayé, mais je peux essayer de trouver un moyen d'utiliser les mêmes mécanismes que votre code, mais j'y penserai plus tard.
La méthode index_table_from_tensor
accepte un paramètre num_oov_buckets
qui mélange tous vos mots vides dans un nombre prédéfini de compartiments.
Si vous définissez ce paramètre sur une valeur "assez grande", vos données se répartiront entre ces compartiments (chaque compartiment contient un ID> ID du dernier mot en vocabulaire).
Alors,
assign
) les dernières lignes (celles correspondant aux compartiments) de votre variable embedding_init
à une valeur aléatoirenum_oov_buckets
simple assez grand que les collisions seront minimiséesvous pouvez obtenir un comportement qui est (approximativement) ce que vous demandez de manière très efficace.
Le comportement aléatoire peut être justifié par une théorie similaire à celle de la table de hachage: si le nombre de compartiments est suffisamment grand, la méthode de hachage des chaînes affectera chaque mot oov à un compartiment différent avec une probabilité élevée seaux). Étant donné que vous attribuez un nombre aléatoire différent à chaque compartiment, vous pouvez obtenir un mappage (presque) différent de chaque mot oov.
Une idée que j’avais pour cela était de capturer les nouveaux mots de l’intégration pré-entraînée en ajoutant une nouvelle dimension à chaque nouveau mot (en maintenant essentiellement la nature unique de ces mots).
En supposant que le nombre de nouveaux mots soit petit mais important, vous pouvez par exemple augmenter les dimensions de vos résultats incorporés de 300 à 300 + # de nouveaux mots, chaque nouveau mot contenant tous les zéros sauf un dans sa dimension.