NLP nas empresas | Como ajustar um modelo de linguagem natural como BERT a um novo domínio linguístico com um Adapter?

Pierre Guillou
9 min readJul 5, 2021
Um modelo BERT com ajuste fino no dataset SQuAD 1.1 pt para a tarefa MLM (Masked Language Model) usando um adapter

Seguindo nosso artigo apresentando os adapters da biblioteca de adapter-transformers e seus diversos interesses para empresas e organizações que desejam utilizar modelos de Inteligência Artificial (IA) para automatizar seus processos de NLP (Natural Language Processing) internos e externos, estamos publicando uma série de artigos acompanhados de notebooks e/ou scripts que são tutoriais que permitem implementar os adapters em seus negócios e atividades. Começamos essa série com este artigo sobre o lang adapter que permite ajustar um modelo de linguagem natural como BERT a qualquer domínio linguístico.

NLP nas empresas | Como ajustar um modelo de linguagem natural como BERT para a tarefa de classificação de tokens (NER) com um Adapter?

NLP nas empresas | Como ajustar um modelo de linguagem natural como BERT para a tarefa de Question-Answering (QA) com um Adapter?

NLP nas empresas | Como criar um modelo BERT de Question-Answering (QA) de desempenho aprimorado com AdapterFusion?

NLP nas empresas | Adapter-Transformers Para Dummies

[ post e notebook atualizados no dia 14 de julho de 2021 ]

Sumário

  • Contexto
  • Modelo de linguagem natural ajustado a um novo domínio
  • Tutorial | Ajusto fino do BERT geral em português no domínio dos textos do dataset SQuAD 1.1 em português
    — Notebook language_modeling_adapter.ipynb
    — Mudanças principais em notebooks e scripts originais
    — Configuração do lang adapter e resultados de treinamento dos modelos
    — Número de parâmetros do modelo com um lang adapter
  • Uso do modelo com lang adapter

Contexto

No artigo “NLP nas empresas | Uma solução para colocar os modelos BERT em produção com Adapters para transformers”, apresentamos a biblioteca adapter-transformers que permite treinar módulos chamados adapter a partir de um modelo transformer do tipo BERT sem alterar os valores de seus embeddings, nem os dos parâmetros de suas camadas.

O interesse é imediato: assim, é possível treinar tantos adapters quanto uma empresa ou organização tenha tarefas de NLP (Natural Language Processing) para realizar em um determinado idioma e isso a partir do mesmo modelo de linguagem natural. Na produção, apenas esse modelo deve ser armazenado e acessível por meio de uma API, bem como os vários adapters.

Essa solução simplifica muito o uso desses diferentes modelos de NLP (um modelo = modelo original + adapter), pois apenas um modelo de linguagem natural deve ser armazenado (o modelo original) mais os adapters (o peso de um lang adapter é apenas entre 6 e 13% do peso do modelo original).

Imagine se uma empresa ou organização tivesse que arquivar tantos modelos originais ajustados quanto tem tarefas de NLP quando um modelo BERT large pesa mais de 1,3 GB …

Modelo de linguagem natural ajustado a um novo domínio

Na Internet hoje é fácil baixar um modelo de linguagem natural como o BERT que já é treinado em sua língua. Por exemplo, existe o modelo BERT base em português da Neuralmind e o modelo BERT large em português da Neuralmind que estão no hub de modelos de Hugging Face.

Esses modelos BERT foram treinados a partir de um corpo geral de textos em português (BrWac). Isso significa que esses modelos aprenderam um conhecimento geral de português. Se sua empresa ou organização trabalha com documentos de um campo linguístico específico, como a saúde, o jurídico, etc. é altamente recomendável ajustar o modelo BERT geral que vai usar ao seu domínio linguístico antes de fazer o seu ajuste fino para realizar tarefas específicas de NLP.

Se o ideal fosse fazê-lo a partir de um vocabulário extraído desse domínio específico, esse processo de ajuste fino requer vários GB de textos (e, portanto, grandes meios de computação com GPUs).

Se for como a maioria das empresas ou organizações e seu conjunto de dados for muito menor, o ajuste fino do modelo de linguagem natural original (o BERT base or large em português da Neuralmind aqui) é possível enquanto mantém o seu vocabulário. E isso pode ajudar a obter um modelo de linguagem natural mais eficiente para as tarefas de NLP no seu domínio linguístico.

Assim, 2 possibilidades se apresentam:

  • ou ajusta todos os embeddings e parâmetros do modelo original: este é o método clássico para o qual existe, por exemplo, um notebook e um script da Hugging Face. O problema já mencionado é que usará tantos modelos em produção quantas tarefas de NLP tiver;
  • ou treina apenas um adapter de idioma (lang adapter): este é o método por meio da biblioteca adapter-transformers

Tutorial | Ajusto fino do BERT geral em português no domínio dos textos do dataset SQuAD 1.1 em português

Notebook language_modeling_adapter.ipynb

Estamos usando aqui o dataset SQuAD 1.1 em português (versão em português do dataset SQuAD v1.1 inglês cuja tradução foi feita pelo grupo Deep Learning Brasil: squad-pt.tar.gz no Google Drive (fonte)) não para treinar o modelo na tarefa de perguntas e respostas (QA: Question Answering), mas para especializar o modelo de linguagem natural para as peculiaridades linguísticas desse dataset (pode fazer o mesmo com qualquer dataset que tiver!).

Em uma segunda etapa (essa será o assunto de outro artigo), poderemos usar esse modelo especializado para realizar tarefas de NLP do mesmo domínio linguístico que o desse dataset.

Como o dataset é relativamente pequeno, seguiremos a explicação dada no parágrafo anterior e manteremos o vocabulário do modelo de linguagem natural geral. Além disso, como não queremos ter que armazenar em produção vários modelos de vários GB (um modelo por tarefa), vamos treinar um adapter da biblioteca adapter-transformers chamado lang adapter.

Por fazer isso, publicamos um notebook (language_modeling_adapter.ipynb e sua versão nbviewer) realizado a partir dos seguintes notebooks e scripts para o ajuste fino de um Modelo de Linguagem Mascarada (MLM) de tipo transformer como o BERT (base ou grande) com qualquer datasets:

Esse notebook pode ser usado para BERT base or large com qualquer dataset. Deixamos os valores do nosso treinamento com o modelo BERT base em português da Neuralmind com um lang adapter pfeiffer+inv ajustado com o o dataset SQuAD 1.1 em português.

Nota: o notebook language_modeling_adapter.ipynb está na pasta language-modeling no github.

Mudanças principais em notebooks e scripts originais

Atualizamos o notebook language_modeling.ipynb para o nosso notebook language_modeling_adapter.ipynb com as seguintes alterações:

  • Avaliação: opção de avaliação do modelo por meio da acurácia do dataset de validação, e não por meio do loss desse dataset.
  • EarlyStopping: selecionando o modelo com a maior precisão de avaliação (paciência de 3 antes de terminar o treinamento).
  • MAD-X 2.0: opção que permite não treinar adapters na última camada do modelo transformer (leia a página 6 de UNKs Everywhere: Adapting Multilingual Language Models to New Scripts).
  • Houlsby MHA last layer (para a configuração de Houlsby) que não permite treinar o adapter após a camada de Feed Forward, mas somente após a de MHA (Multi-Head Attention) no último bloco transformer.

Configuração do lang adapter e resultados de treinamento dos modelos

Como queremos obter um modelo de linguagem que seja o mais especializado possível para o vocabulário do dataset de ajuste fino (SQuAD 1.1 pt aqui), inserimos o adapter invertible ao nível da camada embeddings do modelo BERT original (leia Adapter types).

Em seguida, precisamos inserir um adapter no nível de cada uma das camadas transformer do modelo original. Podemos escolher entre 2 configurações houlsby ou pfeiffer. Simplificando, o segundo tem 2 vezes menos parâmetros, mas permite aproximar o desempenho do primeiro.

Para comparar o desempenho dessas 2 configurações entre si e com um modelo BERT sem adapter ajustado de uma forma clássica (ajuste fino de todas as camadas do modelo), treinamos os 3 modelos seguintes:

  • modelo BERT Neuralmind base sem adapter (o original)
  • o original com adapter pfeiffer+inv mas sem adapter no último bloco transformer (se chama MAD-X 2.0)
  • o original com adapter houlsby+inv mas sem adapter apos a camada FeedForward (unicamente apos a camada de Multi-Attention Head) no último bloco transformer (se chama Houlsby MHA last layer)

Só para constar, o ajuste fino com adapter significa que congelamos todo os parâmetros do modelo BERT original. Apenas os parâmetros dos adapters são treinados.

Aqui estão os resultados:

resultados do treinamento de 3 modelos BER: um original e 2 com adapters

No caso da configuração pfeiffer+inv com MAD-X 2.0, pode-se observar que treinar apenas 6,24% do número de parâmetros do modelo BERT é suficiente para atingir uma acurácia quase igual (menos 2,63%).

A configuração houlsby+inv com Houlsby MHA last layer, a perda de acurácia em comparação do modelo original é ainda menor (menos 2.09%). No entanto, essa configuração tem 2 vezes mais de parâmetros que a configuração pfeiffer+inv.

Em relação aos hiperparâmetros de treinamento, podemos destacar o fato de que sempre usamos os mesmos (taxa de aprendizagem de 1e-4, batch size de 16, Adam epsilon de 1e-6)! Pode alterar o número de épocas, mas como usamos EarlyStopping, colocamos um número alto e modelos com adapters pararam o treinamaneto antes desse limite.

Em resumo, como procuramos eficácia em produção (em particular, velocidade no uso do modelo), usamos a configuração pfeiffer+inv para o nosso lang adapter.

Nota: se usar a configuração pfeiffer ou pfeiffer+inv, é aconselhável não inserir um adapter na última camada de transformação do modelo original para obter um melhor desempenho (isso se chama MAD-X 2.0 como definido no parágrafo precedente).

Número de parâmetros do modelo com um lang adapter

Se usar o o modelo BERT base em português da Neuralmind, pode calcular a porcentagem de parâmetros do modelo com um lang adapter em comparação com ao modelo sem adapter.

O aumento mínimo é de 6.24% com a configuração pfeiffer+inv com MAD-X 2.0 e o máximo de 13.29% com a configuração houlsby+inv sem MAD-X 2.0 (com adapter depois da camada de MHA no último bloco transformer).

Significa que em vez de armazenar a cada vez um modelo de 436MB (BERT base da Neuralmind), vai armazenar no caso mínimo 6.24 x 436 MB= 27.2 MB (+94 MB para os parâmetros de head do modelo) e no caso máximo 13.29 x 436 MB = 57.94 MB (+94 MB para os parâmetros de head do modelo).

Vale a pena, não?

pfeiffer+inv com MAD-X 2.0

Number of parameters of the model with adapter: 115751266
Number of parameters of the model without adapter: 108954466
Number of parameters of the adapter: 6796800
Pourcentage of additional parameters through adapter: 6.24 %

houlsby+inv com Houlsby MHA last layer

Number of parameters of the model with adapter: 122842978
Number of parameters of the model without adapter: 108954466
Number of parameters of the adapter: 13888512
Pourcentage of additional parameters through adapter: 12.75 %

houlsby+inv sem MAD-X 2.0

Number of parameters of the model with adapter: 123433954
Number of parameters of the model without adapter: 108954466
Number of parameters of the adapter: 14479488
Pourcentage of additional parameters through adapter: 13.29 %

Uso do modelo com lang adapter

Em primeiro lugar, deve baixar o modelo original do hub de modelos da Hugging Face:

from transformers import AutoModelForMaskedLM, AutoTokenizermodel_checkpoint = "neuralmind/bert-base-portuguese-cased"model_mlm = AutoModelForMaskedLM.from_pretrained(model_checkpoint)
tokenizer_mlm = AutoTokenizer.from_pretrained(model_checkpoint, use_fast=True)

Então, é necessário acrescentar (e ativar) o lang adapter que treinamos:

# load the language adapter
task_mlm_load_as = 'mlm'
lang_adapter_name = model_mlm.load_adapter(
str(load_lang_adapter),
config=lang_adapter_config,
load_as=task_mlm_load_as,
with_head=True
)

# Set the adapters to be used in every forward pass
model_mlm.set_active_adapters([lang_adapter_name])

Finalmente, usando a biblioteca Pipeline da Hugging Face, podemos usar nosso modelo com lang adapter para encontrar uma palavra oculta em uma frase tirada do dataset SQuAD 1.1 em português:

from transformers import pipeline
nlp = pipeline("fill-mask", model=model_mlm, tokenizer=tokenizer_mlm)
nlp("O panteísmo sustenta que [MASK] é o universo e o universo é Deus.")

Aqui está o resultado:

{'sequence': 'O panteísmo sustenta que Deus é o universo e o universo é Deus.',
'score': 0.865125834941864,
'token': 2538,
'token_str': 'Deus'},

Nosso modelo ajustado obteve uma melhor pontuação (0.865 vs. 0.739) ao encontrar a palavra mascarada Deus do que o modelo original (sem lang adapter). Parece que nosso modelo ajustado no dataset SQuAD 1.1 em português com um lang adapter funcionou :-)

Nota: com uma frase tirada da Wikipedia como “O primeiro caso da COVID-19 foi descoberto em Wuhan, na China”, é o contrario: é o modelo original que encontra a palavra escondida China com a melhor pontuação. Era esperado: ao ajustar o modelo original, o especializamos para a “linguagem” do dataset usado.

Sobre o autor: Pierre Guillou é consultor de IA no Brasil e na França, pesquisador em Deep Learning e NLP do AI Lab (Unb) e professor de Inteligência Artificial (UnB). Entre em contato com ele por meio de seu perfil no LinkedIn.

--

--