Transformers documentation

Personalización de modelos

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Personalización de modelos

Los modelos de Transformers están diseñados para ser personalizables. El código de un modelo está completamente contenido en la subcarpeta model del repositorio de Transformers. Cada carpeta contiene un archivo modeling.py y un archivo configuration.py. Copia estos archivos para comenzar a personalizar un modelo.

Puede ser más fácil empezar desde cero si estás creando un modelo completamente nuevo. Pero para modelos que son muy similares a uno existente en Transformers, es más rápido reutilizar o subclasear la misma clase de configuración y de modelo.

Esta guía te mostrará cómo personalizar un modelo ResNet, habilitar el soporte de AutoClass y compartirlo en el Hub.

Configuración

Una configuración, definida por la clase base PreTrainedConfig, contiene toda la información necesaria para construir un modelo. Aquí es donde se configuran los atributos del modelo ResNet personalizado. Diferentes atributos producen diferentes tipos de modelos ResNet.

Las reglas principales para personalizar una configuración son:

  1. Una configuración personalizada debe ser una subclase de PreTrainedConfig. Esto garantiza que un modelo personalizado tenga toda la funcionalidad de un modelo de Transformers, como from_pretrained(), save_pretrained() y push_to_hub().
  2. El __init__ de PreTrainedConfig debe aceptar cualquier kwargs y estos deben pasarse al __init__ de la superclase. PreTrainedConfig tiene más campos que los establecidos en su configuración personalizada, por lo que, al cargar una configuración con from_pretrained(), esos campos deben ser aceptados por su configuración y pasados a la superclase.

Es útil comprobar la validez de algunos de los parámetros. En el ejemplo siguiente, se implementa una comprobación para garantizar que block_type y stem_type pertenezcan a uno de los valores predefinidos.

Agregue model_type a la clase de configuración para habilitar el soporte de 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)

Guarde la configuración en un archivo JSON en su carpeta de modelo personalizado, custom-resnet, con save_pretrained().

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

Modelo

Con la configuración personalizada de ResNet, ahora puede crear y personalizar el modelo. El modelo es una subclase de la clase base PreTrainedModel. Al igual que con PreTrainedConfig, heredar de PreTrainedModel e inicializar la superclase con la configuración extiende las funcionalidades de Transformers, como el guardado y la carga, al modelo personalizado.

Los modelos de Transformers siguen la convención de aceptar un objeto config en el método __init__. Esto pasa el objeto config completo a las subcapas del modelo, en lugar de dividir el objeto config en múltiples argumentos que se pasan individualmente a las subcapas.

Escribir modelos de esta manera produce un código más simple con una fuente de verdad clara para cualquier hiperparámetro. También facilita reutilizar código de otros modelos de Transformers.

Crearás dos modelos ResNet, un modelo ResNet básico que genera los estados ocultos y un modelo ResNet con una cabeza de clasificación de imágenes.

ResnetModel
ResnetModelForImageClassification

Defina un mapeo entre los tipos de bloques y las clases. Todo lo demás se crea pasando la clase de configuración a la clase de modelo ResNet.

Agrega config_class a la clase del modelo para habilitar el soporte de 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)

Un modelo puede devolver cualquier formato de salida. Devolver un diccionario (como ResnetModelForImageClassification) con pérdidas cuando hay etiquetas disponibles hace que el modelo personalizado sea compatible con Trainer. Para otros formatos de salida, necesitarás tu propio bucle de entrenamiento o una biblioteca diferente para el entrenamiento.

Instancia la clase de modelo personalizada con la configuración.

resnet50d = ResnetModelForImageClassification(resnet50d_config)

En este punto, puedes cargar pesos preentrenados en el modelo o entrenarlo desde cero. En esta guía, cargarás pesos preentrenados.

Cargue los pesos preentrenados desde la biblioteca timm y luego transfiera esos pesos al modelo personalizado con load_state_dict.

import timm

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

AutoClass

La API AutoClass es una atajo para cargar automáticamente la arquitectura correcta de un modelo dado. Es conveniente habilitar esto para los usuarios que carguen su modelo personalizado.

Asegúrate de que la clase de configuración tenga el atributo model_type (debe ser diferente de los tipos de modelo existentes) y la clase de modelo tenga el atributo config_class. Usa el método register() para añadir la configuración y el modelo personalizados a la API de AutoClass.

El primer argumento de AutoConfig.register() debe coincidir con el atributo model_type de la clase de configuración personalizada, y el primer argumento de AutoModel.register() debe coincidir con el config_class de la clase de modelo personalizada.

from transformers import AutoConfig, AutoModel, AutoModelForImageClassification

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

El código de su modelo personalizado ahora es compatible con la API de AutoClass. Los usuarios pueden cargar el modelo con las clases AutoModel o AutoModelForImageClassification.

Subir

Sube un modelo personalizado al Hub para que otros usuarios puedan cargarlo y usarlo fácilmente.

Asegúrate de que el directorio del modelo esté estructurado correctamente, como se muestra a continuación. El directorio debe contener:

  • modeling.py: Contiene el código de ResnetModel y ResnetModelForImageClassification. Este archivo puede depender de importaciones relativas a otros archivos siempre que estén en el mismo directorio.

Al copiar un archivo de modelo de Transformers, reemplace todas las importaciones relativas en la parte superior del archivo modeling.py para importar desde Transformers en su lugar.

  • configuration.py: Contiene el código de ResnetConfig.
  • __init__.py: Puede estar vacío, este archivo permite que Python utilice resnet_model como un módulo.
.
└── resnet_model
    ├── __init__.py
    ├── configuration_resnet.py
    └── modeling_resnet.py

Para compartir el modelo, importe el modelo y la configuración de ResNet.

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

Copia el código de los archivos de modelo y configuración. Para asegurarte de que los objetos AutoClass se guarden con save_pretrained(), llama al método register_for_auto_class(). Esto modifica el archivo JSON de configuración para incluir los objetos AutoClass y el mapeo.

Para un modelo, elige la clase AutoModelFor adecuada según la tarea.

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

Para mapear más de una tarea al modelo, edite auto_map directamente en el archivo JSON de configuración.

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

Cree la configuración y el modelo y cargue los pesos preentrenados en él.

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())

El modelo está listo para publicarse en el Hub. Inicia sesión en tu cuenta de Hugging Face desde la línea de comandos o el cuaderno.

huggingface-CLI
notebook
hf auth login

Llama a push_to_hub() en el modelo para subirlo al Hub.

resnet50d.push_to_hub("custom-resnet50d")

Los pesos preentrenados, la configuración y los archivos modeling.py y configuration.py deben subirse ahora al Hub en un repositorio bajo tu espacio de nombres.

Dado que un modelo personalizado no utiliza el mismo código de modelado que un modelo de Transformers, es necesario añadir trust_remote_code=True en from_pretrained() para cargarlo. Consulta la sección de carga de modelos personalizados para obtener más información.

Update on GitHub