Resumo da otimização do algoritmo - Transofomer evita memória de vídeo insuficiente e tempo de treinamento excessivo

Método da Transofomer para evitar memória de vídeo insuficiente e tempo de treinamento excessivo

Desde o surgimento do BERT, o campo nlp entrou na era dos modelos grandes. Embora o efeito dos modelos grandes seja bom, afinal, nem todos possuem recursos ricos de GPU. Eles costumam ser esticados durante o treinamento e há problemas de falta de memória de memória, ou treinamento. O tempo é muito, muito longo. Portanto, o principal problema a ser resolvido neste artigo é como treinar o modelo grande na biblioteca de transformadores sob a condição de recursos limitados da GPU.

Embora os Transformers de código aberto do Huggingface tenham alcançado um sucesso incrível em tarefas de processamento de linguagem natural (NLP), devido ao grande número de parâmetros de modelo internos, mesmo o uso de GPUs para treinamento ou implantação ainda é muito desafiador, porque usar tais Quando um modelo grande é usado para treinamento ou raciocínio, é fácil sofrer de memória insuficiente (OOM) e tempo de treinamento excessivo.

No entanto, existem muitas maneiras de evitar memória de vídeo insuficiente e tempo de treinamento excessivo. A principal contribuição deste artigo é apresentar os princípios desses métodos e como implementá-los, incluindo os seguintes métodos:

  1. Acumulação de gradiente
  2. Congelando
  3. Precisão Mista Automática
  4. Otimizadores de 8 bits
  5. Ponto de verificação de gradiente
  6. Tokenizadores rápidos
  7. Preenchimento Dinâmico
  8. Preenchimento Dinâmico Uniforme

Entre eles, 1-5 são métodos gerais para redes neurais, que podem ser usados ​​para otimização de desempenho de qualquer rede, e 6-8 são métodos de otimização de desempenho para o campo nlp.

acúmulo de gradiente

A ideia por trás da acumulação de gradiente é muito simples, para simular lotes maiores. Às vezes, para uma melhor convergência ou melhor desempenho, é necessário usar grandes lotes para treinamento, porém, isso geralmente requer uma memória de vídeo maior. Uma possível solução para este problema é a utilização de lotes menores, porém, por um lado, o treinamento com pequenos lotes aumenta o tempo de treinamento e inferência e, por outro lado, o algoritmo gradiente descendente é muito sensível à escolha do tamanho do lote, e pequenos lotes podem levar a convergência instável e desempenho reduzido. Portanto, podemos executar a propagação direta e a retropropagação várias vezes primeiro, para que os gradientes possam ser acumulados. Quando tivermos gradientes de cálculo suficientes, podemos otimizar os parâmetros, de modo a usar uma pequena memória de vídeo para simular o efeito de grandes lotes e o tempo de treinamento não aumentará significativamente.
insira a descrição da imagem aqui

congelar

Congelar é um método muito eficaz. Ao cancelar o cálculo do gradiente em algumas camadas do modelo de cálculo (como a camada de incorporação, as primeiras camadas de bert), ele pode acelerar muito a velocidade de treinamento e reduzir o uso de memória, e há quase não há perda de desempenho do modelo.

Um fato bem conhecido no aprendizado profundo é que a camada inferior da rede aprende os recursos gerais dos dados de entrada, enquanto a camada superior da rede aprende os recursos de alto nível específicos da tarefa de destino. modelo pré-treinado, os parâmetros da camada inferior da rede geralmente não são muito necessários. Mudança, estes são de conhecimento geral, o que precisa ser aprendido são os parâmetros da camada superior, ao usar algum algoritmo de otimização (como SGD, AdamW ou RMSprop) para executar a etapa de otimização, o gradiente da camada inferior da rede é muito pequeno, portanto os parâmetros são quase Isso também é conhecido como desaparecimento de gradiente, portanto, em vez de gastar muito tempo e poder de computação para calcular esses gradientes "inúteis" na parte inferior e, para otimizar esses parâmetros com pequenos gradientes, é melhor congelá-los diretamente. O cálculo dos gradientes também não é otimizado.

O PyTorch fornece uma API confortável para desativar os cálculos de gradiente, que podem ser definidos por meio da propriedade require_grad de arch.Tensor.

Precisão Mista Automática

A precisão mista automática (AMP) é outra maneira de reduzir o consumo de memória e o tempo de treinamento sem perder a qualidade final, proposta pelos pesquisadores da NVIDIA e da Baidu no documento Mixed Precision Training em 2017. A ideia-chave por trás desse método é manter os gradientes e parâmetros do modelo na memória usando menor precisão, ou seja, em vez de usar precisão total (float32), use meia precisão (por exemplo, float16) para manter os tensores na memória. No entanto, ao computar gradientes com menor precisão, alguns valores podem ser tão pequenos que são considerados zero, fenômeno conhecido como “overflow”. Para evitar o "estouro", os autores do artigo original propõem um método de escalonamento de gradiente.

PyTorch fornece um pacote desde a versão 1.6: arch.cuda.amp, com as funções necessárias para usar a precisão mista automática (da precisão reduzida à escala de gradiente), a precisão mista automática é implementada como um gerenciador de contexto, para que possa ser inserido a qualquer momento e em qualquer lugar nos scripts de treinamento e inferência
insira a descrição da imagem aqui

otimizador de 8 bits

A ideia dos Otimizadores de 8 bits é semelhante à precisão mista automática (os parâmetros e gradientes do modelo são salvos com menor precisão), mas os Otimizadores de 8 bits também permitem que o estado do otimizador seja salvo com baixa precisão. O autor (Meta Research) introduziu otimizadores de 8 bits em detalhes no artigo original Otimizadores de 8 bits por meio de quantização em bloco, mostrando que otimizadores de 8 bits reduzem significativamente o uso de memória e aceleram ligeiramente o treinamento. Além disso, os autores estudam o efeito de diferentes configurações de hiperparâmetros, mostrando que o efeito de Otimizadores de 8 bits em diferentes parâmetros de taxa de aprendizado, beta e decaimento de peso é estável, sem degradar o desempenho ou afetar a convergência. Portanto, o autor fornece uma biblioteca de alto nível para o otimizador de 8 bits chamada bitsandbytes.

ponto de verificação de gradiente

Às vezes, mesmo depois de usar os métodos acima, a memória de vídeo pode não ser suficiente, especialmente se o modelo for grande o suficiente. Então o Gradient Checkpointing (Gradient Checkpointing) é o truque da parte inferior da caixa. Este método é a primeira vez em Training Deep Nets With Sublinear Memory Cost. O autor mostra que o gradient checkpoint pode reduzir significativamente a taxa de utilização da memória de vídeo , de reduzido a , onde n é o modelo o número de camadas. Essa abordagem permite treinar modelos grandes em uma única GPU ou fornecer mais memória para aumentar o tamanho do lote para uma convergência melhor e mais rápida. A ideia por trás do ponto de verificação de gradiente é calcular gradientes em pequenos blocos enquanto remove gradientes desnecessários da memória durante a propagação direta e reversa, reduzindo assim a utilização da memória, mas essa abordagem requer mais etapas de computação para reproduzir todo o gráfico de retropropagação, na verdade, é um método de troca tempo para o espaço
insira a descrição da imagem aqui

Há também uma implementação de checkpoints de gradiente no framework PyTorch, por meio dessas duas funções: arch.utils.checkpoint.checkpoint e arch.utils.checkpoint.checkpoint_sequential

Aqui está uma introdução ao ponto de verificação de gradiente no site oficial da tocha:

  • O ponto de verificação de gradiente funciona trocando computação por memória. Em vez de armazenar todas as ativações intermediárias de todo o gráfico de computação para computação reversa, a parte do ponto de verificação não salva as ativações intermediárias, mas as recalcula durante o processo reverso. Pode ser aplicado a qualquer parte do modelo. Especificamente, no passe para frente, a função se comportará como arch.no_grad(), ou seja, nenhuma ativação intermediária será armazenada. No entanto, o avanço salva a tupla de entrada e os parâmetros da função. Durante a retropropagação, as entradas e funções salvas são recuperadas e, em seguida, a função é propagada para frente novamente, agora acompanhando as ativações intermediárias e, em seguida, usando esses valores de ativação para calcular gradientes.

tokenizador rápido

O HuggingFace Transformers fornece dois tipos de tokenizers: tokenizer básico e tokenizer rápido. A principal diferença entre eles é que o tokenizador rápido é escrito em Rust, porque o Python é muito lento em loops, mas os loops são usados ​​ao tokenizar. O tokenizer rápido é um método muito simples que nos permite ganhar velocidade adicional ao tokenizar. Também é muito simples usar o tokenizer rápido, basta alterar o valor use_fast do método from_pretrained em Transformers.AutoTokenizer para True

insira a descrição da imagem aqui

preenchimento dinâmico

De um modo geral, o modelo é treinado com lotes de entradas de dados, e cada entrada do lote deve ter um tamanho fixo, ou seja, um lote de dados deve ser representado por uma matriz, e todos os lotes de dados têm o mesmo tamanho. Um tamanho fixo geralmente é escolhido com base na distribuição de comprimentos no conjunto de dados, no número de recursos e em outros fatores. Em tarefas NLP, o tamanho da entrada é chamado de comprimento do texto ou comprimento máximo. No entanto, textos diferentes têm comprimentos diferentes e, para lidar com essa situação, os pesquisadores propõem marcas de preenchimento e truncamento. O truncamento é usado quando o comprimento máximo é menor que o comprimento do texto de entrada, portanto, alguns tokens são removidos. Quando o comprimento do texto de entrada for menor que o comprimento máximo, os tokens de preenchimento, como [PAD], serão adicionados ao final do texto de entrada. É importante observar que os tokens de preenchimento não devem ser incluídos no cálculo de perda de algumas tarefas (como modelo de construção de linguagem mascarada ou reconhecimento de entidade nomeada)

insira a descrição da imagem aqui

No entanto, os marcadores preenchidos têm desvantagens significativas. Por exemplo, quando o texto de entrada é muito curto em relação ao comprimento máximo selecionado, a eficiência é muito baixa e mais memória adicional é necessária. Por exemplo, eu tenho um comprimento de texto de 512 e, em seguida, outros comprimentos de texto estão em torno de 10, então if max Se seq for definido como 512, isso levará a muitos cálculos inválidos. Para evitar operações de computação adicionais, os pesquisadores propuseram um método muito eficaz, que é preencher o lote de entradas até o comprimento máximo de entrada do lote, conforme mostrado na figura abaixo, esse método pode aumentar a velocidade de treinamento em 35% ou mesmo 50%, é claro, o efeito de aceleração desse método depende do tamanho do lote e da distribuição do comprimento do texto. Quanto menor o lote, mais óbvio é o efeito de aceleração e mais desigual é a distribuição do comprimento do texto , melhor o efeito de aceleração.

insira a descrição da imagem aqui

Preenchimento Dinâmico Uniforme

A ideia é classificar o texto de acordo com o comprimento do texto ao dividir o lote, para que o comprimento do texto no mesmo lote seja quase o mesmo. Essa abordagem é muito eficiente e requer menos computação do que o preenchimento dinâmico, seja durante o treinamento ou na inferência. No entanto, não é recomendado usar preenchimento dinâmico uniforme durante o treinamento, porque é melhor embaralhar os dados durante o treinamento, mas você pode considerar fazer isso se precisar raciocinar muito texto de cada vez durante o raciocínio

insira a descrição da imagem aqui

Resumo da população dinâmica uniforme A otimização de memória e tempo é uma etapa necessária no desenvolvimento de modelos, mesmo em GPUs modernas, portanto, este artigo apresenta os métodos mais poderosos e populares para acelerar o treinamento e reduzir o consumo de memória para modelos grandes, como transformadores

insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/weixin_44077556/article/details/128115413
Recomendado
Clasificación