tf.nn.embedding_lookup(params, ids, partition_strategy='mod', name=None)
No puedo entender el deber de esta función. ¿Es como una tabla de búsqueda? ¿Qué significa devolver los parámetros correspondientes a cada id (en ids)?
Por ejemplo, en el skip-gram
modelo si usamos tf.nn.embedding_lookup(embeddings, train_inputs)
, ¿para cada uno train_input
encuentra la incrustación correspondiente?
Respuestas:
embedding_lookup
La función recupera filas delparams
tensor. El comportamiento es similar al uso de indexación con matrices en numpy. P.ejparams
El argumento también puede ser una lista de tensores, en cuyo casoids
se distribuirá entre los tensores. Por ejemplo, dada una lista de 3 tensores[2, 64]
, el comportamiento por defecto es que van a representarids
:[0, 3]
,[1, 4]
,[2, 5]
.partition_strategy
controla la forma en queids
se distribuyen entre la lista. La partición es útil para problemas de mayor escala cuando la matriz puede ser demasiado grande para mantenerla en una sola pieza.fuente
select_rows
?embedding_lookup
simplemente proporciona una forma conveniente (y paralela) de recuperar incrustaciones correspondientes a id inids
. Elparams
tensor es generalmente una variable tf que se aprende como parte del proceso de entrenamiento, una variable tf cuyos componentes se usan, directa o indirectamente, en una función de pérdida (comotf.l2_loss
) que es optimizada por un optimizador (comotf.train.AdamOptimizer
).Sí, esta función es difícil de entender, hasta que entiendes el punto.
En su forma más simple, es similar a
tf.gather
. Devuelve los elementos deparams
acuerdo con los índices especificados porids
.Por ejemplo (suponiendo que estás dentro
tf.InteractiveSession()
)volvería
[10 20 30 40]
, porque el primer elemento (índice 0) de los parámetros es10
, el segundo elemento de los parámetros (índice 1) es20
, etc.Similar,
volvería
[20 20 40]
.Pero
embedding_lookup
es más que eso. Elparams
argumento puede ser una lista de tensores, en lugar de un solo tensor.En tal caso, los índices, especificados en
ids
, corresponden a elementos de tensores de acuerdo con una estrategia de partición , donde la estrategia de partición predeterminada es 'mod'.En la estrategia 'mod', el índice 0 corresponde al primer elemento del primer tensor de la lista. El índice 1 corresponde al primer elemento del segundo tensor. El índice 2 corresponde al primer elemento del tercer tensor, y así sucesivamente. Simplemente index
i
corresponde al primer elemento del tensor (i + 1) th, para todos los índices0..(n-1)
, suponiendo que params es una lista den
tensores.Ahora, el índice
n
no puede corresponder al tensor n + 1, porque la listaparams
contiene solon
tensores. Entonces, el índicen
corresponde al segundo elemento del primer tensor. Del mismo modo, indexarn+1
corresponde al segundo elemento del segundo tensor, etc.Entonces, en el código
El índice 0 corresponde al primer elemento del primer tensor: 1
El índice 1 corresponde al primer elemento del segundo tensor: 10
El índice 2 corresponde al segundo elemento del primer tensor: 2
El índice 3 corresponde al segundo elemento del segundo tensor: 20
Por lo tanto, el resultado sería:
fuente
partition_strategy='div'
, y obtendría[10, 1, 10, 2, 10, 20]
,id=1
es decir, es el segundo elemento del primer parámetro. Básicamente:partition_strategy=mod
(predeterminado)id%len(params)
: índice del parámetro en parámetrosid//len(params)
: índice del elemento en el parámetro anteriorpartition_strategy=*div*
al revésSí, el propósito de la
tf.nn.embedding_lookup()
función es realizar una búsqueda en la matriz de incrustación y devolver las incrustaciones (o en términos simples la representación vectorial) de las palabras.Una matriz de incrustación simple (de forma:)
vocabulary_size x embedding_dimension
se vería a continuación. (es decir, cada palabra estará representada por un vector de números; de ahí el nombre word2vec )Matriz de incrustación
Dividí la matriz de incrustación anterior y cargué solo las palabras en las
vocab
que estará nuestro vocabulario y los vectores correspondientes en laemb
matriz.Búsqueda de incrustación en TensorFlow
Ahora veremos cómo podemos realizar la búsqueda de incrustación para alguna oración de entrada arbitraria.
Observe cómo obtuvimos las incrustaciones de nuestra matriz de incrustación original (con palabras) utilizando los índices de palabras en nuestro vocabulario.
Por lo general, dicha búsqueda de incrustación es realizada por la primera capa (llamada capa de incrustación ) que luego pasa estas incrustaciones a las capas RNN / LSTM / GRU para su posterior procesamiento.
Nota al margen: por lo general, el vocabulario también tendrá una
unk
ficha especial . Entonces, si un token de nuestra oración de entrada no está presente en nuestro vocabulario, entonces el índice correspondiente a seunk
buscará en la matriz de incrustación.PD Tenga en cuenta que
embedding_dimension
es un hiperparámetro que uno tiene que ajustar para su aplicación, pero los modelos populares como Word2Vec y GloVe usan el300
vector de dimensión para representar cada palabra.Modelo de omisión de word2vec de lectura adicional
fuente
Aquí hay una imagen que representa el proceso de incrustación de búsqueda.
De manera concisa, obtiene las filas correspondientes de una capa de incrustación, especificada por una lista de ID y la proporciona como tensor. Se logra a través del siguiente proceso.
lookup_ids = tf.placeholder([10])
embeddings = tf.Variable([100,10],...)
embed_lookup = tf.embedding_lookup(embeddings, lookup_ids)
lookup = session.run(embed_lookup, feed_dict={lookup_ids:[95,4,14]})
fuente
Cuando el tensor de parámetros está en dimensiones altas, los identificadores solo se refieren a la dimensión superior. Tal vez sea obvio para la mayoría de las personas, pero tengo que ejecutar el siguiente código para entender eso:
Simplemente probando la estrategia 'div' y para un tensor, no hay diferencia.
Aquí está la salida:
fuente
Otra forma de verlo es, suponga que aplana los tensores a una matriz unidimensional, y luego está realizando una búsqueda
(p. ej.) Tensor0 = [1,2,3], Tensor1 = [4,5,6], Tensor2 = [7,8,9]
El tensor aplanado será el siguiente [1,4,7,2,5,8,3,6,9]
Ahora, cuando realices una búsqueda de [0,3,4,1,7], aparecerá [1,2,5,4,6]
(i, e) si el valor de búsqueda es 7, por ejemplo, y tenemos 3 tensores (o un tensor con 3 filas), entonces,
7/3: (El recordatorio es 1, el cociente es 2) Entonces se mostrará el segundo elemento del Tensor1, que es 6
fuente
Como también estaba intrigada por esta función, daré mis dos centavos.
La forma en que lo veo en el caso 2D es solo como una multiplicación de matriz (es fácil generalizar a otras dimensiones).
Considere un vocabulario con N símbolos. Entonces, puedes representar un símbolo x como un vector de dimensiones Nx1, codificado en caliente.
Pero desea una representación de este símbolo no como un vector de Nx1, sino como uno con dimensiones Mx1, llamado y .
Entonces, para transformar x en y , puede usar e incrustar la matriz E , con dimensiones MxN:
y = E x .
Esto es esencialmente lo que está haciendo tf.nn.embedding_lookup (params, ids, ...), con el matiz de que los identificadores son solo un número que representa la posición del 1 en el vector x codificado en caliente .
fuente
Agregar a la respuesta de Asher Stern,
params
se interpreta como una partición de un gran tensor de incrustación. Puede ser un solo tensor que represente el tensor de incrustación completo, o una lista de tensores X todos de la misma forma, excepto la primera dimensión, que representa los tensores de incrustación fragmentados.La función
tf.nn.embedding_lookup
se escribe considerando el hecho de que la incrustación (params) será grande. Por eso lo necesitamospartition_strategy
.fuente