Pytorch
TensorFlow

#
Modelos

Nesta seção, vamos analisar mais de perto a criação e a utilização de um modelo. Vamos utilizar a classe `AutoModel`, que é útil quando você quer instanciar qualquer modelo a partir de um checkpoint.

A classe `AutoModel` e todas as classes filhas são na verdade simples wrapper sobre a grande variedade de modelos disponíveis na biblioteca. É um wrapper inteligente, pois pode automaticamente “adivinhar” a arquitetura apropriada do modelo para seu checkpoint, e então instancia um modelo com esta arquitetura.

Entretanto, se você conhece o tipo de modelo que deseja usar, pode usar diretamente a classe que define sua arquitetura. Vamos dar uma olhada em como isto funciona com um modelo BERT.

##
Criando um Transformer

A primeira coisa que precisamos fazer para inicializar um modelo BERT é carregar um objeto de configuração:

    from transformers import BertConfig, BertModel

    # Construindo a configuração
    config = BertConfig()

    # Construindo o modelo a partir da configuração
    model = BertModel(config)

A configuração contém muitos atributos que são usados para construir o modelo:

    print(config)

    BertConfig {
      [...]
      "hidden_size": 768,
      "intermediate_size": 3072,
      "max_position_embeddings": 512,
      "num_attention_heads": 12,
      "num_hidden_layers": 12,
      [...]
    }

Embora você ainda não tenha visto o que todos esses atributos fazem, você deve reconhecer alguns deles: o atributo `hidden_size` define o tamanho do vetor `hidden_states`, e o `num_hidden_layers` define o número de camadas que o Transformer possui.

###
Diferentes métodos de inicializar o modelo

A criação de um modelo a partir da configuração padrão o inicializa com valores aleatórios:

    from transformers import BertConfig, BertModel

    config = BertConfig()
    model = BertModel(config)

    # O modelo é inicializado aleatoriamente!

O modelo pode ser utilizado neste estado, mas produzirá saídas errôneas; ele precisa ser treinado primeiro. Poderíamos treinar o modelo a partir do zero na tarefa em mãos, mas como você viu em Capítulo 1, isto exigiria muito tempo e muitos dados, e teria um impacto ambiental não negligenciável. Para evitar esforços desnecessários e duplicados, normalmente é possível compartilhar e reutilizar modelos que já foram treinados.

Carregar um Transformer já treinado é simples - podemos fazer isso utilizando o método `from_pretrained()`:

    from transformers import BertModel

    model = BertModel.from_pretrained("bert-base-cased")

Como você viu anteriormente, poderíamos substituir o `BertModel` pela classe equivalente ao `AutoModel`. Faremos isto de agora em diante, pois isto produz um código generalista a partir de um checkpoint; se seu código funciona para checkpoint, ele deve funcionar perfeitamente com outro. Isto se aplica mesmo que a arquitetura seja diferente, desde que o checkpoint tenha sido treinado para uma tarefa semelhante (por exemplo, uma tarefa de análise de sentimento).

No exemplo de código acima não utilizamos `BertConfig`, e em vez disso carregamos um modelo pré-treinado através do identificador `bert-base-cased`. Este é um checkpoint do modelo que foi treinado pelos próprios autores do BERT; você pode encontrar mais detalhes sobre ele em seu model card.

Este modelo agora é inicializado com todos os pesos do checkpoint. Ele pode ser usado diretamente para inferência sobre as tarefas nas quais foi treinado, e também pode ser fine-tuned (aperfeiçoado) em uma nova tarefa. Treinando com pesos pré-treinados e não do zero, podemos rapidamente alcançar bons resultados.

Os pesos foram baixados e armazenados em cache (logo, para as futuras chamadas do método `from_pretrained()` não será realizado o download novamente) em sua respectiva pasta, que tem como padrão o path ~/.cache/huggingface/transformers. Você pode personalizar sua pasta de cache definindo a variável de ambiente `HF_HOME`.

O identificador usado para carregar o modelo pode ser o identificador de qualquer modelo no Model Hub, desde que seja compatível com a arquitetura BERT. A lista completa dos checkpoints BERT disponíveis podem ser encontrada [aqui].https://huggingface.co/models?filter=bert).

###
Métodos para salvar/armazenar o modelo

Salvar um modelo é tão fácil quanto carregar um - utilizamos o método `save_pretrained()`, que é análogo ao método `from_pretrained()`:

    model.save_pretrained("path_no_seu_computador")

Isto salva dois arquivos em seu disco:

    ls path_no_seu_computador

    config.json pytorch_model.bin

Se você der uma olhada no arquivo config.json, você reconhecerá os atributos necessários para construir a arquitetura modelo. Este arquivo também contém alguns metadados, como a origem do checkpoint e a versão 🤗 Transformers que você estava usando quando salvou o checkpoint pela última vez.

O arquivo pytorch_model.bin é conhecido como o dicionário de estado; ele contém todos os pesos do seu modelo. Os dois arquivos andam de mãos dadas; a configuração é necessária para conhecer a arquitetura de seu modelo, enquanto os pesos do modelo são os parâmetros de seu modelo.

##
Usando um modelo de Transformer para inferência

Agora que você sabe como carregar e salvar um modelo, vamos tentar usá-lo para fazer algumas predições. Os Transformers só podem processar números - números que o tokenizer gera. Mas antes de discutirmos os tokenizers, vamos explorar quais entradas o modelo aceita.

Os Tokenizers podem se encarregar de lançar as entradas nos tensores da estrutura apropriada, mas para ajudá-lo a entender o que está acontecendo, vamos dar uma rápida olhada no que deve ser feito antes de enviar as entradas para o modelo.

Digamos que temos um par de sequências:

    sequences = ["Hello!", "Cool.", "Nice!"]

O tokenizer os converte em índices de vocabulário que são normalmente chamados de IDs de entrada. Cada sequência é agora uma lista de números! A saída resultante é:

    encoded_sequences = [
        [101, 7592, 999, 102],
        [101, 4658, 1012, 102],
        [101, 3835, 999, 102],
    ]

Esta é uma lista de sequências codificadas: uma lista de listas. Os tensores só aceitam shapes (tamanhos) retangulares (pense em matrizes). Esta “matriz” já é de forma retangular, portanto, convertê-la em um tensor é fácil:

    import torch

    model_inputs = torch.tensor(encoded_sequences)

###
Usando os tensores como entradas para o modelo

Fazer uso dos tensores com o modelo é extremamente simples - chamamos apenas o modelo com os inputs:

    output = model(model_inputs)

Embora o modelo aceite muitos argumentos diferentes, apenas os IDs de entrada são necessários. Explicaremos o que os outros argumentos fazem e quando eles são necessários mais tarde, mas primeiro precisamos olhar mais de perto os tokenizers que constroem as entradas que um Transformer pode compreender.