Buckets:

hf-doc-build/doc / transformers /main /pt /custom_models.md
mishig's picture
|
download
raw
14.3 kB
# 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](https://github.com/huggingface/transformers/tree/main/src/transformers/models) 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.
> [!TIP]
> 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](#autoclass) e compartilhá-lo no Hub.
## Configuração
A configuração, definida pela classe base [PreTrainedConfig](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig), contém todas as informações necessárias para construir um modelo. É aqui que você configura 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](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig). Isso garante que um modelo personalizado tenha todas as funcionalidades de um modelo do Transformers, como [from_pretrained()](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig.from_pretrained), [save_pretrained()](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig.save_pretrained) e [push_to_hub()](/docs/transformers/main/pt/main_classes/model#transformers.utils.PushToHubMixin.push_to_hub).
2. O `__init__` do [PreTrainedConfig](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig) deve aceitar quaisquer `kwargs` e eles devem ser passados para o `__init__` da superclasse. O [PreTrainedConfig](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig) possui mais campos do que os definidos na sua configuração personalizada, portanto, ao carregar uma configuração com [from_pretrained()](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig.from_pretrained), esses campos precisam ser aceitos pela sua configuração e passados para a superclasse.
> [!TIP]
> É ú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](#autoclass).
```py
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()](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig.save_pretrained).
```py
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](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel). Assim como no [PreTrainedConfig](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig), herdar de [PreTrainedModel](/docs/transformers/main/pt/main_classes/model#transformers.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 múltiplos 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 reutilizar 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.
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.
> [!TIP]
> Adicione `config_class` à classe do modelo para habilitar o suporte a [AutoClass](#autoclass).
```py
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)
```
O método `forward` precisa ser reescrito para calcular a perda para cada logit, caso os rótulos estejam disponíveis. Caso contrário, a classe do modelo ResNet é a mesma.
> [!TIP]
> Adicione `config_class` à classe do modelo para habilitar o suporte a [AutoClass](#autoclass).
```py
import torch
class ResnetModelForImageClassification(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, labels=None):
logits = self.model(tensor)
if labels is not None:
loss = torch.nn.functional.cross_entropy(logits, labels)
return {"loss": loss, "logits": logits}
return {"logits": logits}
```
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](/docs/transformers/main/pt/main_classes/trainer#transformers.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.
```py
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](https://hf.co/docs/timm/index) e, em seguida, transfira esses pesos para o modelo personalizado com [load_state_dict](https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.load_state_dict).
```py
import timm
pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())
```
## AutoClass
A API [AutoClass](./models#model-classes) é 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()](/docs/transformers/main/pt/model_doc/auto#transformers.AutoConfig.register) para adicionar a configuração e o modelo personalizados à API [AutoClass](./models#model-classes).
> [!TIP]
> O primeiro argumento de [AutoConfig.register()](/docs/transformers/main/pt/model_doc/auto#transformers.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.
```py
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](#autoclass). Os usuários podem carregar o modelo com as classes [AutoModel](./model_doc/auto) ou [AutoModelForImageClassification](/docs/transformers/main/pt/model_doc/auto#transformers.AutoModelForImageClassification).
## Upload
Envie um modelo personalizado para o [Hub](https://hf.co/models) 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.
> [!WARNING]
> Ao copiar um arquivo de modelo do Transformers, substitua todos os imports relativos no topo 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.
```bash
.
└── resnet_model
├── __init__.py
├── configuration_resnet.py
└── modeling_resnet.py
```
Para compartilhar o modelo, importe o modelo e a configuração do ResNet.
```py
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()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.save_pretrained), chame o método [register_for_auto_class()](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig.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.
```py
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.
```json
"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.
```py
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.
```bash
hf auth login
```
```py
from huggingface_hub import notebook_login
notebook_login()
```
Chame [push_to_hub()](/docs/transformers/main/pt/main_classes/model#transformers.utils.PushToHubMixin.push_to_hub) no modelo para enviar o modelo ao Hub.
```py
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](https://hf.co/sgugger/custom-resnet50d) 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()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained) para carregá-lo. Consulte a seção de carregamento de [modelos personalizados](./models#custom-models) para mais informações.

Xet Storage Details

Size:
14.3 kB
·
Xet hash:
df8e78a934bf4acb8914adb5668122c9fcae43297d0dc5c6048153c8f8262978

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.