Bertologia

Agenda¶

  • Momento Computer Vision em NLP: ULMFit
  • Open AI Transformer
  • GPT-1 vs GPT-2 vs GPT-3 (semana que vem)
  • BERT
  • Bertologia
  • Miscelania

Momento Computer Vision em NLP¶

Transfer Learning¶

Um dos grandes motivos responsáveis para o boom de Deep Learning em meados de 2014 foi uma técnica conhecida como Transfer Learning. Ela pode ser definida como a seguinte:

Transfer learning and domain adaptation refer to the situation where what has been learned in one setting … is exploited to improve generalization in another setting

Deep Learning Book

Então, basicamente, a gente treina uma rede neural pesada para uma task grande, como o ImageNet, pegamos os pesos da rede treinada e treinamos uma nova rede para uma task menor, inicializando ela com esses pesos aprendidos na tarefa anterior

Mas como isso é possível em NLP?¶

A ideia de combinar a ideia de combinar transfer learning com o que ficou conhecido como aprendizado auto-surpervisionado.

Self-supervised learning: Training a model using labels that are embedded in the independent variable, rather than requiring external labels. For instance, training a model to predict the next word in a text.

Fast.ai book- Chapter 10

A tarefa, no caso de NLP, um tipo de modelo que entra nessa categoria de aprendizado auto surpervisionado é conhecida como modelo de linguagem

Modelo de Linguagem¶

Um modelo de linguagem é capaz de determinar a fluência de um texto. Na prática, o desafio é, com base nas palavras que eu vi até agora, qual deve ser a próxima palavra?

$$ \begin{array}{c} P(w_n|w_0, w_1, w_2, \dots, w_{n-1}) \end{array} $$

Qual a intuição para isso funcionar?

Regra de Probabilidade Condicional¶

$$ \begin{array}{ll} P(w_0, w_1, w_2, \dots, w_n) & = P(w_0) \times P(w_1|w_0) \dots \times P(w_n|w_0, w_1, w_2, \dots, w_{n-1}) \\ & = \displaystyle \prod_{i} P(w_n|w_0, w_1, w_2, \dots, w_{n-1}) \end{array} $$

P(Eu gosto de abacate) = P(Eu) $\times$ P(gosto|Eu) $\times$ P(de|Eu, gosto) $\times$ P(abacate|Eu, gosto, de)

Percebam que tendo um modelo assim, a gente não precisa de labels e, logo, o próprio dado de treinamento pode ser usado para gerar as labels e, assim, treinar algo! Daí a ideia de auto surpervisionado

ULMFit¶

Em Janeiro de 2018, Sebastian Ruder e Jeremy Howard tiveram a ideia de combinar essas duas técnicas, modelo que eles nomearam de ULMFit ou Universal Language Model Fine-tuning

fastai book

A ideia é criar um modelo de Linguagem "genérico", treinado com base no Wikipedia. Disso, fazemos uma etapa de fine-tuning no nosso dataset objetivo, com a ideia de que o modelo aprenda o linguajar específico desse domínio e, então, fazemos uma etapa final de treinamento focando na nossa tarefa final, como um classificador de sentimentos de filmes por exemplo.

Mas e a Arquitetura?¶

Para treinar esses modelos, foi utilizada a seguinte arquitetura:

  • AWD LSTM, que pode ser entendida como uma LSTM com algumas tecnicas a mais de otimização e regularização :)

overview ulmfit

Por fim, a loss, utilizada é a boa e velha Cross Entropy Loss :)

In [152]:
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.utils import plot_model

# define model
vocab_size = 1000
embed_dim = 50  # tamanho do Embedding de cada token
maxlen = 200  # Tamanho máximo da sentença
In [2]:
# Seu código aqui
tokenizer_layer = tf.keras.layers.experimental.preprocessing.TextVectorization(
    standardize='lower_and_strip_punctuation',
    split='whitespace', ngrams=None, output_mode="int",
    output_sequence_length=maxlen, pad_to_max_tokens=False)
tokenizer_layer.adapt(np.array(["O rato roeu a roupa do rei de roma"]))

inputs = layers.Input(shape=(1,), dtype=tf.string, name='input_text')
embedding_layer = layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)
In [3]:
x = tokenizer_layer(inputs)    
x = embedding_layer(x)
x = layers.LSTM(units=1)(x)
x = layers.Dropout(0.1)(x)
x = layers.Dense(20, activation="relu")(x)
x = layers.Dropout(0.1)(x)
outputs = layers.Dense(2, activation="softmax")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
In [4]:
model.compile(loss="categorical_crossentropy", metrics=["accuracy"])

Mas atenção não é tudo que a gente precisa?¶

Contudo, lembrem que na útlima aula vimos um paper que saiu em no meio de 2017, o Attention is All you need? Nele, foi apresentado a arquitetura Transformer

Acontece que a ideia tida por Radford et. al em Junho de 2018 foi a de usar a parte decoder da rede para o processo de aprendizado auto surpervisionado! Esse modelo ficou conhecido como Open AI Transformer, ou GPT-1

attention? attention!

  • A diferença é que no caso desse modelo do Open AI $N=12$ :)

Veremos mais detyalhes sobre os modelos GPT na semana que vem.

BERT¶

Apesar do artigo do GPT-1 ser impressionante para a época, alguns meses depois, em Outubro do mesmo ano (o GPT foi lançado em Junho), o pessoal do Google propôs usar a parte encoder do transformer, junto de outras modificações leves, dando ao modelo o nome de Bidirectional Encoder Representations from Transformers (BERT)

Encoder Layer¶

Relembrando o Encoder Layer dos Transformers

attention? attention!

  • A diferença é que no caso desse modelo do BERT $N=12$ ou $N=24$ :)

A primeira diferença do GPT é abandonar o Masked Multi Head e usar direto o Multi Head Attention, daí o nome birecional!

Mas se fazemos isso, não estamos overfittando (sobreajustando) o modelo já que vamos olhar o contexto futuro para prever a palavra atual?

Solução: usar outro processo de treinamento

A Loss no BERT¶

A grande sacada do BERT é que foi proposta uma nova forma de treinar, justamente por ele ser bidirecional. O processo de treinamento visa otimizar duas tarefas que são aprendidas ao mesmo tempo

Tarefa 1 Masked Language Model¶

A ideia é simples: dado um input de entrada, uma certa porcentagem (cerca de 15% segundo o paper) das palavras desse texto de entrada é máscarada (ou seja, trocadas por um token [MASK]). A tarefa é prever as palavras que foram escondidas. Daí, a última camada da rede tenta prever apenas a palavra que foi ocultada e, logo, não é inato ao modelo BERT gerar sequências!!!

Contudo, como as palavras escondidas são mascaradas com [MASK], isso gera uma discrepância entre os modelos de pré treino e finetuning já que os datasets de finetuning não terão esse token especial. Daí, outra sacada foi simplesmente embaralhar as palavras.

Segundo o paper, dado uma sentença de input, 15% das palavras são escolhidas como tokens para serem trocados. Com esses tokens selecionados, 80% das vezes eles viram [MASK], 10% das vezes eles são trocados por outro token e 10% das vezes eles são mantidos iguais.

O modelo deve prever a sentença de entrada no treinamento desta tarefa.

Tarefa 2 Next Sentence Prediction (NSP)¶

A ideia também é direta: ao fazer o emberdding das sequências de input, são gerados pares de pares (A,B) de sentenças. Durante o processo de treinamento, 50% dessas sentenças tem a ordem invertida (B,A) onde a sentença B não é a sequência de A no córpus de treino. O objetivo desse componente da Loss é detectar se uma sentença B é a próxima sentença de A.

Para acusar a inversão, a sequência toda é prefixada por uma palavra reservada chamada de [CLS], cuja embeddoing à saída também serve como um "resumo" de toda a entrada. Esse não é a única palavra reservada, pois temos ou menows [MASK[, [CLS], [SEP], [OOD] e [PAD].

Em resumo, o BERT formata as sentenças da seguinte forma:

[CLS] sentença A [SEP] sentença B [SEP]

A loss do BERT é dada pela soma do MLM e NSP

In [4]:
from IPython.display import Video

Video("images/TransformerEncoderExample.mp4")
Out[4]:
Your browser does not support the video element.

Fine Tuning¶

Uma vez que a rede aprendeu algo no processo de pré treino, nós podemos fazer uma modificação leve na sua ponta visando um aprendizado surpervisionado e aí treinar a rede para essa tarefa, otimizando todos os parâmetros de ponta a ponta

Mudanças específicas para os casos de finetuning?

source

Classificando uma única sentença: Usando a transformação do [CLS]¶

Rotulando uma sentença: Uma FF para cada palavra¶

Arquiteturas de Refinamento¶

In [153]:


class MultiHeadSelfAttention(layers.Layer):
    def __init__(self, embed_dim, num_heads ):
        super(MultiHeadSelfAttention, self).__init__()
        if embed_dim % num_heads != 0:
            raise ValueError(
                f"dimensão do embedding = {embed_dim} deve ser "  +
                "divisível pelo n. de cabeças = {num_heads}"
            )
        self.embed_dim = embed_dim
        self.num_heads = num_heads
        self.projection_dim = embed_dim // num_heads
        self.query_dense = layers.Dense(embed_dim)
        self.key_dense = layers.Dense(embed_dim)
        self.value_dense = layers.Dense(embed_dim)
        self.combine_heads = layers.Dense(embed_dim)

    def attention(self, query, key, value):
        score = tf.matmul(query, key, transpose_b=True)
        dim_key = tf.cast(tf.shape(key)[-1], tf.float32)
        scaled_score = score / tf.math.sqrt(dim_key)
        weights = tf.nn.softmax(scaled_score, axis=-1)
        output = tf.matmul(weights, value)
        return output, weights

    def separate_heads(self, x, batch_size):
        # divide o embedding_dim em n_cabeças de projection_dim (batch_size e seq_len são mantidos)
        x = tf.reshape(x, (batch_size, -1, self.num_heads, self.projection_dim))
        # reordena o n_cabeças com a seq_len
        return tf.transpose(x, perm=[0, 2, 1, 3])

    def call(self, inputs):
        # x.shape = [batch_size, seq_len, embedding_dim]
        batch_size = tf.shape(inputs)[0]
        query = self.query_dense(inputs)  # (batch_size, seq_len, embed_dim)
        key = self.key_dense(inputs)      # (batch_size, seq_len, embed_dim)
        value = self.value_dense(inputs)  # (batch_size, seq_len, embed_dim)
        query = self.separate_heads(
            query, batch_size
        )  # (batch_size, num_heads, seq_len, projection_dim)
        key = self.separate_heads(
            key, batch_size
        )  # (batch_size, num_heads, seq_len, projection_dim)
        value = self.separate_heads(
            value, batch_size
        )  # (batch_size, num_heads, seq_len, projection_dim)
        attention, weights = self.attention(query, key, value)
        attention = tf.transpose(
            attention, perm=[0, 2, 1, 3]
        )  # (batch_size, seq_len, num_heads, projection_dim)
        concat_attention = tf.reshape(
            attention, (batch_size, -1, self.embed_dim)
        )  # (batch_size, seq_len, embed_dim)
        output = self.combine_heads(
            concat_attention
        )  # (batch_size, seq_len, embed_dim)
        return output
In [154]:
class TokenAndPositionEmbedding(layers.Layer):
    def __init__(self, maxlen, vocab_size, embed_dim):
        super(TokenAndPositionEmbedding, self).__init__()
        positions = np.array(range(0, maxlen, 1)).reshape(-1, 1)
        even_i = np.array(range(0, embed_dim, 2))
        odd_i = np.array(range(1, embed_dim, 2))

        self.word_embedding = layers.Embedding(
            input_dim=vocab_size, output_dim=embed_dim,
        )
        positional_encoding = np.zeros((maxlen, embed_dim))
        positional_encoding[:, 0::2] = np.sin(
            positions / (10000 ** (even_i / embed_dim))
        )
        positional_encoding[:, 1::2] = np.cos(
            positions / (10000 ** ((odd_i - 1) / embed_dim))
        )
        self.positional_encoding = layers.Embedding(
            input_dim=maxlen, output_dim=embed_dim, weights=[positional_encoding], trainable=False
        )
        #trainable é false pq é uma fórmula só, entao nao precisa aprender

    def call(self, x):  # o que  é x aqui?
        # x é um indice
        positions = tf.range(start=0, limit=maxlen, delta=1)
        positions = self.positional_encoding(positions)
        x = self.word_embedding(x)
        return x + positions
In [155]:
class TransformerBlock(layers.Layer):
    def __init__(self, embed_dim, num_heads, ff_dim, rate=0.1):
        super(TransformerBlock, self).__init__()
        self.att = MultiHeadSelfAttention(embed_dim, num_heads)
        self.ffn = keras.Sequential(
            [layers.Dense(ff_dim, activation="relu"), 
             layers.Dense(embed_dim),
            ]
        )
        self.layernorm1 = layers.LayerNormalization(epsilon=1e-6)
        self.layernorm2 = layers.LayerNormalization(epsilon=1e-6)
        self.dropout1 = layers.Dropout(rate)
        self.dropout2 = layers.Dropout(rate)

    def call(self, inputs, training):
        attn_output = self.att(inputs)
        attn_output = self.dropout1(attn_output, training=training)
        out1 = self.layernorm1(inputs + attn_output)
        ffn_output = self.ffn(out1)
        ffn_output = self.dropout2(ffn_output, training=training)
        return self.layernorm2(out1 + ffn_output)
In [156]:
vocab_size = 30000
embed_dim = 768  # tamanho do Embedding de cada token
num_heads = 12  # N. de cabeças de atenção
ff_dim = 12  # tamanho da camada oculta nas redes feed forward dentro do transformer
maxlen = 512 #ja incluindo CLS e SEP

tokenizer_layer = tf.keras.layers.experimental.preprocessing.TextVectorization(
    standardize="lower_and_strip_punctuation",
    split="whitespace",
    ngrams=None,
    output_mode="int",
    output_sequence_length=maxlen,
    pad_to_max_tokens=False,
)
inputs = layers.Input(shape=(1,), dtype=tf.string, name="input_text")
embedding_layer = TokenAndPositionEmbedding(maxlen, vocab_size, embed_dim)
transformer_block = TransformerBlock(embed_dim, num_heads, ff_dim)
In [157]:
x = tokenizer_layer(inputs)    
x = embedding_layer(x)
for i in range(12):
    x = transformer_block(x)
x = x[:,0,:] #cls token
x = layers.Dropout(0.1)(x)
outputs = layers.Dense(2, activation="softmax")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
In [37]:
plot_model(model, show_shapes=True, show_layer_names=True)
Out[37]:

Beleza, mas e os pesos pré treinados?

In [158]:
from transformers import BertTokenizer, pipeline, TFBertForPreTraining
In [138]:
REF_MODEL = 'neuralmind/bert-base-portuguese-cased'
In [139]:
model = TFBertForPreTraining.from_pretrained(REF_MODEL, from_pt=True)
Some weights of the PyTorch model were not used when initializing the TF 2.0 model TFBertForPreTraining: ['cls.predictions.decoder.weight']
- This IS expected if you are initializing TFBertForPreTraining from a PyTorch model trained on another task or with another architecture (e.g. initializing a TFBertForSequenceClassification model from a BertForPretraining model).
- This IS NOT expected if you are initializing TFBertForPreTraining from a PyTorch model that you expect to be exactly identical (e.g. initializing a TFBertForSequenceClassification model from a BertForSequenceClassification model).
All the weights of TFBertForPreTraining were initialized from the PyTorch model.
If your task is similar to the task the model of the ckeckpoint was trained on, you can already use TFBertForPreTraining for predictions without further training.
In [140]:
unmasker = pipeline('fill-mask', model=REF_MODEL)
unmasker("Eu bebi muita [MASK] no carnaval")[:3]
Some weights of the model checkpoint at neuralmind/bert-base-portuguese-cased were not used when initializing BertForMaskedLM: ['cls.seq_relationship.weight', 'cls.seq_relationship.bias']
- This IS expected if you are initializing BertForMaskedLM from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPretraining model).
- This IS NOT expected if you are initializing BertForMaskedLM from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
Out[140]:
[{'sequence': '[CLS] Eu bebi muita água no carnaval [SEP]',
  'score': 0.3878271281719208,
  'token': 1991,
  'token_str': 'água'},
 {'sequence': '[CLS] Eu bebi muita cerveja no carnaval [SEP]',
  'score': 0.3672230541706085,
  'token': 18099,
  'token_str': 'cerveja'},
 {'sequence': '[CLS] Eu bebi muita coisa no carnaval [SEP]',
  'score': 0.18478259444236755,
  'token': 5664,
  'token_str': 'coisa'}]
In [141]:
from transformers import BertTokenizer, TFBertModel

tokenizer = BertTokenizer.from_pretrained(REF_MODEL)
model = TFBertModel.from_pretrained(REF_MODEL, from_pt=True)
text = "O rato roeu a roupa do Rei de Roma"
encoded_input = tokenizer(text, return_tensors='tf')
output = model(encoded_input)
output[0].shape, output[1].shape
Some weights of the PyTorch model were not used when initializing the TF 2.0 model TFBertModel: ['cls.predictions.transform.dense.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.bias', 'cls.seq_relationship.weight', 'cls.predictions.decoder.weight']
- This IS expected if you are initializing TFBertModel from a PyTorch model trained on another task or with another architecture (e.g. initializing a TFBertForSequenceClassification model from a BertForPretraining model).
- This IS NOT expected if you are initializing TFBertModel from a PyTorch model that you expect to be exactly identical (e.g. initializing a TFBertForSequenceClassification model from a BertForSequenceClassification model).
All the weights of TFBertModel were initialized from the PyTorch model.
If your task is similar to the task the model of the ckeckpoint was trained on, you can already use TFBertModel for predictions without further training.
Out[141]:
(TensorShape([1, 13, 768]), TensorShape([1, 768]))
In [142]:
encoded_input['input_ids'].shape
Out[142]:
TensorShape([1, 13])

É o embedding de cada palavra e o segundo é o embedding de None ser o next sentence :)

In [129]:
from transformers import (
    TFBertForSequenceClassification,
    TFBertForMultipleChoice,
    TFBertForTokenClassification,
    TFBertForQuestionAnswering,
)
In [143]:
model = TFBertForSequenceClassification.from_pretrained(REF_MODEL, from_pt=True)
model.summary()
Some weights of the PyTorch model were not used when initializing the TF 2.0 model TFBertForSequenceClassification: ['cls.predictions.transform.dense.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.bias', 'cls.seq_relationship.weight', 'cls.predictions.decoder.weight']
- This IS expected if you are initializing TFBertForSequenceClassification from a PyTorch model trained on another task or with another architecture (e.g. initializing a TFBertForSequenceClassification model from a BertForPretraining model).
- This IS NOT expected if you are initializing TFBertForSequenceClassification from a PyTorch model that you expect to be exactly identical (e.g. initializing a TFBertForSequenceClassification model from a BertForSequenceClassification model).
Some weights or buffers of the TF 2.0 model TFBertForSequenceClassification were not initialized from the PyTorch model and are newly initialized: ['classifier.weight', 'classifier.bias']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
Model: "tf_bert_for_sequence_classification_22"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
bert (TFBertMainLayer)       multiple                  108923136 
_________________________________________________________________
dropout_1400 (Dropout)       multiple                  0         
_________________________________________________________________
classifier (Dense)           multiple                  1538      
=================================================================
Total params: 108,924,674
Trainable params: 108,924,674
Non-trainable params: 0
_________________________________________________________________
In [144]:
model = TFBertForMultipleChoice.from_pretrained(REF_MODEL, from_pt=True)
model.summary()
Some weights of the PyTorch model were not used when initializing the TF 2.0 model TFBertForMultipleChoice: ['cls.predictions.transform.dense.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.bias', 'cls.seq_relationship.weight', 'cls.predictions.decoder.weight']
- This IS expected if you are initializing TFBertForMultipleChoice from a PyTorch model trained on another task or with another architecture (e.g. initializing a TFBertForSequenceClassification model from a BertForPretraining model).
- This IS NOT expected if you are initializing TFBertForMultipleChoice from a PyTorch model that you expect to be exactly identical (e.g. initializing a TFBertForSequenceClassification model from a BertForSequenceClassification model).
Some weights or buffers of the TF 2.0 model TFBertForMultipleChoice were not initialized from the PyTorch model and are newly initialized: ['classifier.weight', 'classifier.bias']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
Model: "tf_bert_for_multiple_choice_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
bert (TFBertMainLayer)       multiple                  108923136 
_________________________________________________________________
dropout_1438 (Dropout)       multiple                  0         
_________________________________________________________________
classifier (Dense)           multiple                  769       
=================================================================
Total params: 108,923,905
Trainable params: 108,923,905
Non-trainable params: 0
_________________________________________________________________
In [159]:
model = TFBertForTokenClassification.from_pretrained(REF_MODEL, from_pt=True)
model.summary()
Some weights of the PyTorch model were not used when initializing the TF 2.0 model TFBertForTokenClassification: ['cls.predictions.transform.dense.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.bias', 'cls.seq_relationship.weight', 'cls.predictions.decoder.weight']
- This IS expected if you are initializing TFBertForTokenClassification from a PyTorch model trained on another task or with another architecture (e.g. initializing a TFBertForSequenceClassification model from a BertForPretraining model).
- This IS NOT expected if you are initializing TFBertForTokenClassification from a PyTorch model that you expect to be exactly identical (e.g. initializing a TFBertForSequenceClassification model from a BertForSequenceClassification model).
Some weights or buffers of the TF 2.0 model TFBertForTokenClassification were not initialized from the PyTorch model and are newly initialized: ['classifier.weight', 'classifier.bias']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
Model: "tf_bert_for_token_classification_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
bert (TFBertMainLayer)       multiple                  108923136 
_________________________________________________________________
dropout_1516 (Dropout)       multiple                  0         
_________________________________________________________________
classifier (Dense)           multiple                  1538      
=================================================================
Total params: 108,924,674
Trainable params: 108,924,674
Non-trainable params: 0
_________________________________________________________________
In [145]:
model = TFBertForQuestionAnswering.from_pretrained(REF_MODEL, from_pt=True)
model.summary()
Some weights of the PyTorch model were not used when initializing the TF 2.0 model TFBertForQuestionAnswering: ['cls.predictions.transform.dense.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.bias', 'cls.seq_relationship.weight', 'cls.predictions.decoder.weight']
- This IS expected if you are initializing TFBertForQuestionAnswering from a PyTorch model trained on another task or with another architecture (e.g. initializing a TFBertForSequenceClassification model from a BertForPretraining model).
- This IS NOT expected if you are initializing TFBertForQuestionAnswering from a PyTorch model that you expect to be exactly identical (e.g. initializing a TFBertForSequenceClassification model from a BertForSequenceClassification model).
Some weights or buffers of the TF 2.0 model TFBertForQuestionAnswering were not initialized from the PyTorch model and are newly initialized: ['qa_outputs.weight', 'qa_outputs.bias']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
Model: "tf_bert_for_question_answering_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
bert (TFBertMainLayer)       multiple                  108923136 
_________________________________________________________________
qa_outputs (Dense)           multiple                  1538      
=================================================================
Total params: 108,924,674
Trainable params: 108,924,674
Non-trainable params: 0
_________________________________________________________________

BERT e seus irmãos¶

Com o sucesso do BERT, vários outros modelos foram propostos, trazendo melhorias para a área. Vamos passar por alguns deles aqui :)

RoBERTa¶

robustly optimized BERT approach

Foi proposta uma variação no pré treinamento do BERT, propondo quatro ideias novas:

  • Dynamic masking. Quando ocorre a máscara de tokens para a tarefa de MLM no caso do BERT, apenas uma unica máscara era considerada para cada observação no período de pré treinamento (static masking). No caso do RoBERTA, é usado um mascaramento dinâmico, ou seja, a estratégia de treinamento aplica uma nova máscara sempre que uma observação é alimentada ao modelo.
  • A loss associada ao NSP é desconsiderada e ocorre a adição de um token separador entre documentos para a MLM task.

  • Mini batches maiores. No caso do BERT, os mini batches tinham tamanho de 256; no RoBERTa eles tem tamanho de 8000

  • Byte-level no caso do byte-pair encoding é maior, resultando em um vocabulario maior

Albert¶

a lite BERT

A idéia era gerar um modelo mais leve que o BERT, mas que mantivesse o mesmo resultado em termos de performance

  • O BERT padrão usa de 100k a 300k de parâmetros. O Albert usa em torno de 12k a 18k :)

As técnicas aplicadas foram as seguintes

  • Cross-layer parameter sharing. Para gerar estabilidade do modelo, todos os parâmetros em todas as camadas foram compartilhados

  • Factorized embedding parameterization. A matriz de embedding inicial tem uma dimensão $|v| \times |m|$, em que $|v|$ é o tamanho do vocabulário e $|m|$ é o número de dimensões do embedding. A ideia aqui, então é aplicar uma tecnica de fatorização de matrizes, decompondo a matriz de embedding em duas menores

  • Inter-sentence coherence loss. A loss NSP é substituida por uma loss definida como sentence order prediction (SOP). A diferença é que ela apresenta exemplos negativos para os casos em que duas sentenças estão com a ordem trocada. Um exemplo negativo seria:

“that is the question”, “to be, or not to be?”

E muitos outros¶

XLNet¶

Ao invés de prever todos os masked tokens independentes condicionalmente, o XLNET prevê os masked tokens de maneira auto-regressiva de forma aleatória

SpanBERT¶

Ao invés de mascarar tokens, ele mascara spans (conjunto de tokens)

ELECTRA¶

Ao invés de mascarar palavras, nós substituimos por tokens similares e tratamos como um problema de classificação binária em que se tenta prever se os tokens foram trocados ou não. É GAN-inspirado

DistilBERT¶

Mesma linha do Albert, mas aplicam uma ténica de compressão de modelo chamada destilação

Modelo final tem 40% menos parâmetros, roda 60% mais rápido e tem 95% de performance mantida

Entre outros

In [146]:
from transformers import (
    TFRobertaForSequenceClassification,
    TFDistilBertForQuestionAnswering,
)

Lista de modelos implementados Lista de modelos disponíveis

Miscelânea¶

Para pessoas que estão treinando em GPU's não tão parrudas, é comum encontrarmos o seguinte erro:

E aí você tenta solucionar e descobre isso:

Felizmente existem duas opções que me ajudaram muito

Gradient Accumulation¶

FP16¶

Mixed precision training offers significant computational speedup by performing operations in half-precision format, while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of Tensor Cores in the Volta and Turing architectures, significant training speedups are experienced by switching to mixed precision -- up to 3x overall speedup on the most arithmetically intense model architectures.

source

Obrigado! :)¶