Pregunta Entender `tf.nn.nce_loss ()` en tensorflow


Estoy tratando de entender la función de pérdida de NCE en Tensorflow. La pérdida de NCE se emplea para una tarea de word2vec, por ejemplo:

# Look up embeddings for inputs.
embeddings = tf.Variable(
    tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
embed = tf.nn.embedding_lookup(embeddings, train_inputs)

# Construct the variables for the NCE loss
nce_weights = tf.Variable(
    tf.truncated_normal([vocabulary_size, embedding_size],
                        stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocabulary_size]))

# Compute the average NCE loss for the batch.
# tf.nce_loss automatically draws a new sample of the negative labels each
# time we evaluate the loss.
loss = tf.reduce_mean(
    tf.nn.nce_loss(weights=nce_weights,
                   biases=nce_biases,
                   labels=train_labels,
                   inputs=embed,
                   num_sampled=num_sampled,
                   num_classes=vocabulary_size))

más detalles, por favor consulte Tensorflow word2vec_basic.py

  1. ¿Cuáles son las matrices de entrada y salida en la función NCE?

En un modelo de word2vec, estamos interesados ​​en construir representaciones para palabras. En el proceso de capacitación, dada una ventana deslizada, cada palabra tendrá dos incrustaciones: 1) cuando la palabra es una palabra central; 2) cuando la palabra es una palabra de contexto. Estas dos incrustaciones se llaman vectores de entrada y salida, respectivamente. (más explicaciones de matrices de entrada y salida)

En mi opinión, la matriz de entrada es embeddings y la matriz de salida es nce_weights. ¿Es correcto?

  1. ¿Cuál es la incrustación final?

De acuerdo a un enviar por s0urcer también relacionado con nce, dice que la matriz de inclusión final es solo la matriz de entrada. Mientras, algunos otros dicen, el final_embedding=input_matrix+output_matrix. ¿Cuál es correcto / más común?


16
2018-01-04 23:54


origen


Respuestas:


Veamos el código relativo en word2vec ejemplo (ejemplos / tutoriales / word2vec)

embeddings = tf.Variable(
    tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
embed = tf.nn.embedding_lookup(embeddings, train_inputs)

Estas dos líneas crean representaciones incrustadas. embeddings es una matriz donde cada fila representa un vector de palabra. embedding_lookup es una forma rápida de obtener vectores correspondientes a train_inputs. En el ejemplo de word2vec, train_inputs consiste en algunos int32 número, representando el id de palabras objetivo Básicamente, se puede colocar mediante la función de capa oculta.

# Construct the variables for the NCE loss
nce_weights = tf.Variable(
    tf.truncated_normal([vocabulary_size, embedding_size],
                        stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocabulary_size]))

Estas dos líneas crean parámetros. Serán actualizados por el optimizador durante el entrenamiento. Nosotros podemos usar tf.matmul(embed, tf.transpose(nce_weights)) + nce_biases para obtener el puntaje de salida final. En otras palabras, La última capa de producto interno en clasificación puede ser reemplazada por.

loss = tf.reduce_mean(
      tf.nn.nce_loss(weights=nce_weights,     # [vocab_size, embed_size]
                   biases=nce_biases,         # [embed_size]
                   labels=train_labels,       # [bs, 1]
                   inputs=embed,              # [bs, embed_size]
                   num_sampled=num_sampled, 
                   num_classes=vocabulary_size))

Estas líneas crean nce loss, @garej ha dado una muy buena explicación. num_sampled se refiere al número de muestras negativas en nce algoritmo.


Para ilustrar el uso de nce, podemos aplicarlo en mnist ejemplo (ejemplos / tutoriales / mnist / mnist_deep.py) con los siguientes 2 pasos:

1. Reemplazar incrustación con salida de capa oculta. La dimensión de la capa oculta es 1024 y num_output es 10. Valor mínimo de num_sampled es 1. Recuerde eliminar la última capa de producto interno en deepnn().

y_conv, keep_prob = deepnn(x)                                            

num_sampled = 1                                                          
vocabulary_size = 10                                                     
embedding_size = 1024                                                    
with tf.device('/cpu:0'):                                                
  embed = y_conv                                                         
  # Construct the variables for the NCE loss                             
  nce_weights = tf.Variable(                                             
      tf.truncated_normal([vocabulary_size, embedding_size],             
                          stddev=1.0 / math.sqrt(embedding_size)))       
  nce_biases = tf.Variable(tf.zeros([vocabulary_size])) 

2. Crear pérdidas y calcular la salida. Después de calcular la salida, podemos usarla para calcular la precisión. Tenga en cuenta que la etiqueta aquí no es un vector caliente como se usa en softmax. Las etiquetas son la etiqueta original de las muestras de entrenamiento.

loss = tf.reduce_mean(                                   
    tf.nn.nce_loss(weights=nce_weights,                           
                   biases=nce_biases,                             
                   labels=y_idx,                                  
                   inputs=embed,                                  
                   num_sampled=num_sampled,                       
                   num_classes=vocabulary_size))                  

output = tf.matmul(y_conv, tf.transpose(nce_weights)) + nce_biases
correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(y_, 1))

Cuando establecemos num_sampled=1, la precisión de val terminará alrededor 98.8%. Y si establecemos num_sampled=9, podemos obtener casi la misma precisión val como entrenados por softmax. Pero ten en cuenta que nce es diferente de softmax.

Código completo de entrenamiento mnist por nce puede ser encontrado aquí. Espero que sea útil.


9
2018-05-21 17:19



los embeddings Tensor es su matriz de salida final. Asigna palabras a vectores. Use esto en su gráfico de predicción de palabras.

La matriz de entrada es un lote de centre-word : context-word pares (train_input y train_label respectivamente) generado a partir del texto de entrenamiento.

Si bien el funcionamiento exacto de la nce_loss Todavía no sé para mí, la idea básica es que utiliza una red de una sola capa (parámetros nce_weights y nce_biases) para mapear un vector de entrada (seleccionado de embeddings utilizando el embed op) a una palabra de salida, y luego compara la salida con la etiqueta de capacitación (una palabra adyacente en el texto de capacitación) y también con una submuestra al azar (num_sampled) de todas las otras palabras en el vocabulario, y luego modifica el vector de entrada (almacenado en embeddings) y los parámetros de red para minimizar el error.


1
2018-01-31 12:19



¿Cuáles son las matrices de entrada y salida en la función NCE?

Tomemos, por ejemplo, el modelo de skip gram, para esta frase:

the quick brown fox jumped over the lazy dog

los pares de entrada y salida son:

(quick, the), (quick, brown), (brown, quick), (brown, fox), ...

Para obtener más información, consulte el tutorial.

¿Cuál es la incrustación final?

La incrustación final que debes extraer suele ser el {w} entre la entrada y la capa oculta.

enter image description here

Para ilustrar de forma más intuitiva, eche un vistazo a la siguiente imagen: enter image description here

El único vector caliente [0, 0, 0, 1, 0] es la capa de entrada en el gráfico anterior, el resultado es la palabra incrustada [10, 12, 19] y W (en el gráfico anterior) es la matriz en Entre.

Para una explicación detallada, lea este tutorial.


1
2018-02-22 13:09



1) En resumen, es correcto en general, pero en parte correcto para la función en cuestión. Ver tutorial:

La pérdida de estimación de ruido-contraste se define en términos de   modelo de regresión logística. Para esto, necesitamos definir los pesos y   sesgos para cada palabra en el vocabulario (también llamado el output weights en contraposición al input embeddings)

Así que las entradas a la función nce_loss son output weights y un pequeño parte de input embeddings, entre otras cosas.

2) La incrustación 'final' (aka vectores de Word, también conocido como representaciones de Vector de Palabras) es lo que llamas input matrix. Las incrustaciones son cadenas (vectores) de esa matriz, que corresponden a cada palabra.

Advertir De hecho, esta terminología es confusa debido al uso de conceptos de entrada y salida en el entorno NN. La matriz de incrustaciones no es una entrada para NN, ya que la entrada a NN es técnicamente una capa de entrada. Obtiene el estado final de esta matriz durante el proceso de entrenamiento. No obstante, esta matriz debe inicializarse en la programación, ya que un algoritmo debe comenzar desde algún estado aleatorio de esta matriz para actualizarlo gradualmente durante el entrenamiento.

Lo mismo es cierto para los pesos: también se deben inicializar. Sucede en la siguiente línea:

nce_weights = tf.Variable(
        tf.truncated_normal([50000, 128], stddev=1.0 / math.sqrt(128)))

Cada vector de incrustación se puede multiplicar por un vector de la matriz de pesos (en una forma de cadena a columna). Entonces obtendremos el escalar en el NN output layer. La norma de este escalar se interpreta como la probabilidad de que la palabra objetivo (desde la capa de entrada) vaya acompañada de una palabra de etiqueta [o contexto] correspondiente al lugar de escalar en output layer.

Advertir: irónicamente hay una confusión (error) en el tutorial de TensorFlow en Construyendo el Gráfico sección - confundieron objetivos y contextos. Lo que es peor, en el archivo python al que se refiere, utilizan etiquetas para palabras contextuales. Creo que desconcertó a muchas personas que luchaban con este pobre tutorial.


Entonces, si estamos hablando de entradas (argumentos) para la función, entonces ambas matrices son tales: ponderaciones y una extracción del tamaño de lote desde las incrustaciones:

tf.nn.nce_loss(weights=nce_weights,            # Tensor of shape(50000, 128)
               biases=nce_biases,              # vector of zeros; len(128)
               labels=train_labels,            # labels == context words enums
               inputs=embed,                   # Tensor of shape(128, 128)
               num_sampled=num_sampled,        # 64: randomly chosen negative (rare) words
               num_classes=vocabulary_size))   # 50000: by construction

Esta nce_loss función genera un vector de batch_size - en el ejemplo de TensorFlow a shape(128,) tensor. Entonces reduce_mean() reduce este resultado a un escalar tomando la media de esos 128 valores, que de hecho es un objetivo para una mayor minimización.

Espero que esto ayude.


0
2018-05-19 20:50



Del papel Aprendizaje de embeddings de palabras de manera eficiente con estimación de ruido-contraste:

NCE se basa en la reducción de la estimación de densidad a la clasificación binaria probabilística. La idea básica es entrenar un clasificador de regresión logística para   discriminar entre muestras de la distribución de datos y muestras de alguna distribución de "ruido"

Podríamos descubrir que en la incrustación de palabras, el NCE es en realidad un muestreo negativo. (Para la diferencia entre estos dos, vea el papel: Notas sobre la estimación del contraste de ruido y el muestreo negativo)

Por lo tanto, no necesita ingresar la distribución de ruido. Y también a partir de la cita, descubrirá que en realidad es una regresión logística: el peso y el sesgo serían la única necesidad para la regresión logística. Si está familiarizado con word2vec, solo está agregando un sesgo.


0
2018-03-15 09:11