创建一个自定义架构
一个AutoClass
自动推断模型架构并下载预训练的配置和权重。通常,我们建议使用AutoClass
来生成与检查点无关的代码。但是,希望对特定模型参数有更多控制的用户可以从几个基础类创建一个自定义的🤗 Transformers模型。这对于任何有兴趣研究、训练或实验🤗 Transformers模型的人来说可能特别有用。在本指南中,深入了解如何在没有AutoClass
的情况下创建自定义模型。学习如何:
- 加载并自定义模型配置。
- 创建一个模型架构。
- 为文本创建一个慢速和快速的分词器。
- 为视觉任务创建一个图像处理器。
- 为音频任务创建一个特征提取器。
- 创建一个用于多模态任务的处理器。
配置
一个配置指的是模型的特定属性。每个模型配置都有不同的属性;例如,所有NLP模型都有hidden_size
、num_attention_heads
、num_hidden_layers
和vocab_size
这些共同属性。这些属性指定了构建模型时使用的注意力头数或隐藏层数。
通过访问DistilBERT的DistilBertConfig来查看其属性,以更深入地了解它:
>>> from transformers import DistilBertConfig
>>> config = DistilBertConfig()
>>> print(config)
DistilBertConfig {
"activation": "gelu",
"attention_dropout": 0.1,
"dim": 768,
"dropout": 0.1,
"hidden_dim": 3072,
"initializer_range": 0.02,
"max_position_embeddings": 512,
"model_type": "distilbert",
"n_heads": 12,
"n_layers": 6,
"pad_token_id": 0,
"qa_dropout": 0.1,
"seq_classif_dropout": 0.2,
"sinusoidal_pos_embds": false,
"transformers_version": "4.16.2",
"vocab_size": 30522
}
DistilBertConfig 显示了用于构建基础 DistilBertModel 的所有默认属性。所有属性都是可定制的,为实验创造了空间。例如,您可以自定义默认模型以:
- 尝试使用
activation
参数来使用不同的激活函数。 - 使用
attention_dropout
参数为注意力概率设置更高的丢弃率。
>>> my_config = DistilBertConfig(activation="relu", attention_dropout=0.4)
>>> print(my_config)
DistilBertConfig {
"activation": "relu",
"attention_dropout": 0.4,
"dim": 768,
"dropout": 0.1,
"hidden_dim": 3072,
"initializer_range": 0.02,
"max_position_embeddings": 512,
"model_type": "distilbert",
"n_heads": 12,
"n_layers": 6,
"pad_token_id": 0,
"qa_dropout": 0.1,
"seq_classif_dropout": 0.2,
"sinusoidal_pos_embds": false,
"transformers_version": "4.16.2",
"vocab_size": 30522
}
预训练模型的属性可以在from_pretrained()函数中修改:
>>> my_config = DistilBertConfig.from_pretrained("distilbert/distilbert-base-uncased", activation="relu", attention_dropout=0.4)
一旦你对模型配置感到满意,你可以使用save_pretrained()保存它。你的配置文件将以JSON文件的形式存储在指定的保存目录中:
>>> my_config.save_pretrained(save_directory="./your_model_save_path")
要重用配置文件,请使用from_pretrained()加载它:
>>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/config.json")
你也可以将你的配置文件保存为字典,或者只保存自定义配置属性与默认配置属性之间的差异!更多详情请参阅配置文档。
模型
下一步是创建一个模型。模型——也被宽泛地称为架构——定义了每一层在做什么以及正在发生哪些操作。配置中的属性如num_hidden_layers
用于定义架构。每个模型都共享基类PreTrainedModel和一些常见方法,如调整输入嵌入和修剪自注意力头。此外,所有模型也是torch.nn.Module
、tf.keras.Model
或flax.linen.Module
的子类。这意味着模型与各自框架的使用是兼容的。
将您的自定义配置属性加载到模型中:
>>> from transformers import DistilBertModel
>>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/config.json")
>>> model = DistilBertModel(my_config)
这将创建一个具有随机值而不是预训练权重的模型。在训练之前,您将无法将此模型用于任何有用的用途。训练是一个昂贵且耗时的过程。通常,使用预训练模型可以更快地获得更好的结果,同时仅使用训练所需资源的一小部分。
使用from_pretrained()创建一个预训练模型:
>>> model = DistilBertModel.from_pretrained("distilbert/distilbert-base-uncased")
当你加载预训练权重时,如果模型是由🤗 Transformers提供的,默认的模型配置会自动加载。但是,你仍然可以替换默认模型配置的部分或全部属性,如果你愿意的话:
>>> model = DistilBertModel.from_pretrained("distilbert/distilbert-base-uncased", config=my_config)
将您的自定义配置属性加载到模型中:
>>> from transformers import TFDistilBertModel
>>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/my_config.json")
>>> tf_model = TFDistilBertModel(my_config)
这将创建一个具有随机值而不是预训练权重的模型。在训练之前,您将无法将此模型用于任何有用的用途。训练是一个昂贵且耗时的过程。通常,使用预训练模型可以更快地获得更好的结果,同时仅使用训练所需资源的一小部分。
使用from_pretrained()创建一个预训练模型:
>>> tf_model = TFDistilBertModel.from_pretrained("distilbert/distilbert-base-uncased")
当你加载预训练权重时,如果模型是由🤗 Transformers提供的,默认的模型配置会自动加载。但是,你仍然可以替换默认模型配置的部分或全部属性,如果你愿意的话:
>>> tf_model = TFDistilBertModel.from_pretrained("distilbert/distilbert-base-uncased", config=my_config)
模型头
此时,您已经拥有了一个输出隐藏状态的基础DistilBERT模型。隐藏状态作为输入传递给模型头部以生成最终输出。🤗 Transformers为每个任务提供了不同的模型头部,只要模型支持该任务(即,您不能将DistilBERT用于像翻译这样的序列到序列任务)。
例如,DistilBertForSequenceClassification 是一个带有序列分类头的基础 DistilBERT 模型。序列分类头是在池化输出之上的一个线性层。
>>> from transformers import DistilBertForSequenceClassification
>>> model = DistilBertForSequenceClassification.from_pretrained("distilbert/distilbert-base-uncased")
通过切换到不同的模型头,可以轻松地将此检查点重用于另一个任务。对于问答任务,您将使用DistilBertForQuestionAnswering模型头。问答头与序列分类头类似,只是它在隐藏状态输出之上有一个线性层。
>>> from transformers import DistilBertForQuestionAnswering
>>> model = DistilBertForQuestionAnswering.from_pretrained("distilbert/distilbert-base-uncased")
例如,TFDistilBertForSequenceClassification 是一个带有序列分类头的基础 DistilBERT 模型。序列分类头是在池化输出之上的线性层。
>>> from transformers import TFDistilBertForSequenceClassification
>>> tf_model = TFDistilBertForSequenceClassification.from_pretrained("distilbert/distilbert-base-uncased")
通过切换到不同的模型头,可以轻松地将此检查点重用于另一个任务。对于问答任务,您将使用TFDistilBertForQuestionAnswering模型头。问答头与序列分类头类似,只是它在隐藏状态输出之上有一个线性层。
>>> from transformers import TFDistilBertForQuestionAnswering
>>> tf_model = TFDistilBertForQuestionAnswering.from_pretrained("distilbert/distilbert-base-uncased")
分词器
在使用模型处理文本数据之前,您需要的最后一个基类是一个tokenizer,用于将原始文本转换为张量。您可以使用🤗 Transformers中的两种类型的tokenizer:
- PreTrainedTokenizer: 一个Python实现的标记器。
- PreTrainedTokenizerFast: 一个来自我们基于Rust的🤗 Tokenizer库的分词器。由于其Rust实现,这种分词器类型显著更快——尤其是在批量分词时。快速分词器还提供了额外的方法,如偏移映射,它将标记映射到原始单词或字符。
两个分词器都支持常见的方法,如编码和解码、添加新标记以及管理特殊标记。
并非每个模型都支持快速分词器。请查看此表格以检查模型是否支持快速分词器。
如果你训练了自己的分词器,你可以从你的词汇表文件中创建一个:
>>> from transformers import DistilBertTokenizer
>>> my_tokenizer = DistilBertTokenizer(vocab_file="my_vocab_file.txt", do_lower_case=False, padding_side="left")
重要的是要记住,自定义分词器的词汇表将与预训练模型的分词器生成的词汇表不同。如果您使用的是预训练模型,则需要使用预训练模型的词汇表,否则输入将没有意义。使用DistilBertTokenizer类创建一个带有预训练模型词汇表的分词器:
>>> from transformers import DistilBertTokenizer
>>> slow_tokenizer = DistilBertTokenizer.from_pretrained("distilbert/distilbert-base-uncased")
使用DistilBertTokenizerFast类创建一个快速分词器:
>>> from transformers import DistilBertTokenizerFast
>>> fast_tokenizer = DistilBertTokenizerFast.from_pretrained("distilbert/distilbert-base-uncased")
默认情况下,AutoTokenizer 会尝试加载一个快速分词器。你可以通过在 from_pretrained
中设置 use_fast=False
来禁用此行为。
图像处理器
图像处理器处理视觉输入。它继承自基础类 ImageProcessingMixin。
要使用,请创建一个与您正在使用的模型相关联的图像处理器。例如,如果您使用ViT进行图像分类,请创建一个默认的ViTImageProcessor:
>>> from transformers import ViTImageProcessor
>>> vit_extractor = ViTImageProcessor()
>>> print(vit_extractor)
ViTImageProcessor {
"do_normalize": true,
"do_resize": true,
"image_processor_type": "ViTImageProcessor",
"image_mean": [
0.5,
0.5,
0.5
],
"image_std": [
0.5,
0.5,
0.5
],
"resample": 2,
"size": 224
}
如果你不需要任何定制化,只需使用from_pretrained
方法来加载模型的默认图像处理器参数。
修改任何ViTImageProcessor参数以创建您的自定义图像处理器:
>>> from transformers import ViTImageProcessor
>>> my_vit_extractor = ViTImageProcessor(resample="PIL.Image.BOX", do_normalize=False, image_mean=[0.3, 0.3, 0.3])
>>> print(my_vit_extractor)
ViTImageProcessor {
"do_normalize": false,
"do_resize": true,
"image_processor_type": "ViTImageProcessor",
"image_mean": [
0.3,
0.3,
0.3
],
"image_std": [
0.5,
0.5,
0.5
],
"resample": "PIL.Image.BOX",
"size": 224
}
Backbone
![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/Backbone.png)
计算机视觉模型由骨干网络、颈部网络和头部网络组成。骨干网络从输入图像中提取特征,颈部网络结合并增强提取的特征,头部网络用于主要任务(例如,目标检测)。首先在模型配置中初始化骨干网络,并指定是否要加载预训练权重或加载随机初始化的权重。然后,您可以将模型配置传递给模型头部。
例如,要将一个ResNet骨干网络加载到一个带有实例分割头的MaskFormer模型中:
<hfoptions id="backbone"> <hfoption id="pretrained weights">设置 use_pretrained_backbone=True
以加载预训练的 ResNet 权重作为骨干网络。
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
config = MaskFormerConfig(backbone="microsoft/resnet-50", use_pretrained_backbone=True) # backbone and neck config
model = MaskFormerForInstanceSegmentation(config) # head
设置 use_pretrained_backbone=False
以随机初始化一个 ResNet 骨干网络。
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
config = MaskFormerConfig(backbone="microsoft/resnet-50", use_pretrained_backbone=False) # backbone and neck config
model = MaskFormerForInstanceSegmentation(config) # head
你也可以单独加载骨干配置,然后将其传递给模型配置。
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation, ResNetConfig
backbone_config = ResNetConfig()
config = MaskFormerConfig(backbone_config=backbone_config)
model = MaskFormerForInstanceSegmentation(config)
timm 模型在模型中使用 use_timm_backbone=True
或通过 TimmBackbone 和 TimmBackboneConfig 加载。
使用 use_timm_backbone=True
和 use_pretrained_backbone=True
来加载预训练的 timm 权重作为骨干网络。
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
config = MaskFormerConfig(backbone="resnet50", use_pretrained_backbone=True, use_timm_backbone=True) # backbone and neck config
model = MaskFormerForInstanceSegmentation(config) # head
设置 use_timm_backbone=True
和 use_pretrained_backbone=False
以加载一个随机初始化的 timm 骨干网络。
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
config = MaskFormerConfig(backbone="resnet50", use_pretrained_backbone=False, use_timm_backbone=True) # backbone and neck config
model = MaskFormerForInstanceSegmentation(config) # head
你也可以加载骨干网络配置并使用它来创建一个TimmBackbone
或将其传递给模型配置。Timm骨干网络默认会加载预训练权重。设置use_pretrained_backbone=False
以加载随机初始化的权重。
from transformers import TimmBackboneConfig, TimmBackbone
backbone_config = TimmBackboneConfig("resnet50", use_pretrained_backbone=False)
# Create a backbone class
backbone = TimmBackbone(config=backbone_config)
# Create a model with a timm backbone
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
config = MaskFormerConfig(backbone_config=backbone_config)
model = MaskFormerForInstanceSegmentation(config)
特征提取器
特征提取器处理音频输入。它继承自基础FeatureExtractionMixin类,也可能继承自SequenceFeatureExtractor类以处理音频输入。
要使用,请创建一个与您正在使用的模型相关联的特征提取器。例如,如果您正在使用Wav2Vec2进行音频分类,请创建一个默认的Wav2Vec2FeatureExtractor:
>>> from transformers import Wav2Vec2FeatureExtractor
>>> w2v2_extractor = Wav2Vec2FeatureExtractor()
>>> print(w2v2_extractor)
Wav2Vec2FeatureExtractor {
"do_normalize": true,
"feature_extractor_type": "Wav2Vec2FeatureExtractor",
"feature_size": 1,
"padding_side": "right",
"padding_value": 0.0,
"return_attention_mask": false,
"sampling_rate": 16000
}
如果你不需要任何定制化,只需使用 from_pretrained
方法来加载模型的默认特征提取器参数。
修改任何Wav2Vec2FeatureExtractor参数以创建您的自定义特征提取器:
>>> from transformers import Wav2Vec2FeatureExtractor
>>> w2v2_extractor = Wav2Vec2FeatureExtractor(sampling_rate=8000, do_normalize=False)
>>> print(w2v2_extractor)
Wav2Vec2FeatureExtractor {
"do_normalize": false,
"feature_extractor_type": "Wav2Vec2FeatureExtractor",
"feature_size": 1,
"padding_side": "right",
"padding_value": 0.0,
"return_attention_mask": false,
"sampling_rate": 8000
}
处理器
对于支持多模态任务的模型,🤗 Transformers 提供了一个处理器类,方便地将特征提取器和分词器等处理类封装到一个对象中。例如,让我们使用 Wav2Vec2Processor 进行自动语音识别任务(ASR)。ASR 将音频转录为文本,因此您需要一个特征提取器和一个分词器。
创建一个特征提取器来处理音频输入:
>>> from transformers import Wav2Vec2FeatureExtractor
>>> feature_extractor = Wav2Vec2FeatureExtractor(padding_value=1.0, do_normalize=True)
创建一个分词器来处理文本输入:
>>> from transformers import Wav2Vec2CTCTokenizer
>>> tokenizer = Wav2Vec2CTCTokenizer(vocab_file="my_vocab_file.txt")
将特征提取器和分词器结合在Wav2Vec2Processor中:
>>> from transformers import Wav2Vec2Processor
>>> processor = Wav2Vec2Processor(feature_extractor=feature_extractor, tokenizer=tokenizer)
通过两个基本类——配置和模型——以及一个额外的预处理类(分词器、图像处理器、特征提取器或处理器),您可以创建🤗 Transformers支持的任何模型。这些基类中的每一个都是可配置的,允许您使用所需的特定属性。您可以轻松设置模型进行训练,或修改现有的预训练模型以进行微调。
< > Update on GitHub