Este repositório contém código para replicar nossa pesquisa descrita em "Craming: Treinando um modelo de idioma em uma única GPU em um dia". Experimentamos o modelo de idioma que prede um modelo do tipo Bert com computação limitada, imaginando "quão ruim pode realmente ser"?
Você pode encontrar nosso artigo aqui: https://arxiv.org/abs/2212.14034, e o resumo abaixo:
As tendências recentes na modelagem de idiomas se concentraram no aumento do desempenho por meio da escala e resultaram em um ambiente em que os modelos de linguagem de treinamento está fora do alcance para a maioria dos pesquisadores e profissionais. Enquanto a maioria na comunidade está perguntando como ultrapassar os limites da computação extrema, fazemos a pergunta oposta:
Até onde podemos chegar com uma única GPU em apenas um dia?
Investigamos o desempenho a jusante alcançável com um modelo de idioma baseado em transformador treinado completamente do zero com modelagem de idiomas mascarada para um único dia em uma única GPU de consumidor . Além de re-analisar quase todos os componentes do oleoduto pré-treinamento para esse cenário e fornecer um pipeline modificado com desempenho próximo a Bert, investigamos por que a redução é difícil e quais modificações realmente melhoram o desempenho nesse cenário. Fornecemos evidências de que, mesmo nesse ambiente restrito, o desempenho segue de perto as leis de escala observadas em configurações de grande computação. Através das lentes das leis de dimensionamento, categorizamos uma série de melhorias recentes no treinamento e na arquitetura e discutimos seu mérito e aplicabilidade prática (ou falta dela) para a configuração limitada de computação.
Você precisa de Pytorch 2.0 para executar o novo código. Se você deseja permanecer no Pytorch 1.*, pode verificar a tag Last1.13release . O novo modelo, treinado com a nova base de código é 1-2% melhor na cola com o mesmo orçamento. O ponto de verificação pode ser encontrado em https://huggingface.co/jonasgeiping/crammed-bert. O antigo ponto de verificação agora é https://huggingface.co/jonasgeiping/crammed-bert-legacy.
Além disso, o pré -processamento de dados melhorou, agora você pode transmitir dados diretamente do HuggingFace, a partir do upload em https://huggingface.co/datasets/jonasgeiping/the_pile_wordPieCex32768_2efdb9d060d1ae95faf9522768_2efdb9d060d1ae95FAF9522768_2.
Contexto:
Execute pip install . Para instalar todas as dependências.
torch (pelo menos versão 2.1)transformers , tokenizers , datasets , evaluatehydra-corepsutil , pynvml , safetensorseinops pip install . Para instalar todos os pacotes e scripts.curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh , então git clone https://github.com/google-research/deduplicate-text-datasets/tree/dev-v1 e depois execute cargo install --target-dir ../cramming/dedupPara verificar uma instalação mínima, você pode executar
python pretrain.py name=test arch=hf-bert-base train=bert-base data=sanity-check-2 dryrun=True impl.microbatch_size=2
Este comando pré-processos um pequeno conjunto de dados de verificação de sanidade e executa uma única etapa de treinamento.
Use o script pretrain.py para pré -atrelar com computação limitada. Este repositório usa o Hydra (https://hydra.cc/docs/intro/), para que todos os campos em cramming/config possam ser modificados na linha de comando. Por exemplo, o budget pode ser modificado fornecendo budget=48 como argumento adicional (para executar por 48 horas), ou a taxa de aprendizado pode ser modificada via train.optim.lr=1e-4 . Confira a pasta de configuração para ver todos os argumentos.
Seu primeiro passo deve ser verificar os pacotes instalados. Para fazer isso, você pode executar python pretrain.py dryrun=True , que executará a verificação de sanidade padrão para uma única iteração. A partir daí, você pode ativar a funcionalidade adicional. Por exemplo, modifique a arquitetura, por exemplo, arch=bert-original e treinamento de configuração de treinamento train=bert-original . Para realmente treinar um modelo de idioma, você precisa se afastar do conjunto de dados de verificação de sanidade para pelo menos data=pile-readymade . Em seguida, escolha uma configuração de treinamento aprimorada, por exemplo, train=bert-o4 e um layout de modelo aprimorado, por exemplo, arch=crammed-bert .
As fontes de dados de data.sources . As chamadas subsequentes com a mesma configuração reutilizarão esse banco de dados de sequências tokenizadas. Por padrão, um novo tokenizador também será construído e salvo durante esse processo. As opções de dados importantes são data.max_entries_in_raw_dataset , que define quanto dados brutos serão carregados. Por exemplo, para uma grande fonte de dados como C4, apenas um subconjunto de dados brutos será baixado. Então, max_seq_in_tokenized_dataset gargalos de quantas seqüências processadas serão armazenadas no banco de dados. Esse número deve ser maior que o número de seqüências que devem ser lidas dentro do orçamento.
Notas adicionais:
data=pile-readymadepython pretrain.py data=... dryrun=True , que secar o treinamento, mas executa o pré-processamento de dados completos. As execuções posteriores podem reutilizar os dados em cache.impl.threads . Especialmente o código de desduplicação requer quantidades substanciais de RAM.bookcorpus-wikipedia , que pré-processam de forma comparativamente rápida e só então examinava o C4 processado e filtrado completo. Para referência e se você estiver interessado apenas em mudar de treinamento/arquitetura, poderá encontrar alguns conjuntos de dados pré -processados aqui:
Essas fontes de dados podem ser transmitidas. Para fazer isso, data=pile-readymade .
Os dados pré-processados são convenientes para trabalhar, e acho que as modificações no processamento e filtragem de dados continuam sendo subexploradas em comparação com o treinamento e a arquitetura por causa disso. Pode haver mais ganhos a serem obtidos com melhores dados do que com outros ajustes; portanto, você pode considerar a configuração do código e do ambiente para que o pipeline de processamento de dados completo funcione.
Agora você pode encontrar um ponto de verificação para a versão final treinada na the-pile em https://huggingface.co/jonasgeiping/crammed-bert.
Para avaliar modelos pré -ridicularizados em cola (ou algumas tarefas de cola), use eval.py Este script procura modelos salvos no diretório base. Dado o nome de uma execução anterior, esse script, por padrão, recuperará o ponto de verificação mais recente salvo com esse nome e executará avaliações.
Você pode registrar as execuções para sua conta de pesos e preconceitos. Para fazer isso, basta modificar wandb.entity e wandb.project na linha de comando ou em cramming/config/wandb/default.yaml .
Para replicar a receita final discutida no artigo, execute
python pretrain.py name=amp_b8192_cb_o4_final arch=crammed-bert train=bert-o4 data=pile-readymade
para pré -atrelar e
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 avaliar o modelo. A receita chamada "Crammed Bert" no artigo corresponde à arquitetura chamada crammed-bert na configuração, treinada com a configuração de treinamento bert-o4 na the-pile dados.
Para um desempenho ideal, você precisa estar no mais recente Pytorch Nightly e definir as seguintes variáveis do indutor (que modificam a configuração torch.compile usando o Indutor):
max_autotune_gemm: Truemax_autotune_pointwise: Falsetriton.cudagraphs: Truetriton.cudagraph_trees: False Pré -treinamento: GPU único, configurações originais de Bert:
python pretrain.py name=bert data=bookcorpus-wikipedia arch=bert-original train=bert-original budget=10000000
Multi-GPU, configurações originais 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
Avalie um ponto de verificação Huggingface (neste exemplo no 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
Avalie um ponto de verificação local (desativar a compilação, que espera formas fixas agora):
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
Sanidade Verifique o código distribuído na 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
Exemplos adicionais para receitas podem ser encontrados na pasta /scripts .
Atualmente, as seguintes opções estão quebradas/limitadas/em andamento. Use -os a seu próprio critério. Obviamente, quaisquer contribuições aqui são muito apreciadas. Você também pode me enviar uma mensagem com mais perguntas sobre qualquer um desses pontos, se quiser analisá -los.
Last1.13release . Se você estiver interessado em reviver algumas dessas opções. Sinta -se à vontade para abrir uma solicitação de tração com atualizações para a nova base de código.Por favor, não hesite em entrar em contato conosco com qualquer dúvida ou abrir um problema no Github.