NLP nas empresas | Como eu treinei um modelo T5 em português na tarefa QA no Google Colab

Pierre Guillou
12 min readJan 27, 2022

--

T5 é um modelo Seq2Seq que pode ser ajustado para qualquer tarefa de NLP, como a tarefa de QA
T5 é um modelo Seq2Seq que pode ser ajustado para qualquer tarefa de NLP, como a tarefa de QA

Este artigo fornece acesso ao notebook, ao modelo T5 base em português ajustado na tarefa de Question-Answering (QA) a partir do dataset SQuAD 1.1 pt, e ao QA App que permite que o modelo seja usado para inferência de respostas. O trabalho foi feito utilizando apenas o Google Colab/Drive e o ambiente da Hugging Face (bibliotecas transformers e datasets, o model hub e Spaces). Esperamos que esse modelo possa ajudar qualquer pessoa interessada neste tema e que além disso, as pessoas encontrem nesse artigo todas as dicas para ajustar (gratuitamente!) qualquer modelo de NLP no Google Colab.

Sumário

  • Treinar qualquer modelo de Deep Learning nos serviços gratuitos do Google?
  • (pré-training) Várias limitações para o pré-training dos modelos de Deep Learning, em particular de linguagem natural
  • (finetuning) Possibilidade de fazer o fine-tuning dos modelos de linguagem natural existentes pelo Transfer Learning
  • Contra o problema de desconexões frequentes do Google Colab: treine seu modelo por steps, em vez de épocas
  • Caso prático com o modelo T5 na tarefa QA
    1. Configuração do(s) Google Drive
    2. Salvando resultados no Google Drive
    2.1 Conecte o disco do seu Google Drive ao notebook para armazenar permanentemente as saídas de treinamento do modelo.
    2.2 Altere os caminhos para pastas no seu Google Drive nos argumentos output_dir e logging_dir.
    3. Use uma estratégia de backup de modelos intermediários em steps, não em épocas.
    4. Continue o treinamento a partir do ultimo checkpoint.
    5. Obtenha o melhor modelo ao final do treinamento.
    6. (opção) Pare o treinamento antes do final.
  • Modelo, notebook, resultados e código para usar na produção
    - Modelo
    - Notebook
    - Resultados do treinamento
    - Código para usar o modelo para inferência na produção
  • App T5 para QA em português

Treinar qualquer modelo de Deep Learning nos serviços gratuitos do Google?

Via Google Colab e Google Drive, o Google teoricamente permite treinar qualquer modelo de Deep Learning em um GPU ou TPU (Colab) e salvá-lo gratuitamente (Drive).

Para acessar esses 2 serviços (e muitos outros como o Gmail!), tudo que precisa fazer é criar uma conta em Google Conta. Não custa nada!

Então? Basta criar um notebook no Google Colab para treinar um modelo de Deep Learning e executá-lo?

(pré-training) Várias limitações para o pré-training dos modelos de Deep Learning, em particular de linguagem natural

Na realidade, as limitações desses 2 serviços (Google Colab e Google Drive) reduzem as possibilidades de treinar um modelo de Deep Learning gratuitamente no Google Colab:

  • disco de tamanho pequeno (15 GB por conta … para salvar dados de treinamento, logs, modelos de verificação intermediários (checkpoints) durante o treinamento e o modelo final…),
  • GPU de baixa velocidade e pequena RAM (um único GPU: geralmente um NVIDIA Tesla K80 de 12 GB…) (observação: se tiver chance, um NVIDIA T4 com 16 GB de RAM)
  • acesso ao GPU limitado em duração e frequência (muitas vezes é impossível usar um GPU, sessões do Google Colab limitadas a 12 horas por notebook com interrupções frequentes que interrompem o treinamento do modelo, necessidade de ficar presente para confirmar sua presença e assim, guardar a sessão aberta…).
Mensagem no Google Colab (“Não é possível conectar ao back-end da GPU”)
Mensagem no Google Colab (“Não é possível conectar ao back-end da GPU”)
Mensagem no Google Colab (“Você ainda está ai?”)
Mensagem no Google Colab (“Você ainda está ai?”)

Em particular, os novos modelos de linguagem natural como BERT e ainda mais o T5, por seu número de parâmetros (centenas de milhões a vários bilhões de parâmetros ) e o tamanho do seu dataset de pré-training (de várias dezenas a centenas de GB de textos), não podem ser pré-treinados nesses serviços do Google.

:-(

No entanto, muitas empresas (Google, Facebook, Microsoft, Open AI…) e indivíduos já fizeram esse trabalho de pré-training em vários idiomas e disponibilizaram esses modelos de linguagem natural para download gratuito, por exemplo no model hub do Hugging Face.

:-)

Por exemplo, aqui estão alguns modelos de linguagem natural em português da Neuralmind nesse model hub:

(finetuning) Possibilidade de fazer o fine-tuning dos modelos de linguagem natural existentes pelo Transfer Learning

Assim, nesses 2 serviços (Google Colab e Google Drive) e usando técnicas de transferência de aprendizagem (Transfer Learning), é então possível ajustar (fine-tuning) as versões small, base, large desses modelos de linguagem natural para tarefas específicas (downstream tasks), como classificação, NER, QA, etc.

Por quê?

  • o tamanho do dataset de ajuste fino (fine-tuning) pode ser pequeno (da ordem de centenas de MB ou mesmo alguns MB);
  • é possível simular um grande batch (conjunto de sequências de textos) sem encher toda a RAM do GPU com acúmulo de gradiente (argumento gradient_accumulation_steps na classe TrainingArguments da biblioteca Transformers);
  • geralmente, poucas épocas são suficientes para o ajuste fino de um modelo de linguagem para uma tarefa particular (mas com a método detalhado neste post, pode usar quantas épocas quiser!).

Contra o problema de desconexões frequentes do Google Colab: treine seu modelo por steps, em vez de épocas

Legal! No entanto, ainda há um ponto-chave a ser resolvido, que é um problema inerente ao Google Colab: as desconexões frequentes.

Como veremos no estudo de caso prático no próximo parágrafo, a solução é a seguinte: deve treinar seu modelo por steps e não por épocas, e regularmente salvar seus modelos intermediários (checkpoints) no Google Drive. Et voilà!

Explicação: uma época geralmente requer um longo tempo durante o qual existe o risco de desconexão do Google Colab: ao alternar a estratégia de backup de modelos intermediários para steps, pode reduzir o tempo entre 2 modelos intermediários (checkpoints) como desejar, o que permitirá que arquive alguns antes do próximo logout do Google Colab. Além disso, permite obter mais versões do modelo (enquanto a estratégia por épocas, fornece apenas uma por época). A desvantagem é que o tempo geral de ajuste fino (fine-tuning) do modelo é maior, pois há mais avaliação do modelo.

Caso prático com o modelo T5 na tarefa QA

Vamos fazer o fine-tuning do modelo PTT5 base (T5 em português: veja o paper “PTT5: Pretraining and validating the T5 model on Brazilian Portuguese data”) para a tarefa Question-Answering (QA) no dataset SQuAD v1.1 pt do grupo “Deep Learning Brasil”.

1. Configuração do(s) Google Drive

É importante poder usar facilmente várias contas do Google Drive. Por quê? Além dos problemas de desconexão do Google Drive que abordaremos no ponto 2, há o problema da limitação de uso do GPU no Google Colab: seu notebook não pode funcionar por mais de 12 horas com um GPU. Além disso, notamos que o Google Colab impede o uso de um GPU após usá-lo por algumas horas. Tem que esperar 1 dia ou mais para acessá-lo novamente.

A solução é a seguinte:

  1. na sua conta do Google Drive, crie uma pasta com o nome do seu modelo. Por exemplo, como estamos usando o modelo base PTT5 aqui armazenado no model hub da Hugging Face, seu “nome” é unicamp-dl/ptt5-base-portuguese-vocab. Então vamos chamar nossa pasta de “ptt5-base-portuguese-vocab”.
  2. Nessa pasta, vamos colocar nosso notebook (aqui: HuggingFace_Notebook_t5-base-portuguese-vocab_question_answering_QA_squad_v11_pt.ipynb).

Pronto. Se aparecer o problema de acessar um GPU, aqui está o método a seguir:

  1. Crie uma nova conta no Google Drive (ou seja, uma nova conta Gmail)
  2. Da sua primeira conta, compartilhe a pasta “ptt5-base-portuguese-vocab” com o novo gmail da forma seguinte:
Como partilhar uma pasta entre 2 contas Google Drive

3. Na sua nova conta, clique no link “Compartilhados comigo” (“Shared with me”), abra o menu a partir da pasta “ptt5-base-portuguese-vocab” e clique no link “Adicionar atalho ao Google Drive” (“Add a shortcut to Drive”). Escolhe a pasta “Meu Drive” (“My Drive”) e valide pelo botão “Adicionar atalho” (“Add shortcut”).

Como adicionar um atalho no “Meu Drive” para a sua pasta partilhada no Google Drive
Como adicionar um atalho no “Meu Drive” para a sua pasta partilhada no Google Drive

Et voilà! Agora, tem 2 contas do Google Drive para rodar seu notebook, contas que tem acesso à mesma pasta do seu modelo. Na verdade, pode rodar o seu notebook de qualquer uma e, assim, superar o problema de acessar um GPU (observação: pode usar esse método com quantas contas do Google Drive quiser!).

2. Salvando resultados no Google Drive

Para conseguir o fine-tuning seguindo as dicas precedentes, precisar prestar atenção ao ponto seguinte: acesso ao GPU limitado em duração e frequência (sessões do Google Colab limitadas a 12 horas por notebook com interrupções frequentes que interrompem o treinamento do modelo).

Observação: se usar a biblioteca Transformers da Hugging Face, precisa configurar a classe Seq2SeqTrainingArguments (da classe TrainingArguments) e a classe QuestionAnsweringSeq2SeqTrainer (adaptação da classe Seq2SeqTrainer da classe Trainer) do treinamento do seu modelo com as seguintes especificações.

Se não alterar os caminhos para pastas nos argumentos output_dir e logging_dir da classe TrainingArguments, os pontos de verificação do modelo ou checkpoints (arquivos do modelo com tempos de entrada diferentes) e logs (informações sobre a avaliação do modelo) serão temporariamente arquivados no Google Colab. Por isso, ao menor problema de desconexão, eles serão perdidos!

Portanto, é recomendado de seguir este método:

2.1 Conecte o disco do seu Google Drive ao notebook para armazenar permanentemente as saídas de treinamento do modelo.

Veja o código a seguir a colocar no topo do notebook para fazer isso:

from google.colab import drive
drive.mount('/content/drive', force_remount=True)

2.2 Altere os caminhos para pastas no seu Google Drive dos argumentos output_dir e logging_dir.

Veja o código a seguir para fazer isso:

import pathlib
from pathlib import Path
# name of folder principal
model_checkpoint = "unicamp-dl/ptt5-base-portuguese-vocab"
model_name = model_checkpoint.split("/")[-1]
# hyperparameters
num_train_epochs = 10
learning_rate = 1e-4
# creation of folders checkpoints and logs
folder_model = 'e' + str(num_train_epochs) + '_lr' + str(learning_rate)
output_dir = '/content/drive/MyDrive/' + str(model_name) + '/checkpoints/' + folder_model
Path(output_dir).mkdir(parents=True, exist_ok=True)
logging_dir = '/content/drive/MyDrive/' + str(model_name) + '/logs/' + folder_model
Path(logging_dir).mkdir(parents=True, exist_ok=True)

3. Use uma estratégia de backup de modelos intermediários em steps, não em épocas.

O treinamento de um modelo é feito em batch (aqui, número de sequências de texto a serem processadas em paralelo no GPU). Uma época (conjunto de sequências de texto de treinamento) corresponde a num_steps x batch com:

num_steps = numero de sequências de texto do dataset de treinamento dividido por o numero de sequências de texto dentro de um batch

O treinamento de um modelo é feito por unidade. Pode ser uma época (método padrão) ou uma série de steps (número inteiro positivo), com uma avaliação de seu desempenho por meio do dataset de validação no final de cada unidade.

Assim, se uma época corresponde a 2000 steps por exemplo, podemos definir num_steps a 1000, o que torna possível avaliar o modelo duas vezes por época.

Se ocorrer um problema como a desconexão do Google Colab, não há problema: será suficiente continuar o treinamento do último checkpoint :-) E voilà!

Observação: como após cada avaliação, o checkpoint correspondente (o modelo naquele momento) é salvo no diretório output_dir localizado no Google Drive. O número de checkpoints salvos depende do argumento save_total_limit. Como o Google Drive é limitado a 15 GB, a recomendação é arquivar o número mínimo de checkpoints, por exemplo 3. Usando o argumento save_total_limit (por exemplo, 3), o script guardará apenas os save_total_limit últimos checkpoints (incluindo o checkpoint com a melhor avaliação). No entanto, notamos que esse apagamento nem sempre é bem feito no Google Drive. Portanto, é melhor verificá-lo de tempos em tempos e excluir manualmente os checkpoints (que tem de ser apagados), se necessário.

Veja o código a seguir para treinar o modelo por steps, e não por épocas:

# do training and evaluation
do_train = True
do_eval= True
# batch
batch_size = 4
gradient_accumulation_steps = 3
per_device_train_batch_size = batch_size
# true training batch: batch_size x gradient_accumulation_steps
per_device_eval_batch_size = batch_size*16
# in evaluation, there is no backward: it means there is more GPU available
# LR, wd, epochs
learning_rate = 1e-4
weight_decay = 0.01
num_train_epochs = 10
fp16 = True
# logs
logging_strategy = "steps"
logging_first_step = True
logging_steps = 3000 # if logging_strategy = "steps"
eval_steps = logging_steps
# checkpoints
evaluation_strategy = logging_strategy
save_strategy = logging_strategy
save_steps = logging_steps
save_total_limit = 3
# best model
load_best_model_at_end = True
metric_for_best_model = "f1" #"loss"
if metric_for_best_model == "loss":
greater_is_better = False
else:
greater_is_better = True
# evaluation
num_beams = 1
# Training arguments
from transformers import Seq2SeqTrainingArguments
training_args = Seq2SeqTrainingArguments(
output_dir=output_dir,
do_train=do_train,
do_eval=do_eval,
evaluation_strategy=evaluation_strategy,
learning_rate=learning_rate,
per_device_train_batch_size=per_device_train_batch_size,
per_device_eval_batch_size=per_device_eval_batch_size,
gradient_accumulation_steps=gradient_accumulation_steps,
weight_decay=weight_decay,
num_train_epochs=num_train_epochs,
predict_with_generate=True,
save_steps=save_steps,
save_total_limit=save_total_limit,
save_strategy=save_strategy,
load_best_model_at_end=load_best_model_at_end,
metric_for_best_model=metric_for_best_model,
greater_is_better=greater_is_better,
logging_dir=logging_dir, # directory for storing logs
logging_strategy=logging_strategy,
logging_steps=logging_steps, # if logging_strategy = "steps"
fp16=fp16,
push_to_hub=False,
)

4. Continue o treinamento a partir do ultimo checkpoint.

Se o treinamento foi realizado em steps, seu modelo é registrado com mais frequência nos checkpoints. Para continuar desde o último checkpoint (por exemplo, se houve uma desconexão), basta usar o seguinte código (claro, após executar o código anterior no notebook):

# let's say that our last checkpoint is "checkpoint-6000"
checkpoint_dir = str(output_dir + "/checkpoint-6000")
trainer.train(checkpoint_dir)

5. Obtenha o melhor modelo ao final do treinamento.

No código do ponto 3, existem parâmetros que correspondem ao melhor modelo. Permitem ao final do treinamento, recuperar o checkpoint que teve a melhor métrica (por exemplo, f1). Aqui está a lista de parâmetros a serem usados ​​em Seq2SeqTrainingArguments para fazer isso:

# best model
load_best_model_at_end = True
metric_for_best_model = "f1" #"loss"
if metric_for_best_model == "loss":
greater_is_better = False
else:
greater_is_better = True

6. (opção) Pare o treinamento antes do final.

Ao usar um ambiente com limitações (como o Google Colab), pode ser interessante não esperar o final do número total de steps (ou épocas se for a unidade de treinamento) se a métrica do dataset de validação não melhorar para um número definido de checkpoints. Esse é o parâmetro early_stopping_patience do Seq2SeqTrainer. Aqui está o codigo a seguir para fazer isso:

from transformers.trainer_callback import EarlyStoppingCallbackearly_stopping_patience = save_total_limit# Initialize our Trainer
trainer = QuestionAnsweringSeq2SeqTrainer(
model=model,
args=training_args,
train_dataset=train_dataset if do_train else None,
eval_dataset=eval_dataset if do_eval else None,
eval_examples=eval_examples if do_eval else None,
tokenizer=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
post_process_function=post_processing_function,
callbacks=[EarlyStoppingCallback(early_stopping_patience=early_stopping_patience)],
)

Modelo, notebook, resultados e código para usar na produção

Modelo

O nosso modelo T5 base em português ajustado na tarefa QA está disponível online no model hub da Hugging Face:

Notebook

O notebook está no github: HuggingFace_Notebook_t5-base-portuguese-vocab_question_answering_QA_squad_v11_pt.ipynb

Resultados do treinamento

- f1: 79.3
- exact_match: 67.3983

Código para usar o modelo para inferência na produção

# install pytorch: check https://pytorch.org/
# !pip install transformers
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

# model & tokenizer
model_name = "pierreguillou/t5-base-qa-squad-v1.1-portuguese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)

# parameters
max_target_length=32
num_beams=1
early_stopping=True

input_text = 'question: Quando foi descoberta a Covid-19? context: A pandemia de COVID-19, também conhecida como pandemia de coronavírus, é uma pandemia em curso de COVID-19, uma doença respiratória aguda causada pelo coronavírus da síndrome respiratória aguda grave 2 (SARS-CoV-2). A doença foi identificada pela primeira vez em Wuhan, na província de Hubei, República Popular da China, em 1 de dezembro de 2019, mas o primeiro caso foi reportado em 31 de dezembro do mesmo ano.'
label = '1 de dezembro de 2019'

inputs = tokenizer(input_text, return_tensors="pt")

outputs = model.generate(inputs["input_ids"],
max_length=max_target_length,
num_beams=num_beams,
early_stopping=early_stopping
)
pred = tokenizer.decode(outputs[0], skip_special_tokens=True, clean_up_tokenization_spaces=True)

print('true answer |', label)
print('pred |', pred)

Pode usar também o método pipeline() da biblioteca transformers.

!pip install transformers
import transformers
from transformers import pipeline
# model
model_name = "pierreguillou/t5-base-qa-squad-v1.1-portuguese"
# parameters
max_target_length=32
num_beams=1
early_stopping=True
clean_up_tokenization_spaces=True
input_text = 'question: Quando foi descoberta a Covid-19? context: A pandemia de COVID-19, também conhecida como pandemia de coronavírus, é uma pandemia em curso de COVID-19, uma doença respiratória aguda causada pelo coronavírus da síndrome respiratória aguda grave 2 (SARS-CoV-2). A doença foi identificada pela primeira vez em Wuhan, na província de Hubei, República Popular da China, em 1 de dezembro de 2019, mas o primeiro caso foi reportado em 31 de dezembro do mesmo ano.'
label = '1 de dezembro de 2019'
text2text = pipeline(
"text2text-generation",
model=model_name,
max_length=max_target_length,
num_beams=num_beams,
early_stopping=early_stopping,
clean_up_tokenization_spaces=clean_up_tokenization_spaces
)
pred = text2text(input_text)print('true answer |', label)
print('pred |', pred)

App T5 base para QA em português

O Hugging Face Spaces permite criar e fazer upload de App usando modelos transformers. Assim, pudemos disponibilizar um App a todos para usar o modelo T5 base ajustado no dataset SQuAD 1.1 em português na tarefa QA.

Aqui está um GIF animado desse QA App:

QA App de Pierre Guillou para utilizar o modelo T5 base treinado no dataset SQuAD 1.1 em português (gif animado)
QA App de Pierre Guillou para utilizar o modelo T5 base treinado no dataset SQuAD 1.1 em português (gif animado)

Sobre o autor: Pierre Guillou é Head of AI na startup de HealthTech Laudite (Brasil), e consultor de IA no Brasil e na França. Entre em contato com ele por meio de seu perfil no LinkedIn.

--

--