Transformers 文档
自定义模型
并获得增强的文档体验
开始
自定义模型
Transformers 模型被设计为可自定义的。模型的代码完全包含在 Transformers 仓库的 model 子文件夹中。每个文件夹包含一个 modeling.py
和一个 configuration.py
文件。复制这些文件以开始自定义模型。
如果您要创建全新的模型,从头开始可能会更容易。但是对于与 Transformers 中现有模型非常相似的模型,重用或子类化相同的配置和模型类会更快。
本指南将向您展示如何自定义 ResNet 模型,启用 AutoClass 支持,并在 Hub 上共享它。
配置
配置,由基础 PretrainedConfig 类给出,包含构建模型的所有必要信息。您可以在这里配置自定义 ResNet 模型的属性。不同的属性会产生不同的 ResNet 模型类型。
自定义配置的主要规则是
- 自定义配置必须子类化 PretrainedConfig。这确保了自定义模型具有 Transformers 模型的所有功能,例如 from_pretrained()、save_pretrained() 和 push_to_hub()。
- PretrainedConfig
__init__
必须接受任何kwargs
,并且它们必须传递给超类__init__
。PretrainedConfig 具有比自定义配置中设置的字段更多的字段,因此当您使用 from_pretrained() 加载配置时,这些字段需要被您的配置接受并传递给超类。
检查某些参数的有效性很有用。在下面的示例中,实现了一个检查以确保 block_type
和 stem_type
属于预定义的值之一。
将 model_type
添加到配置类以启用 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)
使用 save_pretrained() 将配置保存到自定义模型文件夹 custom-resnet
中的 JSON 文件中。
resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d_config.save_pretrained("custom-resnet")
模型
有了自定义 ResNet 配置,您现在可以创建和自定义模型。该模型子类化了基础 PreTrainedModel 类。与 PretrainedConfig 类似,从 PreTrainedModel 继承并将超类与配置一起初始化,扩展了 Transformers 的功能,例如将保存和加载到自定义模型。
Transformers 模型遵循在 __init__
方法中接受 config
对象的约定。这会将整个 config
传递给模型子层,而不是将 config
对象分解为多个单独传递给子层的参数。
以这种方式编写模型会生成更简单的代码,并为任何超参数提供清晰的事实来源。这也使得重用来自其他 Transformers 模型代码变得更容易。
您将创建两个 ResNet 模型,一个输出隐藏状态的精简 ResNet 模型和一个带有图像分类头的 ResNet 模型。
定义块类型和类之间的映射。其他所有内容都是通过将配置类传递给 ResNet 模型类来创建的。
将 config_class
添加到模型类以启用 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)
模型可以返回任何输出格式。当标签可用时,返回带有损失的字典(如 ResnetModelForImageClassification
)使自定义模型与 Trainer 兼容。对于其他输出格式,您将需要自己的训练循环或不同的库进行训练。
使用配置实例化自定义模型类。
resnet50d = ResnetModelForImageClassification(resnet50d_config)
此时,您可以将预训练权重加载到模型中或从头开始训练它。在本指南中,您将加载预训练权重。
从 timm 库加载预训练权重,然后使用 load_state_dict 将这些权重转移到自定义模型。
import timm
pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())
AutoClass
AutoClass API 是自动为给定模型加载正确架构的快捷方式。为加载自定义模型的用户启用此功能很方便。
确保在配置类中具有 model_type
属性(必须与现有模型类型不同),并在模型类中具有 config_class
属性。使用 register() 方法将自定义配置和模型添加到 AutoClass API。
AutoConfig.register() 的第一个参数必须与自定义配置类中的 model_type
属性匹配,而 AutoModel.register()
的第一个参数必须与自定义模型类的 config_class
匹配。
from transformers import AutoConfig, AutoModel, AutoModelForImageClassification
AutoConfig.register("resnet", ResnetConfig)
AutoModel.register(ResnetConfig, ResnetModel)
AutoModelForImageClassification.register(ResnetConfig, ResnetModelForImageClassification)
您的自定义模型代码现在与 AutoClass API 兼容。用户可以使用 AutoModel 或 AutoModelForImageClassification 类加载模型。
上传
将自定义模型上传到 Hub,以便其他用户可以轻松加载和使用它。
确保模型目录结构正确,如下所示。该目录应包含
modeling.py
:包含ResnetModel
和ResnetModelForImageClassification
的代码。此文件可以依赖于与同一目录中其他文件的相对导入。
复制 Transformers 模型文件时,请替换 modeling.py
文件顶部的所有相对导入,以改为从 Transformers 导入。
configuration.py
:包含ResnetConfig
的代码。__init__.py
:可以为空,此文件允许将 Pythonresnet_model
用作模块。
. └── resnet_model ├── __init__.py ├── configuration_resnet.py └── modeling_resnet.py
要共享模型,请导入 ResNet 模型和配置。
from resnet_model.configuration_resnet import ResnetConfig
from resnet_model.modeling_resnet import ResnetModel, ResnetModelForImageClassification
复制模型和配置文件中的代码。为确保 AutoClass 对象与 save_pretrained() 一起保存,请调用 register_for_auto_class() 方法。这将修改配置 JSON 文件以包含 AutoClass 对象和映射。
对于模型,请根据任务选择适当的 AutoModelFor
类。
ResnetConfig.register_for_auto_class()
ResnetModel.register_for_auto_class("AutoModel")
ResnetModelForImageClassification.register_for_auto_class("AutoModelForImageClassification")
要将多个任务映射到模型,请直接编辑配置 JSON 文件中的 auto_map
。
"auto_map": {
"AutoConfig": "<your-repo-name>--<config-name>",
"AutoModel": "<your-repo-name>--<config-name>",
"AutoModelFor<Task>": "<your-repo-name>--<config-name>",
},
创建配置和模型,并将预训练权重加载到其中。
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())
模型现在可以推送到 Hub 了。从命令行或笔记本电脑登录到您的 Hugging Face 帐户。
huggingface-cli login
在模型上调用 push_to_hub() 以将模型上传到 Hub。
resnet50d.push_to_hub("custom-resnet50d")
预训练权重、配置、modeling.py
和 configuration.py
文件现在都应上传到 Hub,并位于您命名空间下的 repository 中。
由于自定义模型不使用与 Transformers 模型相同的建模代码,因此您需要在 from_pretrained() 中添加 trust_remode_code=True
才能加载它。有关更多信息,请参阅加载自定义模型部分。