Este repositorio contiene código para replicar nuestra investigación descrita en "abarrotar: capacitar un modelo de idioma en una sola GPU en un día". Experimentamos con el modelo de lenguaje previamente un modelo de tipo Bert con cálculo limitado, preguntándonos "¿qué tan malo puede ser realmente"?
Puede encontrar nuestro documento aquí: https://arxiv.org/abs/2212.14034, y el resumen a continuación:
Las tendencias recientes en el modelado de idiomas se han centrado en aumentar el rendimiento a través de la escala, y han resultado en un entorno en el que los modelos de lenguaje de capacitación están fuera del alcance de la mayoría de los investigadores y profesionales. Si bien la mayoría de la comunidad pregunta cómo superar los límites del cálculo extremo, hacemos la pregunta opuesta:
¿Hasta dónde podemos llegar con una sola GPU en solo un día?
Investigamos el rendimiento aguas abajo que se puede lograr con un modelo de lenguaje basado en transformador entrenado completamente desde cero con modelado de lenguaje enmascarado durante un solo día en una sola GPU de consumo . Además de volver a analizar casi todos los componentes de la tubería previa a la altura para este escenario y proporcionar una tubería modificada con un rendimiento cercano a Bert, investigamos por qué la ampliación es difícil, y qué modificaciones realmente mejoran el rendimiento en este escenario. Proporcionamos evidencia de que incluso en este entorno restringido, el rendimiento sigue de cerca las leyes de escala observadas en entornos de gran competencia. A través de la lente de las leyes de escala, clasificamos una variedad de mejoras recientes a la capacitación y la arquitectura y discutimos su mérito y aplicabilidad práctica (o falta de ella) para el entorno de cálculo limitado.
Necesita Pytorch 2.0 para ejecutar el nuevo código. Si desea permanecer en Pytorch 1.*, puede consultar la etiqueta Last1.13release . El nuevo modelo, entrenado con la nueva base de código, es 1-2% mejor en pegamento con el mismo presupuesto. El punto de control se puede encontrar en https://huggingface.co/jonasgeiping/crammed-bert. El antiguo punto de control ahora es https://huggingface.co/jonasgeiping/crammed-bert-legacy.
Además, el preprocesamiento de datos ha mejorado, ahora puede transmitir datos directamente desde Huggingface, desde la carga en https://huggingface.co/datasets/jonasgeiping/the_pile_wordpiecex32768_2efdb9d060d1ae95faf952ec1a50f020.
Configuración:
Ejecute pip install . para instalar todas las dependencias.
torch (al menos la versión 2.1)transformers , tokenizers , datasets , evaluatehydra-corepsutil , pynvml , safetensorseinops pip install . Para instalar todos los paquetes y scripts.curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh , luego git clone https://github.com/google-research/deduplicate-text-datasets/tree/dev-v1 y luego ejecute cargo install --target-dir ../cramming/dedupPara verificar una instalación mínima, puede ejecutar
python pretrain.py name=test arch=hf-bert-base train=bert-base data=sanity-check-2 dryrun=True impl.microbatch_size=2
Este comando preprocesa un pequeño conjunto de datos de verificación de cordura y ejecuta un solo paso de entrenamiento.
Use el script pretrain.py para pretrenar con un cálculo limitado. Este repositorio usa Hydra (https://hydra.cc/docs/intro/), por lo que todos los campos en cramming/config se pueden modificar en la línea de comandos. Por ejemplo, el budget puede modificarse proporcionando budget=48 como argumento adicional (para ejecutarse durante 48 horas), o la tasa de aprendizaje puede modificarse a través de train.optim.lr=1e-4 . Consulte la carpeta de configuración para ver todos los argumentos.
Su primer paso debe ser verificar los paquetes instalados. Para hacerlo, puede ejecutar python pretrain.py dryrun=True , que ejecutará la verificación de cordura predeterminada para una sola iteración. A partir de ahí, puede habilitar una funcionalidad adicional. Por ejemplo, modifique la arquitectura, por ejemplo, arch=bert-original and Training Setup train=bert-original . Para realmente capacitar a un modelo de idioma, debe cambiar del conjunto de datos de verificación de cordura a al menos data=pile-readymade . Luego, elija una configuración de entrenamiento mejorada, por ejemplo, train=bert-o4 , y un diseño de modelo mejorado, por ejemplo, arch=crammed-bert .
Las fuentes de datos de data.sources Los fuentes se leerán, normalizarán y pretenderán antes de que comience la capacitación y almacenan en caché en una base de datos. Las llamadas posteriores con la misma configuración reutilizarán esta base de datos de secuencias tokenizadas. Por defecto, también se construirá y guardará un nuevo tokenizador durante este proceso. Las opciones de datos importantes son data.max_entries_in_raw_dataset MAX_ENTRIES_IN_RAW_DATASET, que define cuántos datos sin procesar se cargarán. Por ejemplo, para una gran fuente de datos como C4, solo se descargará un subconjunto de datos sin procesar. Luego, max_seq_in_tokenized_dataset cuellos de botella cuántas secuencias procesadas se almacenarán en la base de datos. Este número debe ser mayor que el número de secuencias que se espera que se lean dentro del presupuesto.
Notas adicionales:
data=pile-readymadepython pretrain.py data=... dryrun=True , que lleva el entrenamiento en seco, pero ejecuta el preprocesamiento de datos completo. Las ejecuciones posteriores pueden reutilizar los datos en caché.impl.threads . Especialmente el código de deduplicación requiere cantidades sustanciales de RAM.bookcorpus-wikipedia , que preprocesos relativamente rápido y solo luego examinar el C4 procesado y filtrado completo. Para referencia y si solo está interesado en cambiar de capacitación/arquitectura, puede encontrar algunos conjuntos de datos preprocesados aquí:
Estas fuentes de datos se pueden transmitir. Para hacerlo, Simple Set data=pile-readymade .
Los datos preprocesados son convenientes para trabajar, y creo que las modificaciones para el procesamiento y el filtrado de datos continúan siendo subexplorados en comparación con la capacitación y la arquitectura debido a esto. Puede haber más ganancias con mejores datos, que con otros ajustes, por lo que, en última instancia, es posible que desee considerar la configuración del código y el entorno para que funcione la tubería de procesamiento de datos completo.
Ahora puede encontrar un punto de control para la versión final entrenada en the-pile en https://huggingface.co/jonasgeiping/crammed-bert.
Para evaluar los modelos previos a la petróleo sobre pegamento (o algunas tareas de pegamento), use eval.py Este script busca modelos guardados en el directorio base. Dado el nombre de una ejecución anterior, este script, de forma predeterminada, recuperará el último punto de control guardado con este nombre y luego ejecutará evaluaciones.
Puede iniciar sesión en su cuenta de pesas y sesgos. Para hacerlo, simplemente modifique wandb.entity y wandb.project en la línea de comandos o en cramming/config/wandb/default.yaml .
Para replicar la receta final discutida en el documento, ejecute
python pretrain.py name=amp_b8192_cb_o4_final arch=crammed-bert train=bert-o4 data=pile-readymade
para previamente y
python eval.py eval=GLUE_sane name=amp_b8192_cb_o4_final eval.checkpoint=latest impl.microbatch_size=16 impl.shuffle_in_dataloader=True impl.compile_torch=False
para evaluar el modelo. La receta llamada "Bert abarrotada" en el documento corresponde a la arquitectura llamada crammed-bert en la configuración, entrenada con la configuración de entrenamiento bert-o4 en Data the-pile .
Para un rendimiento óptimo, debe estar en el último Pytorch Nightly y establecer las siguientes variables de inductor (que modifican la configuración torch.compile usando inductor):
max_autotune_gemm: Truemax_autotune_pointwise: Falsetriton.cudagraphs: Truetriton.cudagraph_trees: False Prueba: GPU único, configuración original de Bert:
python pretrain.py name=bert data=bookcorpus-wikipedia arch=bert-original train=bert-original budget=10000000
Multi-GPU, configuración original de Bert:
torchrun --nproc_per_node=4 --standalone pretrain.py name=bert4gpu data=bookcorpus-wikipedia arch=bert-original train=bert-original budget=10000000 impl.fullgraph=false impl._inductor_vars.triton.cudagraphs=False
Eval un punto de control de la cara de abrazos (en este ejemplo en RTE):
python eval.py eval=GLUE_sane eval/tasks=rte name=bert-finetuning eval.checkpoint=hf://bert-base-uncased impl.shuffle_in_dataloader=True impl.compile_torch=False impl.microbatch_size=16
Eval un punto de control local (Deshabilitar la compilación, que espera formas fijas en este momento):
python eval.py eval=GLUE_sane eval/tasks=rte name=NAME_OF_PRETRAINING_RUN eval.checkpoint=latest impl.shuffle_in_dataloader=True impl.compile_torch=False
Verificación de cordura para el código distribuido en la CPU:
CUDA_VISIBLE_DEVICES= torchrun --nproc_per_node=2 --standalone pretrain.py name=cpu_multi_check dryrun=True data=sanity-check-2 impl.dist_backend=gloo impl.fullgraph=false impl._inductor_vars.triton.cudagraphs=False
Se pueden encontrar ejemplos adicionales para recetas en la carpeta /scripts .
Las siguientes opciones están actualmente rotas/limitadas/trabajo en progreso. Úselos a su propia discreción. Por supuesto, cualquier contribución aquí es muy apreciada. También puede enviarme un mensaje con más preguntas sobre cualquiera de estos puntos, si desea investigarlos.
Last1.13release . Si está interesado en revivir algunas de estas opciones. No dude en abrir una solicitud de extracción con actualizaciones a la nueva base de código.Por favor, no dude en contactarnos con cualquier pregunta o abrir un problema en GitHub.