Secuencia a secuencia Modelos de la Parte 2

Hola a todos!

La segunda parte de la traducción, que publicamos hace un par de semanas, en preparación para el lanzamiento de la segunda secuencia del curso "Científico de datos" . A continuación hay otro material interesante y una lección abierta.

Mientras tanto, nos adentramos en la jungla de modelos.

Modelo de traducción neuronal

Si bien el núcleo del modelo de secuencia a secuencia es creado por funciones de tensorflow/tensorflow/python/ops/seq2seq.py , todavía hay un par de trucos utilizados en nuestro modelo de traducción en models/tutorials/rnn/translate/seq2seq_model.py , acerca de Vale la pena mencionar.



Softmax muestreado y proyección de salida

Como se mencionó anteriormente, queremos usar el softmax muestreado para trabajar con un diccionario de salida grande. Para decodificar a partir de él, debe seguir la proyección de la salida. Tanto la pérdida softmax muestreada como la proyección de salida se generan mediante el siguiente código en seq2seq_model.py .

 if num_samples > 0 and num_samples < self.target_vocab_size: w_t = tf.get_variable("proj_w", [self.target_vocab_size, size], dtype=dtype) w = tf.transpose(w_t) b = tf.get_variable("proj_b", [self.target_vocab_size], dtype=dtype) output_projection = (w, b) def sampled_loss(labels, inputs): labels = tf.reshape(labels, [-1, 1]) # We need to compute the sampled_softmax_loss using 32bit floats to # avoid numerical instabilities. local_w_t = tf.cast(w_t, tf.float32) local_b = tf.cast(b, tf.float32) local_inputs = tf.cast(inputs, tf.float32) return tf.cast( tf.nn.sampled_softmax_loss( weights=local_w_t, biases=local_b, labels=labels, inputs=local_inputs, num_sampled=num_samples, num_classes=self.target_vocab_size), dtype) 

Primero, tenga en cuenta que solo creamos softmax muestreado si el número de muestras (512 por defecto) es menor que el tamaño del diccionario de destino. Para diccionarios menores de 512, es mejor usar la pérdida estándar de softmax.

Luego, cree una proyección de la salida. Este es un par que consiste en una matriz de pesos y un vector de desplazamiento. Cuando se usa, la celda rnn devuelve los vectores de forma del número de muestras de entrenamiento por size , y no el número de muestras de entrenamiento por target_vocab_size . Para restaurar logits, debe multiplicarlo por la matriz de pesos y agregar un desplazamiento, que ocurre en las líneas 124-126 en seq2seq_model.py .

 if output_projection is not None: for b in xrange(len(buckets)): self.outputs[b] = [tf.matmul(output, output_projection[0]) + output_projection[1] for ...] 

Bucketing y acolchado

Además del softmax muestreado, nuestro modelo de traducción también utiliza el bucketing , un método que le permite administrar de manera eficiente oraciones de diferentes longitudes. Para comenzar, explica el problema. Al traducir del inglés al francés, tenemos oraciones en inglés de diferentes longitudes L1 en la entrada y oraciones en francés de diferentes longitudes L1 en la salida. Como la oración en inglés se transmite como encoder_inputs , y la oración en francés se muestra como decoder_inputs (con el prefijo del símbolo GO), es necesario crear un modelo seq2seq para cada par (L1, L2 + 1) de longitudes de oraciones en inglés y francés. Como resultado, obtenemos un gráfico enorme que consta de muchos subgráficos similares. Por otro lado, podemos "rellenar" cada oración con caracteres PAD especiales. Y luego solo necesitamos un modelo seq2seq para longitudes "empaquetadas". Pero dicho modelo será ineficaz en oraciones cortas: debe codificar y decodificar muchos caracteres PAD inútiles.

Como compromiso entre crear un gráfico para cada par de longitudes y rellenarlo en una sola longitud, usamos un cierto número de cubos y rellenamos cada oración a la longitud del grupo anterior. En translate.py usamos los siguientes grupos por defecto.

 buckets = [(5, 10), (10, 15), (20, 25), (40, 50)] 


Por lo tanto, si una oración en inglés con 3 tokens llega a la entrada, y la oración en francés correspondiente contiene 6 tokens en la salida, irán al primer grupo y se completarán hasta la longitud 5 en la entrada del codificador y la longitud 10 en la entrada del decodificador. Y si hay 8 tokens en la oferta en inglés, y en el francés 18 correspondiente, no caerán en el grupo (10, 15) y se transferirán al grupo (20, 25), es decir, la oferta en inglés aumentará a 20 tokens, y la francesa a 25.

Recuerde que al crear la entrada del decodificador, agregamos el carácter GO especial a la entrada. Esto sucede en la función get_batch() en seq2seq_model.py , que también voltea la oración en inglés. La inversión de la entrada ayudó a mejorar los resultados del modelo de traducción neural de Sutskever et al., 2014 (pdf). Para finalmente resolverlo, imagine que hay una oración "voy". En la entrada, dividida en tokens ["I", "go", "."] , Y en la salida hay una oración "Je vais", dividida en tokens ["Je", "vais", "."] . Se agregarán al grupo (5, 10), con una representación del codificador de entrada [PAD PAD "." "go" "I"] [PAD PAD "." "go" "I"] y la entrada del decodificador [GO "Je" "vais" "." EOS PAD PAD PAD PAD PAD] [GO "Je" "vais" "." EOS PAD PAD PAD PAD PAD] .

Ejecutarlo

Para entrenar el modelo descrito anteriormente, necesitará un gran cuerpo anglo-francés. Para la capacitación, utilizaremos el cuerpo 10 ^ 9 francés-inglés del sitio web WMT'15 , y probaremos las noticias del mismo sitio como muestra de trabajo. Ambos conjuntos de datos se train_dir en train_dir cuando se train_dir el siguiente comando.

 python translate.py --data_dir [your_data_directory] --train_dir [checkpoints_directory] --en_vocab_size=40000 --fr_vocab_size=40000 

Necesitará 18 GB de espacio en el disco duro y varias horas para preparar el edificio de capacitación. El caso se desempaqueta, los archivos de diccionario se crean en data_dir, y luego el caso se tokeniza y se convierte en identificadores enteros. Presta atención a los parámetros responsables del tamaño del diccionario. En el ejemplo anterior, todas las palabras fuera de las 40,000 palabras usadas con mayor frecuencia se convertirán en un token UNK que representa una palabra desconocida. Por lo tanto, al cambiar el tamaño del diccionario, el binario volverá a reformar la carcasa mediante el token-id. Después de la preparación de datos comienza el entrenamiento.

Los valores especificados en la translate son muy altos por defecto. Los modelos grandes que aprenden durante mucho tiempo muestran buenos resultados, pero puede llevar demasiado tiempo o demasiada memoria de GPU. Puede especificar un modelo de entrenamiento más pequeño, como en el ejemplo a continuación.

 python translate.py --data_dir [your_data_directory] --train_dir [checkpoints_directory] --size=256 --num_layers=2 --steps_per_checkpoint=50 

El comando anterior entrenará el modelo con dos capas (hay 3 por defecto), cada una de las cuales tiene 256 unidades (1024 por defecto), con un punto de control cada 50 pasos (200 por defecto). Experimente con estas opciones para ver qué modelo de tamaño es el adecuado para su GPU.

Durante el entrenamiento, cada paso del binario steps_per_checkpoin t proporcionará estadísticas sobre los pasos anteriores. Con los parámetros predeterminados (3 capas de tamaño 1024), el primer mensaje es el siguiente:

 global step 200 learning rate 0.5000 step-time 1.39 perplexity 1720.62 eval: bucket 0 perplexity 184.97 eval: bucket 1 perplexity 248.81 eval: bucket 2 perplexity 341.64 eval: bucket 3 perplexity 469.04 global step 400 learning rate 0.5000 step-time 1.38 perplexity 379.89 eval: bucket 0 perplexity 151.32 eval: bucket 1 perplexity 190.36 eval: bucket 2 perplexity 227.46 eval: bucket 3 perplexity 238.66 

Tenga en cuenta que cada paso lleva un poco menos de 1,4 segundos, lo que deja perpleja la muestra de entrenamiento y deja perpleja la muestra de trabajo en cada grupo. Después de aproximadamente 30 mil pasos, vemos cómo los perplejos de las oraciones cortas (grupos 0 y 1) se vuelven inequívocos. El edificio de entrenamiento contiene alrededor de 22 millones de oraciones, una iteración (una serie de datos de entrenamiento) toma alrededor de 340 mil pasos con una cantidad de 64 muestras de entrenamiento. En esta etapa, el modelo puede usarse para traducir oraciones en inglés al francés usando la opción --decode .

 python translate.py --decode --data_dir [your_data_directory] --train_dir [checkpoints_directory] Reading model parameters from /tmp/translate.ckpt-340000 > Who is the president of the United States? Qui est le président des États-Unis ? 

Que sigue

El ejemplo anterior muestra cómo crear su propio traductor inglés-francés de principio a fin. Ejecútelo y vea cómo funciona el modelo. La calidad es aceptable, pero no se puede obtener un modelo de traducción ideal con los parámetros predeterminados. Aquí hay algunas cosas que puede mejorar.

Primero, usamos tokenización primitiva, la función básica de basic_tokenizer en data_utils . Se puede encontrar un mejor tokenizador en el sitio web de WMT'15 . Si lo usa y un diccionario grande, puede lograr mejores traducciones.

Además, los parámetros predeterminados del modelo de traducción no están configurados perfectamente. Puede intentar cambiar la velocidad de aprendizaje, la atenuación, la inicialización de los pesos del modelo. También puede reemplazar el GradientDescentOptimizer estándar en seq2seq_model.py con algo más avanzado, como AdagradOptimizer . ¡Prueba y mira para obtener mejores resultados!

Finalmente, el modelo presentado anteriormente puede usarse no solo para la traducción, sino también para cualquier otra tarea de secuencia a secuencia. Incluso si desea convertir una secuencia en un árbol, por ejemplo, generar un árbol de análisis, este modelo puede producir resultados de vanguardia, como lo muestran Vinyals & Kaiser et al., 2014 (pdf) . Por lo tanto, puede crear no solo un traductor, sino también un analizador, un bot de chat o cualquier otro programa que desee. Experimento!

Eso es todo!

Estamos esperando sus comentarios y preguntas aquí o lo invitamos a preguntarle a su maestro en una lección abierta .

Source: https://habr.com/ru/post/es432302/


All Articles