Tutorial: entrenamiento de motores de traducción automática neuronal con Marian - mtuoc/tutorials GitHub Wiki
En esta unidad vamos a aprender a entrenar un sistema de traducción automática neuronal utilizando Marian. Para ello utilizaremos un corpus preprocesado con SentencePiece o bien con subword-nmt.
Para entrenar el sistema también vas a necesitar el binario de marian. Para ello tienes dos opciones:
- Compilarlo (solo para expertos) siguiendo las instrucciones de: https://marian-nmt.github.io/
- Descargar una versión ya compilada (solo para CPU) que va a funcionar bien en un Ubuntu 20.04 (también en máquina virtual o en Windows Linux Subsystem). La puedes descargar de este enlace: marian
NOTA MUY IMPORTANTE: PARA ENTRENAR SISTEMAS NEURONALES ES IMPRESCINDIBLE DISPONER DE UNIDADES GPU POTENTES. EN ESTE APARTADO, COMO QUE TRABAJAMOS CON CPU, INICIAREMOS LOS PROCESOS DE ENTRENAMIENTO Y LOS PARAREMOS PASADOS UNOS MINUTOS.
Para realizar un proceso de entrenamiento básico, pondremos el archivo marian y los corpus de entrenamiento y validación en un directorio y ejecutaremos el siguiente comando:
./marian --train-sets train.sp.en train.sp.es --valid-sets val.sp.en val.sp.es --vocabs vocab-en.yml vocab-es.yml --model model.npz
Se inciciará el proceso de entrenamiento y aparecerán una serie de mensajes como los siguientes:
...
[2021-05-08 12:00:51] [config] workspace: 2048
[2021-05-08 12:00:51] [config] Model is being created with Marian v1.10.12 b36d0bbb 2021-03-22 11:13:40 -0700
[2021-05-08 12:00:51] [training] Using single-device training
[2021-05-08 12:00:51] [comm] Compiled without MPI support. Running as a single process on PC1P2G3J
[2021-05-08 12:00:51] Synced seed 1620468050
[2021-05-08 12:00:51] [data] Creating vocabulary vocab-en.yml from train.sp.en
[2021-05-08 12:02:00] [data] Loading vocabulary from JSON/Yaml file vocab-en.yml
[2021-05-08 12:02:01] [data] Setting vocabulary size for input 0 to 32,826
[2021-05-08 12:02:01] [data] Creating vocabulary vocab-es.yml from train.sp.es
[2021-05-08 12:03:37] [data] Loading vocabulary from JSON/Yaml file vocab-es.yml
[2021-05-08 12:03:37] [data] Setting vocabulary size for input 1 to 41,685
[2021-05-08 12:03:37] [memory] Extending reserved space to 2048 MB (device cpu0)
[2021-05-08 12:03:37] [training] Using 1 CPUs
[2021-05-08 12:03:37] Training started
[2021-05-08 12:03:37] [data] Shuffling data
...
En un ordenador con una GPU potente el proceso de entrenamiento duraría un par de días. Sin GPU el proceso duraría años, por lo que se tendrá que parar pasados unos minutos.
Normalmente se quiere tener un control más detallado sobre los parámetros de entrenamiento y poder escoger el tipo de motor neuronal (por ejemplo: s2s o Transformer). Por ejemplo, una entrenamiento de tipo transformer se podría iniciar de la siguiente manera:
./marian --model model.npz --type transformer --train-sets train.sp.en train.sp.es --max-length 100 --vocabs vocab-en.yml vocab-es.yml --mini-batch-fit -w 10000 --maxi-batch 1000 --early-stopping 10 --valid-freq 5000 --save-freq 5000 --disp-freq 500 --valid-metrics bleu --valid-sets val.sp.en val.sp.es --quiet-translation --valid-mini-batch 64 --beam-size 6 --normalize 0.6 --log train.log --valid-log valid.log --enc-depth 6 --dec-depth 6 --transformer-heads 8 --transformer-postprocess-emb d --transformer-postprocess dan --transformer-dropout 0.1 --label-smoothing 0.1 --learn-rate 0.0003 --lr-warmup 16000 --lr-decay-inv-sqrt 16000 --lr-report --optimizer-params 0.9 0.98 1e-09 --clip-norm 5 --tied-embeddings-all --devices 0 --sync-sgd --seed 1111 --exponential-smoothing --guided-alignment train.sp.en.es.align
y uno de s2s de la siguiente manera:
./marian --devices 0 --type s2s --model model.npz --train-sets train.sp.en train.sp.es --vocabs vocab-en.yml vocab-es.yml --dim-vocabs 100000 100000 --mini-batch-fit -w 3000 --layer-normalization --dropout-rnn 0.2 --dropout-src 0.1 --dropout-trg 0.1 --early-stopping 5 --valid-freq 10000 --save-freq 10000 --disp-freq 1000 --valid-metrics bleu --valid-sets val.sp.en val.sp.es --log train.log --valid-log valid.log --overwrite --keep-best --seed 1111 --exponential-smoothing --normalize=1 --beam-size 12 --quiet-translation --guided-alignment train.sp.en.es.align
No obstante, habitualmente se utilizan unos archivos de configuración que podemos editar para adaptarlos a nuestras necesidades. Los archivos de configuración pueden variar ligeramente dependiendo de la versión de marian que estemos utilizando en un determinado momento. Por este motivo conviene generar estos archivos cada vez que actualizamos la versión de marian. Para generar estos archivos de configuración repetimos las instrucciones anteriores acabándolas con la instrucción --dump-config y redirigier la salida a un archivo Yaml.
./marian --model model.npz --type transformer --train-sets train.sp.en train.sp.es --max-length 100 --vocabs vocab-en.yml vocab-es.yml --mini-batch-fit -w 10000 --maxi-batch 1000 --early-stopping 10 --valid-freq 5000 --save-freq 5000 --disp-freq 500 --valid-metrics bleu --valid-sets val.sp.en val.sp.es --quiet-translation --valid-mini-batch 64 --beam-size 6 --normalize 0.6 --log train.log --valid-log valid.log --enc-depth 6 --dec-depth 6 --transformer-heads 8 --transformer-postprocess-emb d --transformer-postprocess dan --transformer-dropout 0.1 --label-smoothing 0.1 --learn-rate 0.0003 --lr-warmup 16000 --lr-decay-inv-sqrt 16000 --lr-report --optimizer-params 0.9 0.98 1e-09 --clip-norm 5 --tied-embeddings-all --devices 0 --sync-sgd --seed 1111 --exponential-smoothing --guided-alignment train.sp.en.es.align --dump-config > config-transformer-bleu.yml
o bien:
./marian --devices 0 --type s2s --model model.npz --train-sets train.sp.en train.sp.es --vocabs vocab-en.yml vocab-es.yml --dim-vocabs 100000 100000 --mini-batch-fit -w 3000 --layer-normalization --dropout-rnn 0.2 --dropout-src 0.1 --dropout-trg 0.1 --early-stopping 5 --valid-freq 10000 --save-freq 10000 --disp-freq 1000 --valid-metrics bleu --valid-sets val.sp.en val.sp.es --log train.log --valid-log valid.log --overwrite --keep-best --seed 1111 --exponential-smoothing --normalize=1 --beam-size 12 --quiet-translation --guided-alignment train.sp.es.en.align --dump-config > config-s2s-bleu.yml
Cuando generamos estos archivos de configuración las opciones están en un orden que no es demasiado cómodo y conviene situar las opciones más habituales al principio del archivo para facilitar la modificación. Por ejemplo, para entrenar un sistema Transformer, podríamos utilizar el siguiente archivos de configuración: config-transformer-bleu.yml (mostramos únicamente las opciones que habitualmente modificamos):
authors: false
cite: false
train-sets:
- train.sp.en
- train.sp.es
valid-sets:
- val.sp.en
- val.sp.es
guided-alignment: train.sp.es.en.align
vocabs:
- vocab-en.yml
- vocab-es.yml
early-stopping: 5
keep-best: true
overwrite: true
dim-vocabs:
- 64000
- 64000
workspace: 10000
Ahora podemos entrear els sistema con este archivo de configuración haciendo (config-transformer-bleu.yml):
./marian -c config-transformer-bleu.yml
Podemos hacer lo mismo para el sistema s2s (config-transformer-s2s).yml:
./marian -c config-s2s.yml
Marian proporciona la opcíón --task, que proporciona una manera rápida de configurar un entrenamiento de un tipo determinado. La lista de configuraciones predefinidas incluye:
- best-deep: La arquitectura RNN BiDeep propuesta por Miceli Barone et al. (2017)
- transformer-base y transformer-big: arquitercturas y configuraciones de entrenamiento para los models Transformer "base" y Transformer "big", respectivamente, presentados en Vaswani et al. (2019)
- transformer-base-prenorm y transformer-big-prenorm: variantes de dos modelos Transformer con "prenorm", es decir, la normalización de la capa se realiza como el primer paso de preprocesamiento por bloques.
Las opciones se pueden seleccionar directamente con --task . Por ejemplo, para entrenar un transformer-base podríamos escribir:
./marian --train-sets train.sp.en train.sp.es --valid-sets val.sp.en val.sp.es --vocabs vocab-en.yml vocab-es.yml --model model.npz --task transformer-base
(o probar cualquiera del resto de opciones). Además, podemos utilizar la opcón --dump-config para obtener un archivo de configuración para esta configuración predefinida:
./marian --train-sets train.sp.en train.sp.es --valid-sets val.sp.en val.sp.es --vocabs vocab-en.yml vocab-es.yml --model model.npz --task transformer-base --dump-config > config-transformer-base.yml
Después podemos editar el archivo yml resultante para poner las opciones que modificamos más frecuentemente y poder ejecutar el entrenamiento con la instrucción:
./marian -c config-transformer-base.yml
Dos puntos importantes a tener en cuenta en nuesta configuración es la métrica o métricas de validación que utilizaremos y en qué momento pararemos el entrenamiento. Normalmente se detiene un entrenamiento cuando no se consiguen mejoras en los resultados dado por la métrica o métricas de validación durante un determinado número de validaciones (lo que se conoce como early stopping). Marian ofrece las siguientes métricas de validación:
- cross-entropy
- ce-mean-words
- valid-script: ejecuta el script de validación especificado con la opción --valid-script-path. El script tiene que devolver un número de coma flotante.
- translation: ejecuta el script especificado con la opción --valid-script-path pasándole como parámetro el nombre del archivode validación de la lengua de partida como primer argumento (por ejemplo $1 en Bash script, sys.argv[1] en Python, etc.). El script tiene que devolver un número de coma flotante.
- bleu: calcula el valor de BLEU sobre los conjuntos de validación en bruto. Como que habitualmente estos conjuntos están formados por subpalabras, el valor BLEU suele ser más alto que el real y nunca se debe utilizar el valor de BLEU obtenido como índice real de calidad.
- bleu-detok: calcula el valor de BLEU sobre los conjuntos de validación postprocesados. Requiere SentencePiece y Marian v1.6.2+.
Early stopping es la técnica habitual para decidir cuándo detener un entrenamiento basada en una heurística que utiliza el conjunto de validación. Por defecto se utiliza una paciencia de 10, es decir un --early-stopping de 10. Esto quiere decir que el entrenamiento se parará cuando pasen 10 procesos de validación iterativos que no consiga mejoras. Si se utiliza más de una métrica en la validación por defecto se detiene entrenamiento cuando cualquiera de estas métricas llega al valor de early-stopping. Pero se puede indicar que se detenga cuando todas las métricas lleguen al valor de early-stopping poniendo el valor del parámetro --early-stopping-on en all (el valor por defecto es any)
Hay dos parámetros más a tener en cuenta relacionados con early-stopping:
- overwrite: por defecto Marian guarda todos los modelos para cada paso de validación. Si ponemos este parámetro en true borrará los modelos anteriores y mantendrá únicamente el último (o el mejor, dependiendo de la siguiente opción).
- keep-best: se utiliza junto a la opción anterior. Si está en true guarda el mejor modelo.
Para indicar más de una métrica de validación, en el archivo de configuración tenemos que indicarlas en el parámetro valid-metrics:
valid-metrics:
- cross-entropy
- bleu-detok