python-2.7 - started - tensorflow tutorial pdf
Cómo agregar nuevas incrustaciones para palabras desconocidas en Tensorflow(capacitación y preconfiguración para pruebas) (2)
El siguiente ejemplo de código adapta su función embed_tensor
para que las palabras se embed_tensor
siguiente manera:
- Para las palabras que tienen una inserción preestablecida, la inserción se inicializa con la inserción preestablecida. La inserción puede mantenerse fija durante el entrenamiento si el entrenamiento es
False
. - Para las palabras en los datos de entrenamiento que no tienen una inserción preestablecida, la incrustación se inicializa aleatoriamente. La inserción puede mantenerse fija durante el entrenamiento si el entrenamiento es
False
. - Para las palabras en los datos de prueba que no aparecen en los datos de entrenamiento y no tienen una inserción preestablecida, se utiliza un solo vector de incrustación inicializado aleatoriamente. Este vector no puede ser entrenado.
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 = 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),
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)
Para tu información, para tener una representación sensata y no aleatoria de las palabras que no aparecen en los datos de entrenamiento y no tienen una incrustación preestablecida, podrías considerar mapear palabras con baja frecuencia en tus datos de entrenamiento en un token unk (ese no está en su vocabulario) y hacer el unk_embedding
entrenable. De esta forma, aprendes un prototipo de palabras que no se ven en los datos de entrenamiento.
Tengo curiosidad sobre cómo puedo agregar un vector de 300 dimensiones de aleatoriedad normal (elementos ''type = tf.float32) siempre que se encuentre una palabra desconocida para el vocabulario pre-entrenado. Estoy usando incrustaciones de palabras Glove previamente entrenadas, pero en algunos casos, me doy cuenta de que encuentro palabras desconocidas, y quiero crear un vector de palabras aleatorias normal para esta nueva palabra desconocida encontrada.
El problema es que con mi configuración actual, uso tf.contrib.lookup.index_table_from_tensor para convertir de palabras a enteros en función del vocabulario conocido. Esta función puede crear nuevos tokens y hash para un número predefinido de palabras sin vocabulario, pero mi inserción no contendrá una incrustación para este nuevo valor hash desconocido. No estoy seguro de si puedo agregar simplemente una inserción aleatoria al final de la lista de inserción.
También me gustaría hacer esto de una manera eficiente, por lo que la función tensorflow preconstruida o el método que implica funciones de flujo de tensión probablemente sería el más eficiente. Defino tokens especiales conocidos, como un token de final de frase y un valor predeterminado desconocido como la cadena vacía ("" en el índice 0), pero este tiene un poder limitado para aprender diferentes palabras desconocidas. Actualmente uso tf.nn.embedding_lookup () como el paso de incorporación final.
Me gustaría poder agregar nuevos vectores aleatorios 300d para cada palabra desconocida en los datos de entrenamiento, y también me gustaría agregar vectores de palabras aleatorios prefabricados para cualquier token desconocido que no se haya visto en el entrenamiento y que posiblemente se encuentre durante la prueba. ¿Cuál es la forma más eficiente de hacer esto?
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)
Nunca lo intenté, pero puedo tratar de proporcionar una forma posible utilizando las mismas maquinarias de tu código, pero lo pensaré más adelante.
El método index_table_from_tensor
acepta un parámetro num_oov_buckets
que num_oov_buckets
todas las palabras de oov en un número predefinido de segmentos.
Si configura este parámetro con un cierto valor "suficientemente grande", verá los datos distribuidos entre estos segmentos (cada segmento tiene un ID> ID de la última palabra en el vocabulario).
Asi que,
- si (en cada búsqueda) establece (es decir
assign
) las últimas filas (las correspondientes a los depósitos) de su variableembedding_init
a un valor aleatorio - si haces
num_oov_buckets
suficientemente grande como para que las colisiones se minimicen
puedes obtener un comportamiento que sea (una aproximación de) lo que estás preguntando de una manera muy eficiente.
El comportamiento aleatorio puede justificarse mediante una teoría similar a la tabla hash: si el número de cubetas es suficientemente grande, el método de hash de las cadenas asignará cada palabra oov a un cucharón diferente con alta probabilidad (es decir, minimizando las colisiones al mismo cubos). Dado que está asignando un número aleatorio diferente a cada cubo diferente, puede obtener un mapeo (casi) diferente de cada palabra oov.