Transformers documentation
视觉编码器-解码器模型
该模型于 2021-09-21 在 HF papers 上发布,并于 2021-10-13 贡献给 Hugging Face Transformers。
视觉编码器-解码器模型
概述
可以使用 VisionEncoderDecoderModel 来初始化一个图像到文本模型,其中编码器可以是任意基于 Transformer 的预训练视觉模型(例如 ViT、BEiT、DeiT、Swin),解码器可以是任意预训练语言模型(例如 RoBERTa、GPT2、BERT、DistilBERT)。
使用预训练检查点初始化图像到文本序列模型的有效性已在(例如)Minghao Li、Tengchao Lv、Lei Cui、Yijuan Lu、Dinei Florencio、Cha Zhang、Zhoujun Li 和 Furu Wei 的 TrOCR: Transformer-based Optical Character Recognition with Pre-trained Models 中得到证明。
在 VisionEncoderDecoderModel 完成训练/微调后,可以像其他模型一样进行保存/加载(更多信息请参见下文示例)。
一个示例应用是图像描述生成,其中编码器用于对图像进行编码,随后自回归语言模型生成描述文本。另一个示例是光学字符识别。请参阅 TrOCR,它是 VisionEncoderDecoderModel 的一个实例。
从模型配置中随机初始化 VisionEncoderDecoderModel
VisionEncoderDecoderModel 可以通过编码器和解码器的配置进行随机初始化。在下面的示例中,我们展示了如何使用编码器的默认 ViTModel 配置以及解码器的默认 BertForCausalLM 配置来实现这一点。
from transformers import BertConfig, VisionEncoderDecoderConfig, VisionEncoderDecoderModel, ViTConfig
config_encoder = ViTConfig()
config_decoder = BertConfig()
config = VisionEncoderDecoderConfig.from_encoder_decoder_configs(config_encoder, config_decoder)
model = VisionEncoderDecoderModel(config=config)从预训练编码器和预训练解码器初始化 VisionEncoderDecoderModel
VisionEncoderDecoderModel 可以从预训练的编码器检查点和预训练的解码器检查点进行初始化。请注意,任何基于 Transformer 的预训练视觉模型,例如 Swin,都可以作为编码器;而预训练的自编码模型(例如 BERT)、预训练的因果语言模型(例如 GPT2),以及序列到序列模型的预训练解码器部分(例如 BART 的解码器),都可以作为解码器。
根据您选择作为解码器的架构,交叉注意力层可能会被随机初始化。
如Warm-starting-encoder-decoder 博客文章中所示,从预训练的编码器和解码器检查点初始化 VisionEncoderDecoderModel 后,需要在下游任务上对模型进行微调。
为此,VisionEncoderDecoderModel 类提供了 VisionEncoderDecoderModel.from_encoder_decoder_pretrained() 方法。
from transformers import VisionEncoderDecoderModel
model = VisionEncoderDecoderModel.from_encoder_decoder_pretrained(
"microsoft/swin-base-patch4-window7-224-in22k", "google-bert/bert-base-uncased"
)加载现有的 VisionEncoderDecoderModel 检查点并执行推理
要加载 VisionEncoderDecoderModel 类的微调检查点,VisionEncoderDecoderModel 与 Transformers 中的其他模型架构一样,提供了 from_pretrained(...) 方法。
要执行推理,请使用 generate 方法,该方法支持自回归地生成文本。此方法支持多种解码形式,例如贪心解码、束搜索和多项式采样。
import requests
from PIL import Image
from transformers import GPT2TokenizerFast, ViTImageProcessor, VisionEncoderDecoderModel
# load a fine-tuned image captioning model and corresponding tokenizer and image processor
model = VisionEncoderDecoderModel.from_pretrained("nlpconnect/vit-gpt2-image-captioning", device_map="auto")
tokenizer = GPT2TokenizerFast.from_pretrained("nlpconnect/vit-gpt2-image-captioning")
image_processor = ViTImageProcessor.from_pretrained("nlpconnect/vit-gpt2-image-captioning")
# let's perform inference on an image
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)
pixel_values = image_processor(image, return_tensors="pt").to(model.device).pixel_values
# autoregressively generate caption (uses greedy decoding by default)
generated_ids = model.generate(pixel_values)
generated_text = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(generated_text)
a cat laying on a blanket next to a cat laying on a bed训练
模型创建完成后,可以在由(图像,文本)对组成的数据集上对其进行微调,方式与 BART、T5 或其他编码器-解码器模型类似。
如您所见,模型计算损失只需要 2 个输入:pixel_values(即图像)和 labels(即编码后的目标序列的 input_ids)。
from datasets import load_dataset
from transformers import BertTokenizer, VisionEncoderDecoderModel, ViTImageProcessor
image_processor = ViTImageProcessor.from_pretrained("google/vit-base-patch16-224-in21k")
tokenizer = BertTokenizer.from_pretrained("google-bert/bert-base-uncased")
model = VisionEncoderDecoderModel.from_encoder_decoder_pretrained(
"google/vit-base-patch16-224-in21k", "google-bert/bert-base-uncased"
)
model.config.decoder_start_token_id = tokenizer.cls_token_id
model.config.pad_token_id = tokenizer.pad_token_id
dataset = load_dataset("huggingface/cats-image")
image = dataset["test"]["image"][0]
pixel_values = image_processor(image, return_tensors="pt").to(model.device).pixel_values
labels = tokenizer(
"an image of two cats chilling on a couch",
return_tensors="pt",
).input_ids
# the forward function automatically creates the correct decoder_input_ids
loss = model(pixel_values=pixel_values, labels=labels).loss该模型由 nielsr 贡献。
VisionEncoderDecoderConfig
class transformers.VisionEncoderDecoderConfig
< source >( transformers_version: str | None = Nonearchitectures: list[str] | None = Noneoutput_hidden_states: bool | None = Falsereturn_dict: bool | None = Truedtype: str | torch.dtype | None = Nonechunk_size_feed_forward: int = 0id2label: dict[int, str] | dict[str, str] | None = Nonelabel2id: dict[str, int] | dict[str, str] | None = Noneproblem_type: Literal['regression', 'single_label_classification', 'multi_label_classification'] | None = Noneis_encoder_decoder: bool = Trueencoder: transformers.configuration_utils.PreTrainedConfig | dict | None = Nonedecoder: transformers.configuration_utils.PreTrainedConfig | dict | None = None )
这是用于存储视觉编码器-解码器模型配置的类。它根据指定的参数实例化视觉编码器-解码器模型,并定义模型架构。使用默认值实例化配置将得到与 None 类似的配置。
配置对象继承自 PreTrainedConfig,可用于控制模型输出。有关更多信息,请参阅 PreTrainedConfig 的文档。
示例:
>>> from transformers import BertConfig, ViTConfig, VisionEncoderDecoderConfig, VisionEncoderDecoderModel
>>> # Initializing a ViT & BERT style configuration
>>> config_encoder = ViTConfig()
>>> config_decoder = BertConfig()
>>> config = VisionEncoderDecoderConfig(encoder=config_encoder, decoder=config_decoder)
>>> # Initializing a ViTBert model (with random weights) from a ViT & google-bert/bert-base-uncased style configurations
>>> model = VisionEncoderDecoderModel(config=config)
>>> # Accessing the model configuration
>>> config_encoder = model.config.encoder
>>> config_decoder = model.config.decoder
>>> # set decoder config to causal lm
>>> config_decoder.is_decoder = True
>>> config_decoder.add_cross_attention = True
>>> # Saving the model, including its configuration
>>> model.save_pretrained("my-model")
>>> # loading model and config from pretrained folder
>>> encoder_decoder_config = VisionEncoderDecoderConfig.from_pretrained("my-model")
>>> model = VisionEncoderDecoderModel.from_pretrained("my-model", config=encoder_decoder_config)from_encoder_decoder_configs
< source >( encoder_config: PreTrainedConfigdecoder_config: PreTrainedConfig**kwargs ) → VisionEncoderDecoderConfig
配置对象的实例
从预训练的编码器模型配置和解码器模型配置实例化一个 VisionEncoderDecoderConfig(或其派生类)。
VisionEncoderDecoderModel
class transformers.VisionEncoderDecoderModel
< source >( config: transformers.configuration_utils.PreTrainedConfig | None = Noneencoder: transformers.modeling_utils.PreTrainedModel | None = Nonedecoder: transformers.modeling_utils.PreTrainedModel | None = None )
参数
- config (PreTrainedConfig, 可选) — 包含模型所有参数的模型配置类。使用配置文件进行初始化时,不会加载与模型关联的权重,仅加载配置。请查看 from_pretrained() 方法以加载模型权重。
- encoder (
PreTrainedModel,可选) — 要使用的编码器模型。 - decoder (
PreTrainedModel,可选) — 要使用的解码器模型。
输出原始隐藏状态、顶部未附加任何特定头部的裸视觉编码器-解码器模型。
该模型继承自 PreTrainedModel。请查阅父类文档,了解该库为所有模型实现的通用方法(例如下载或保存、调整输入嵌入大小、剪枝头等)。
该模型也是 PyTorch torch.nn.Module 的子类。 请将其作为常规的 PyTorch Module 使用,有关通用用法和行为的所有事项,请参阅 PyTorch 文档。
forward
< source >( pixel_values: typing.Optional[torch.Tensor] = Nonedecoder_input_ids: typing.Optional[torch.LongTensor] = Nonedecoder_attention_mask: typing.Optional[torch.BoolTensor] = Noneencoder_outputs: tuple[torch.Tensor] | None = Nonepast_key_values: transformers.cache_utils.Cache | None = Nonedecoder_inputs_embeds: typing.Optional[torch.Tensor] = Nonelabels: typing.Optional[torch.LongTensor] = Noneuse_cache: bool | None = Noneoutput_attentions: bool | None = Noneoutput_hidden_states: bool | None = Nonereturn_dict: bool | None = None**kwargs ) → Seq2SeqLMOutput or tuple(torch.Tensor)
参数
- pixel_values(形状为
(batch_size, num_channels, image_size, image_size)的torch.Tensor,可选) — 与输入图像对应的张量。可以使用image_processor_class获取像素值。有关详细信息,请参阅image_processor_class.__call__(processor_class使用image_processor_class来处理图像)。 - decoder_input_ids (
torch.LongTensor形状为(batch_size, target_sequence_length), 可选) — 解码器输入序列中各 token 在词汇表中的索引。可通过 PreTrainedTokenizer 获取索引。详情请参阅 PreTrainedTokenizer.encode() 和 PreTrainedTokenizer.call()。什么是输入 ID?如果使用 past_key_values,则只需输入最后一个 decoder_input_ids(参见 past_key_values)。在训练时,模型会自动通过将 labels 向右移位、用 pad_token_id 替换 -100,并在前面添加 decoder_start_token_id 来创建 decoder_input_ids。可以使用 PreTrainedTokenizer 获取索引。有关详细信息,请参阅 PreTrainedTokenizer.encode() 和 PreTrainedTokenizer.call()。
如果使用了
past_key_values,则可以选择性地仅输入最后几个decoder_input_ids(参见past_key_values)。在训练过程中,模型会自动将
labels向右移位,用pad_token_id替换 -100,并在前面添加decoder_start_token_id,从而生成decoder_input_ids。 - decoder_attention_mask(形状为
(batch_size, target_sequence_length)的torch.BoolTensor,可选) — 默认行为:生成一个忽略decoder_input_ids中填充标记的张量。默认情况下也会使用因果掩码。 - encoder_outputs (
tuple[torch.Tensor],可选) — 元组由 (last_hidden_state,可选:hidden_states,可选:attentions)last_hidden_state的形状为(batch_size, sequence_length, hidden_size),可选),是编码器最后一层输出的隐藏状态序列。用于解码器的交叉注意力。 - past_key_values (
~cache_utils.Cache, 可选) — 预计算的隐藏状态(自注意力块和交叉注意力块中的键和值),可用于加速顺序解码。这通常由past_key_values在解码的先前阶段返回,当use_cache=True或config.use_cache=True.仅允许将 Cache 实例作为输入,请参阅我们的 kv cache 指南。 如果未传入
past_key_values,则默认会初始化 DynamicCache。模型将输出与输入相同的缓存格式。
如果使用了
past_key_values,用户应仅输入未处理的input_ids(即未向该模型提供其过去键值状态的那些),其形状为(batch_size, unprocessed_length),而不是形状为(batch_size, sequence_length)的全部input_ids。 - decoder_inputs_embeds (
torch.Tensor,形状为(batch_size, target_sequence_length, hidden_size),可选) — 可选地,您可以选择直接传入嵌入表示,而不是传入decoder_input_ids。如果您希望对decoder_input_ids索引如何转换为相应向量拥有比模型内部嵌入查找矩阵更多的控制权,这将非常有用。 - labels(形状为
(batch_size, sequence_length)的torch.LongTensor,可选)— 用于计算解码器掩码语言建模损失的标签。索引应在[-100, 0, ..., config.vocab_size]范围内(参见input_ids的文档字符串)。索引设置为-100的令牌将被忽略(即被掩码),损失仅针对标签位于[0, ..., config.vocab_size]范围内的令牌进行计算。 - use_cache (
bool,可选) — 如果设置为True,则会返回past_key_values键值状态,可用于加速解码(参见past_key_values)。 - output_attentions (
bool, 可选) — 是否返回所有注意力层的注意力张量。有关详细信息,请参阅返回张量中的attentions。 - output_hidden_states (
bool,可选) — 是否返回所有层的隐藏状态。有关更多详细信息,请参阅返回张量中的hidden_states。 - return_dict (
bool, 可选) — 是否返回 ModelOutput 而不是普通元组。
返回值
Seq2SeqLMOutput 或 tuple(torch.Tensor)
一个 Seq2SeqLMOutput 或 torch.Tensor 元组(如果传入了 return_dict=False 或 config.return_dict=False),其包含的元素取决于配置(VisionEncoderDecoderConfig)和输入。
VisionEncoderDecoderModel 的 forward 方法重写了 __call__ 特殊方法。
尽管前向传播的实现需要在此函数中定义,但之后应调用
Module实例,而不是直接调用此函数,因为前者会负责执行预处理和后处理步骤,而后者则会静默地忽略这些步骤。
loss(形状为
(1,)的torch.Tensor,可选,在提供labels时返回)— 语言建模损失。logits(形状为
(batch_size, sequence_length, config.vocab_size)的torch.Tensor)— 语言建模头的预测分数(SoftMax 之前每个词汇表 token 的分数)。past_key_values(
EncoderDecoderCache,可选,在传入use_cache=True或config.use_cache=True时返回)—— 它是一个 EncoderDecoderCache 实例。更多详情,请参阅我们的 kv cache 指南。包含预计算的隐藏状态(自注意力块和交叉注意力块中的键和值),可用于(参见
past_key_values输入)加速顺序解码。decoder_hidden_states (
tuple(torch.Tensor),可选,在传入output_hidden_states=True或config.output_hidden_states=True时返回) — 一个torch.Tensor元组(如果模型具有嵌入层,则包含嵌入层输出的一个张量,以及每个层输出的一个张量),形状为(batch_size, sequence_length, hidden_size)。解码器在每一层输出处的隐藏状态,以及初始嵌入输出。
decoder_attentions (
tuple(torch.Tensor),可选,在传入output_attentions=True或config.output_attentions=True时返回) — 一个torch.Tensor元组(每层一个),形状为(batch_size, num_heads, sequence_length, sequence_length)。解码器在注意力 softmax 之后的注意力权重,用于在自注意力头中计算加权平均值。
cross_attentions (
tuple(torch.Tensor),可选,在传入output_attentions=True或config.output_attentions=True时返回) — 一个torch.Tensor元组(每层一个),形状为(batch_size, num_heads, sequence_length, sequence_length)。解码器交叉注意力层在注意力 softmax 之后的注意力权重,用于在交叉注意力头中计算加权平均值。
encoder_last_hidden_state(形状为
(batch_size, sequence_length, hidden_size)的torch.Tensor,可选)— 模型编码器最后一层输出的隐藏状态序列。encoder_hidden_states (
tuple(torch.Tensor),可选,在传入output_hidden_states=True或config.output_hidden_states=True时返回) — 一个torch.Tensor元组(如果模型具有嵌入层,则包含嵌入层输出的一个张量,以及每个层输出的一个张量),形状为(batch_size, sequence_length, hidden_size)。编码器在每一层输出处的隐藏状态,以及初始嵌入输出。
encoder_attentions(
tuple(torch.Tensor),可选,在传入output_attentions=True或config.output_attentions=True时返回)—— 一个torch.Tensor元组(每层一个),形状为(batch_size, num_heads, sequence_length, sequence_length)。编码器在注意力 softmax 之后的注意力权重,用于在自注意力头中计算加权平均值。
示例:
>>> from transformers import AutoProcessor, VisionEncoderDecoderModel
>>> from huggingface_hub.utils import httpx
>>> from io import BytesIO
>>> from PIL import Image
>>> import torch
>>> processor = AutoProcessor.from_pretrained("microsoft/trocr-base-handwritten")
>>> model = VisionEncoderDecoderModel.from_pretrained("microsoft/trocr-base-handwritten")
>>> # load image from the IAM dataset
>>> url = "https://fki.tic.heia-fr.ch/static/img/a01-122-02.jpg"
>>> with httpx.stream("GET", url) as response:
... image = Image.open(BytesIO(response.read())).convert("RGB")
>>> # training
>>> model.config.decoder_start_token_id = processor.tokenizer.eos_token_id
>>> model.config.pad_token_id = processor.tokenizer.pad_token_id
>>> model.config.vocab_size = model.config.decoder.vocab_size
>>> pixel_values = processor(image, return_tensors="pt").pixel_values
>>> text = "hello world"
>>> labels = processor.tokenizer(text, return_tensors="pt").input_ids
>>> outputs = model(pixel_values=pixel_values, labels=labels)
>>> loss = outputs.loss
>>> # inference (generation)
>>> generated_ids = model.generate(pixel_values)
>>> generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]from_encoder_decoder_pretrained
< source >( encoder_pretrained_model_name_or_path: str | None = Nonedecoder_pretrained_model_name_or_path: str | None = None*model_args**kwargs )
参数
- encoder_pretrained_model_name_or_path (
str, 可选) — 用于初始化图像编码器的必要信息。可以是:- 一个字符串,即托管在 huggingface.co 模型仓库中的预训练模型的 model id。例如
google/vit-base-patch16-224-in21k。 - 指向一个目录的路径,该目录包含使用 save_pretrained() 保存的模型权重,例如
./my_model_directory/。
- 一个字符串,即托管在 huggingface.co 模型仓库中的预训练模型的 model id。例如
- decoder_pretrained_model_name_or_path (
str, 可选, 默认为None) — 初始化文本解码器所需的信息。可以是:- 一个字符串,表示托管在 huggingface.co 模型仓库中的预训练模型的 model id。
- 指向一个目录的路径,该目录包含使用 save_pretrained() 保存的模型权重,例如
./my_model_directory/。
- model_args(其余位置参数,可选)—
所有其余位置参数都会传递给底层模型的
__init__方法。 - kwargs (其余关键字参数字典, 可选) —
可用于更新配置对象(在加载之后)并初始化模型(例如,
output_attentions=True).- 要更新编码器配置,请为每个配置参数使用前缀 encoder_。
- 要更新解码器配置,请为每个配置参数使用前缀 decoder_。
- 要更新父模型配置,请勿为每个配置参数使用前缀。
行为取决于是否提供了
config或自动加载。
从库中的一个或两个基础类实例化编码器和解码器,并使用预训练模型检查点。
模型默认使用 model.eval() 设置为评估模式(Dropout 模块被禁用)。若要训练模型,需先使用 model.train() 将其切换回训练模式。
示例:
>>> from transformers import VisionEncoderDecoderModel
>>> # initialize a vit-bert from a pretrained ViT and a pretrained BERT model. Note that the cross-attention layers will be randomly initialized
>>> model = VisionEncoderDecoderModel.from_encoder_decoder_pretrained(
... "google/vit-base-patch16-224-in21k", "google-bert/bert-base-uncased"
... )
>>> # saving model after fine-tuning
>>> model.save_pretrained("./vit-bert")
>>> # load fine-tuned model
>>> model = VisionEncoderDecoderModel.from_pretrained("./vit-bert")