Transformers documentation

Personalizando modelos

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Personalizando modelos

Os modelos do Transformers são projetados para serem personalizáveis. O código de um modelo está totalmente contido na subpasta model do repositório do Transformers. Cada pasta contém os arquivos modeling.py e configuration.py. Copie esses arquivos para começar a personalizar um modelo.

Pode ser mais fácil começar do zero se você estiver criando um modelo totalmente novo. Mas, para modelos muito semelhantes a um existente no Transformers, é mais rápido reutilizar ou subclassear a mesma configuração e a mesma classe de modelo.

Este guia mostrará como personalizar um modelo ResNet, habilitar o suporte a AutoClass e compartilhá-lo no Hub.

Configuração

A configuração, definida pela classe base PreTrainedConfig, contém todas as informações necessárias para construir um modelo. É aqui que você configurará os atributos do modelo ResNet personalizado. Atributos diferentes resultam em diferentes tipos de modelo ResNet.

As principais regras para personalizar uma configuração são:

  1. Uma configuração personalizada deve ser uma subclasse de PreTrainedConfig. Isso garante que um modelo personalizado tenha toda a funcionalidade de um modelo do Transformers, como from_pretrained(), save_pretrained() e push_to_hub().
  2. O __init__ do PreTrainedConfig deve aceitar quaisquer kwargs e eles devem ser passados para o __init__ da superclasse. O PreTrainedConfig possui mais campos do que os definidos na sua configuração personalizada, portanto, ao carregar uma configuração com from_pretrained(), esses campos precisam ser aceitos pela sua configuração e passados para a superclasse.

É útil verificar a validade de alguns parâmetros. No exemplo abaixo, uma verificação é implementada para garantir que block_type e stem_type pertençam a um dos valores predefinidos.

Adicione model_type à classe de configuração para habilitar o suporte a AutoClass.

from transformers import PreTrainedConfig
from typing import List

class ResnetConfig(PreTrainedConfig):
    model_type = "resnet"

    def __init__(
        self,
        block_type="bottleneck",
        layers: list[int] = [3, 4, 6, 3],
        num_classes: int = 1000,
        input_channels: int = 3,
        cardinality: int = 1,
        base_width: int = 64,
        stem_width: int = 64,
        stem_type: str = "",
        avg_down: bool = False,
        **kwargs,
    ):
        if block_type not in ["basic", "bottleneck"]:
            raise ValueError(f"`block_type` must be 'basic' or bottleneck', got {block_type}.")
        if stem_type not in ["", "deep", "deep-tiered"]:
            raise ValueError(f"`stem_type` must be '', 'deep' or 'deep-tiered', got {stem_type}.")

        self.block_type = block_type
        self.layers = layers
        self.num_classes = num_classes
        self.input_channels = input_channels
        self.cardinality = cardinality
        self.base_width = base_width
        self.stem_width = stem_width
        self.stem_type = stem_type
        self.avg_down = avg_down
        super().__init__(**kwargs)

Salve a configuração em um arquivo JSON na pasta do seu modelo personalizado, custom-resnet, com save_pretrained().

resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d_config.save_pretrained("custom-resnet")

Model

Com a configuração personalizada do ResNet, você agora pode criar e personalizar o modelo. O modelo é uma subclasse da classe base PreTrainedModel. Assim como no PreTrainedConfig, herdar de PreTrainedModel e inicializar a superclasse com a configuração estende as funcionalidades dos Transformers, como salvar e carregar, para o modelo personalizado.

Os modelos do Transformers seguem a convenção de aceitar um objeto config no método __init__. Isso passa o config inteiro para as subcamadas do modelo, em vez de dividir o objeto config em vários argumentos que são passados individualmente para as subcamadas.

Escrever modelos dessa forma gera um código mais simples, com uma fonte de verdade clara para quaisquer hiperparâmetros. Também facilita a reutilização de código de outros modelos do Transformers.

Você criará dois modelos ResNet: um modelo ResNet básico que produz os estados ocultos e um modelo ResNet com uma cabeça de classificação de imagem.

ResnetModel
ResnetModelForImageClassification

Defina um mapeamento entre os tipos de bloco e as classes. Tudo o mais é criado passando a classe de configuração para a classe de modelo ResNet.

Adicione config_class à classe do modelo para habilitar o suporte a AutoClass.

from transformers import PreTrainedModel
from timm.models.resnet import BasicBlock, Bottleneck, ResNet
from .configuration_resnet import ResnetConfig

BLOCK_MAPPING = {"basic": BasicBlock, "bottleneck": Bottleneck}

class ResnetModel(PreTrainedModel):
    config_class = ResnetConfig

    def __init__(self, config):
        super().__init__(config)
        block_layer = BLOCK_MAPPING[config.block_type]
        self.model = ResNet(
            block_layer,
            config.layers,
            num_classes=config.num_classes,
            in_chans=config.input_channels,
            cardinality=config.cardinality,
            base_width=config.base_width,
            stem_width=config.stem_width,
            stem_type=config.stem_type,
            avg_down=config.avg_down,
        )

    def forward(self, tensor):
        return self.model.forward_features(tensor)

Um modelo pode retornar qualquer formato de saída. Retornar um dicionário (como ResnetModelForImageClassification) com perdas quando os rótulos estão disponíveis torna o modelo personalizado compatível com Trainer. Para outros formatos de saída, você precisará de um próprio loop de treinamento ou de uma biblioteca diferente para o treinamento.

Instancie a classe de modelo personalizada com a configuração.

resnet50d = ResnetModelForImageClassification(resnet50d_config)

Neste ponto, você pode carregar pesos pré-treinados no modelo ou treiná-lo do zero. Neste guia, você carregará pesos pré-treinados.

Carregue os pesos pré-treinados da biblioteca timm e, em seguida, transfira esses pesos para o modelo personalizado com load_state_dict.

import timm

pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())

AutoClass

A API AutoClass é uma atalho para carregar automaticamente a arquitetura correta para um modelo específico. É conveniente habilitar isso para usuários que carregam seu modelo personalizado.

Verifique se a classe de configuração possui o atributo model_type (que deve ser diferente dos tipos de modelo existentes) e se a classe do modelo possui o atributo config_class. Use o método register() para adicionar a configuração e o modelo personalizados à API AutoClass.

O primeiro argumento de AutoConfig.register() deve corresponder ao atributo model_type na classe de configuração personalizada, e o primeiro argumento de AutoModel.register() deve corresponder ao config_class da classe de modelo personalizada.

from transformers import AutoConfig, AutoModel, AutoModelForImageClassification

AutoConfig.register("resnet", ResnetConfig)
AutoModel.register(ResnetConfig, ResnetModel)
AutoModelForImageClassification.register(ResnetConfig, ResnetModelForImageClassification)

O código do seu modelo personalizado agora é compatível com a API AutoClass. Os usuários podem carregar o modelo com as classes AutoModel ou AutoModelForImageClassification.

Upload

Envie um modelo personalizado para o Hub para permitir que outros usuários o carreguem e utilizem com facilidade.

Certifique-se de que o diretório do modelo esteja estruturado corretamente, conforme mostrado abaixo. O diretório deve conter:

  • modeling.py: Contém o código de ResnetModel e ResnetModelForImageClassification. Este arquivo pode usar imports relativos para outros arquivos, desde que estejam no mesmo diretório.

Ao copiar um arquivo de modelo do Transformers, substitua todos os imports relativos no início do arquivo modeling.py para importar do Transformers.

  • configuration.py: Contém o código de ResnetConfig.
  • __init__.py: Pode estar vazio; esse arquivo permite que o Python utilize resnet_model como um módulo.
.
└── resnet_model
    ├── __init__.py
    ├── configuration_resnet.py
    └── modeling_resnet.py

Para compartilhar o modelo, importe o modelo e a configuração do ResNet.

from resnet_model.configuration_resnet import ResnetConfig
from resnet_model.modeling_resnet import ResnetModel, ResnetModelForImageClassification

Copie o código dos arquivos de modelo e de configuração. Para garantir que os objetos AutoClass sejam salvos com save_pretrained(), chame o método register_for_auto_class(). Isso modifica o arquivo JSON de configuração para incluir os objetos AutoClass e o mapeamento.

Para um modelo, escolha a classe AutoModelFor adequada com base na tarefa.

ResnetConfig.register_for_auto_class()
ResnetModel.register_for_auto_class("AutoModel")
ResnetModelForImageClassification.register_for_auto_class("AutoModelForImageClassification")

Para mapear mais de uma tarefa para o modelo, edite auto_map diretamente no arquivo JSON de configuração.

"auto_map": {
    "AutoConfig": "<your-repo-name>--<config-name>",
    "AutoModel": "<your-repo-name>--<config-name>",
    "AutoModelFor<Task>": "<your-repo-name>--<config-name>",    
},

Crie a configuração e o modelo e carregue os pesos pré-treinados nele.

resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d = ResnetModelForImageClassification(resnet50d_config)

pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())

O modelo está pronto para ser enviado ao Hub. Faça login na sua conta do Hugging Face pela linha de comando ou pelo notebook.

huggingface-CLI
notebook
hf auth login

Chame push_to_hub() no modelo para enviar o modelo ao Hub.

resnet50d.push_to_hub("custom-resnet50d")

Os pesos pré-treinados, a configuração e os arquivos modeling.py e configuration.py devem ser enviados ao Hub em um repositório sob seu namespace.

Como um modelo personalizado não usa o mesmo código de modelagem que um modelo do Transformers, você precisa adicionar trust_remote_code=True em from_pretrained() para carregá-lo. Consulte a seção de carregamento de modelos personalizados para mais informações.

Update on GitHub