创建自定义架构(模型架构)¶
AutoClass 可以自动推断模型架构并下载预训练的配置和权重。通常,我们建议使用 AutoClass 来生成与检查点无关的代码。但是,希望对特定模型参数有更多控制的用户可以从一些基础类中创建自定义 🤗 Transformers 模型。这特别有助于那些研究、训练或实验 🤗 Transformers 模型的人。本指南将深入介绍如何在不使用 AutoClass 的情况下创建自定义模型。您将学习如何:
- 加载和自定义模型配置。
- 创建模型架构。
- 为文本创建慢速和快速分词器。
- 为视觉任务创建图像处理器。
- 为音频任务创建特征提取器。
- 为多模态任务创建处理器。
配置¶
配置是指模型的具体属性。每个模型配置都有不同的属性;例如,所有自然语言处理模型都有一些共同的属性,如 hidden_size、num_attention_heads、num_hidden_layers 和 vocab_size。这些属性指定了构建模型时要使用的注意力头数量或隐藏层数量。
通过访问 DistilBertConfig 来查看 DistilBERT 的属性:
from transformers import DistilBertConfig
config = DistilBertConfig()
print(config)
DistilBertConfig 显示了用于构建基础 DistilBertModel 的所有默认属性。所有属性都可以自定义,为实验提供了空间。例如,您可以使用 activation 参数尝试不同的激活函数,使用 attention_dropout 参数调整注意力概率的更高 dropout 比率。
my_config = DistilBertConfig(activation="relu", attention_dropout=0.4)
print(my_config)
预训练模型的属性可以在 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")
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)
TensorFlow¶
加载自定义配置属性到模型中:
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)
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")
TensorFlow¶
例如,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")
分词器¶
在使用模型处理文本数据之前,您需要一个分词器将原始文本转换为张量。🤗 Transformers 支持两种类型的分词器:
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)
如果您不需要任何自定义,只需使用 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)
主干网络¶
计算机视觉模型由主干网络、颈部和头部组成。主干网络从输入图像中提取特征,颈部组合和增强提取的特征,头部用于主要任务(如对象检测)。首先在模型配置中初始化主干网络,并指定是否要加载预训练权重或随机初始化权重。然后,您可以将模型配置传递给模型头部。
例如,将 ResNet 主干网络加载到带有实例分割头部的 MaskFormer 模型中:
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
# 加载预训练的 ResNet 权重
config = MaskFormerConfig(backbone="microsoft/resnet-50", use_pretrained_backbone=True) # 主干网络和颈部配置
model = MaskFormerForInstanceSegmentation(config) # 头部
# 随机初始化 ResNet 主干网络
config = MaskFormerConfig(backbone="microsoft/resnet-50", use_pretrained_backbone=False) # 主干网络和颈部配置
model = MaskFormerForInstanceSegmentation(config) # 头部
您也可以单独加载主干网络配置,然后将其传递给模型配置。
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) # 主干网络和颈部配置
model = MaskFormerForInstanceSegmentation(config) # 头部
使用 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) # 主干网络和颈部配置
model = MaskFormerForInstanceSegmentation(config) # 头部
您还可以单独加载主干网络配置,使用它创建 TimmBackbone 或将其传递给模型配置。timm 主干网络默认加载预训练权重。使用 use_pretrained_backbone=False 加载随机初始化的权重。
from transformers import TimmBackboneConfig, TimmBackbone
backbone_config = TimmBackboneConfig("resnet50", use_pretrained_backbone=False)
# 创建主干网络类
backbone = TimmBackbone(config=backbone_config)
# 创建带有 `timm` 主干网络的模型
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)
如果您不需要任何自定义,只需使用 from_pretrained 方法加载模型的默认特征提取器参数。
修改 Wav2Vec2FeatureExtractor 的任何参数以创建自定义特征提取器:
from transformers import Wav2Vec2FeatureExtractor
w2v2_extractor = Wav2Vec2FeatureExtractor(sampling_rate=8000, do_normalize=False)
print(w2v2_extractor)
处理器¶
对于支持多模态任务的模型,🤗 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 支持的任何模型。这些基类都是可配置的,允许您使用所需的特定属性。您可以轻松地设置模型进行训练或修改现有的预训练模型以进行微调。