金字塔视觉转换器 V2 (PVTv2)
概述
PVTv2 模型在 Wenhai Wang、Enze Xie、Xiang Li、Deng-Ping Fan、Kaitao Song、Ding Liang、Tong Lu、Ping Luo 和 Ling Shao 的论文 PVT v2: Improved Baselines with Pyramid Vision Transformer 中提出。作为 PVT 的改进版本,它摒弃了位置嵌入,而是依靠通过零填充和重叠补丁嵌入编码的位置信息。这种对位置嵌入的不依赖性简化了架构,并能够在任何分辨率下运行推理而无需对其进行插值。
PVTv2编码器结构已成功部署,并在语义分割的Segformer、单目深度的GLPN和全景分割的Panoptic Segformer中取得了最先进的成绩。
PVTv2属于一类称为分层Transformer的模型家族,该家族对Transformer层进行了调整以生成多尺度特征图。与视觉Transformer(ViT)的列状结构(会丢失细粒度细节)不同,多尺度特征图可以保留这些细节并有助于密集预测任务的性能。在PVTv2中,这是通过在每个编码器层中使用具有重叠核的二维卷积生成图像块标记来实现的。
分层Transformer的多尺度特征使其能够轻松替换传统的主力计算机视觉骨干模型(如ResNet)在更大架构中的作用。Segformer和Panoptic Segformer都证明,使用PVTv2作为骨干的配置始终优于具有相似大小的ResNet骨干的配置。
PVTv2的另一个强大功能是自注意力层中复杂度的降低,称为空间缩减注意力(SRA),它使用二维卷积层将隐藏状态投影到更小的分辨率,然后使用查询对其进行注意力计算,将自注意力的$O(n^2)$复杂度提高到$O(n^2/R)$,其中$R$是空间缩减比率(sr_ratio
,即二维卷积中的核大小和步长)。
SRA在PVT中引入,是PVTv2中使用的默认注意力复杂度降低方法。但是,PVTv2还引入了使用与图像大小相关的线性复杂度的自注意力机制的选项,他们称之为“线性SRA”。此方法使用平均池化将隐藏状态缩减到固定大小,该大小与其原始分辨率无关(尽管这本质上比常规SRA更具损耗性)。可以通过在PVTv2Config中将linear_attention
设置为True
来启用此选项。
论文摘要:
Transformer最近在计算机视觉领域取得了令人鼓舞的进展。在这项工作中,我们通过添加三种设计来改进原始的Pyramid Vision Transformer(PVT v1),从而提出了新的基线,包括(1)线性复杂度注意力层,(2)重叠补丁嵌入,以及(3)卷积前馈网络。通过这些修改,PVT v2将PVT v1的计算复杂度降低到线性,并在分类、检测和分割等基本视觉任务上取得了显著的改进。值得注意的是,所提出的PVT v2实现了与最近的一些工作(如Swin Transformer)相当或更好的性能。我们希望这项工作能够促进计算机视觉领域最先进的Transformer研究。代码可在https://github.com/whai362/PVT获取。
此模型由FoamoftheSea贡献。原始代码可以在这里找到here。
使用技巧
PVTv2是一个分层Transformer模型,在图像分类和许多其他任务中都表现出了强大的性能,用作Segformer中的语义分割骨干、GLPN中的单目深度估计骨干以及Panoptic Segformer中的全景分割骨干,始终表现出比类似的ResNet配置更高的性能。
与纯Transformer架构相比,像PVTv2这样的分层Transformer通过将卷积神经网络(CNN)的设计元素融入到其编码器中,在图像数据上实现了优越的数据和参数效率。这创建了一个兼具两者的架构,将CNN的有用归纳偏差(如平移等变性和局部性)注入到网络中,同时仍然享受到Transformer的自注意力机制提供的动态数据响应和全局关系建模的好处(transformers)。
PVTv2使用重叠补丁嵌入来创建多尺度特征图,并使用零填充和深度卷积注入位置信息。
为了降低注意力层的复杂度,PVTv2使用步长为2的二维卷积(SRA)或固定大小的平均池化(线性SRA)对隐藏状态进行空间缩减。虽然本质上更具损耗性,但线性SRA以相对于图像大小的线性复杂度提供了令人印象深刻的性能。要在自注意力层中使用线性SRA,请在
PvtV2Config
中设置linear_attention=True
。PvtV2Model是分层Transformer编码器(在文献中也常称为混合Transformer或MiT)。PvtV2ForImageClassification在顶部添加了一个简单的分类器头来执行图像分类。
PvtV2Backbone
可以与更大的架构(如Deformable DETR)中的AutoBackbone系统一起使用。所有模型大小的ImageNet预训练权重都可以在hub上找到。
使用PVTv2的最佳方法是使用
AutoModelForImageClassification
加载您选择的尺寸的预训练检查点。
import requests
import torch
from transformers import AutoModelForImageClassification, AutoImageProcessor
from PIL import Image
model = AutoModelForImageClassification.from_pretrained("OpenGVLab/pvt_v2_b0")
image_processor = AutoImageProcessor.from_pretrained("OpenGVLab/pvt_v2_b0")
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)
processed = image_processor(image)
outputs = model(torch.tensor(processed["pixel_values"]))
要将PVTv2用作更复杂架构(如DeformableDETR)的骨干,可以使用AutoBackbone(此模型需要微调,因为您正在替换预训练模型中的骨干)。
import requests
import torch
from transformers import AutoConfig, AutoModelForObjectDetection, AutoImageProcessor
from PIL import Image
model = AutoModelForObjectDetection.from_config(
config=AutoConfig.from_pretrained(
"SenseTime/deformable-detr",
backbone_config=AutoConfig.from_pretrained("OpenGVLab/pvt_v2_b5"),
use_timm_backbone=False
),
)
image_processor = AutoImageProcessor.from_pretrained("SenseTime/deformable-detr")
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw)
processed = image_processor(image)
outputs = model(torch.tensor(processed["pixel_values"]))
PVTv2在ImageNet-1K上的性能(按模型大小(B0-B5)划分)
方法 | 大小 | Acc@1 | 参数量(M) |
---|---|---|---|
PVT-V2-B0 | 224 | 70.5 | 3.7 |
PVT-V2-B1 | 224 | 78.7 | 14.0 |
PVT-V2-B2-Linear | 224 | 82.1 | 22.6 |
PVT-V2-B2 | 224 | 82.0 | 25.4 |
PVT-V2-B3 | 224 | 83.1 | 45.2 |
PVT-V2-B4 | 224 | 83.6 | 62.6 |
PVT-V2-B5 | 224 | 83.8 | 82.0 |
PvtV2Config
类 transformers.PvtV2Config
< 源代码 >( image_size: Union = 224 num_channels: int = 3 num_encoder_blocks: int = 4 depths: List = [2, 2, 2, 2] sr_ratios: List = [8, 4, 2, 1] hidden_sizes: List = [32, 64, 160, 256] patch_sizes: List = [7, 3, 3, 3] strides: List = [4, 2, 2, 2] num_attention_heads: List = [1, 2, 5, 8] mlp_ratios: List = [8, 8, 4, 4] hidden_act: Union = 'gelu' hidden_dropout_prob: float = 0.0 attention_probs_dropout_prob: float = 0.0 initializer_range: float = 0.02 drop_path_rate: float = 0.0 layer_norm_eps: float = 1e-06 qkv_bias: bool = True linear_attention: bool = False out_features = None out_indices = None **kwargs )
参数
- image_size (
Union[int, Tuple[int, int]]
, 可选, 默认为 224) — 输入图像大小。传递整数数值表示正方形图像,或传递 (高度,宽度) 元组。 - num_channels (
int
, 可选, 默认为 3) — 输入通道数。 - num_encoder_blocks (
[int]
, 可选, 默认为 4) — 编码器块的数量(即 Mix Transformer 编码器中的阶段数)。 - depths (
List[int]
, 可选, 默认为[2, 2, 2, 2]
) — 每个编码器块中的层数。 - sr_ratios (
List[int]
, 可选, 默认为[8, 4, 2, 1]
) — 每个编码器块的空间缩减比率。 - hidden_sizes (
List[int]
, 可选, 默认为[32, 64, 160, 256]
) — 每个编码器块的维度。 - patch_sizes (
List[int]
, 可选, 默认为[7, 3, 3, 3]
) — 每个编码器块之前重叠补丁嵌入的补丁大小。 - strides (
List[int]
, 可选, 默认为[4, 2, 2, 2]
) — 每个编码器块之前重叠补丁嵌入的步长。 - num_attention_heads (
List[int]
,可选,默认为[1, 2, 5, 8]
) — Transformer 编码器每个块中每个注意力层的注意力头数量。 - mlp_ratios (
List[int]
,可选,默认为[8, 8, 4, 4]
) — 编码器块中 Mix FFNs 的隐藏层大小与输入层大小的比率。 - hidden_act (
str
或Callable
,可选,默认为"gelu"
) — 编码器和池化器中的非线性激活函数(函数或字符串)。如果为字符串,则支持"gelu"
、"relu"
、"selu"
和"gelu_new"
。 - hidden_dropout_prob (
float
,可选,默认为 0.0) — 嵌入、编码器和池化器中所有全连接层的 dropout 概率。 - attention_probs_dropout_prob (
float
,可选,默认为 0.0) — 注意力概率的 dropout 比率。 - initializer_range (
float
,可选,默认为 0.02) — 初始化所有权重矩阵的截断正态初始化器的标准差。 - drop_path_rate (
float
,可选,默认为 0.0) — Transformer 编码器块中使用的随机深度的 dropout 概率。 - layer_norm_eps (
float
,可选,默认为 1e-06) — 层归一化层使用的 epsilon。 - qkv_bias (
bool
,可选,默认为True
) — 是否应向查询、键和值添加可学习的偏置。 - linear_attention (
bool
,可选,默认为False
) — 使用线性注意力复杂度。如果设置为 True,则忽略sr_ratio
,并且在注意力层中使用平均池化进行降维,而不是使用步长卷积。
这是一个配置类,用于存储 PvtV2Model 的配置。它用于根据指定的参数实例化 Pvt V2 模型,定义模型架构。使用默认值实例化配置将生成与 Pvt V2 B0 OpenGVLab/pvt_v2_b0 架构类似的配置。
配置对象继承自 PretrainedConfig,可用于控制模型输出。阅读 PretrainedConfig 中的文档以获取更多信息。
示例
>>> from transformers import PvtV2Model, PvtV2Config
>>> # Initializing a pvt_v2_b0 style configuration
>>> configuration = PvtV2Config()
>>> # Initializing a model from the OpenGVLab/pvt_v2_b0 style configuration
>>> model = PvtV2Model(configuration)
>>> # Accessing the model configuration
>>> configuration = model.config
PvtForImageClassification
类 transformers.PvtV2ForImageClassification
< 源代码 >( config: PvtV2Config )
参数
- config (~PvtV2Config) — 模型配置类,包含模型的所有参数。使用配置文件初始化不会加载与模型关联的权重,仅加载配置。查看 from_pretrained() 方法以加载模型权重。
顶部带有图像分类头的 Pvt-v2 模型转换器(在 [CLS] token 的最终隐藏状态之上添加一个线性层),例如用于 ImageNet。
此模型是 PyTorch torch.nn.Module 的子类。将其用作常规 PyTorch 模块,并参考 PyTorch 文档以了解有关一般用法和行为的所有事项。
前向传播
< 源代码 > ( pixel_values: Optional labels: Optional = None output_attentions: Optional = None output_hidden_states: Optional = None return_dict: Optional = None ) → transformers.modeling_outputs.ImageClassifierOutput 或 tuple(torch.FloatTensor)
参数
- pixel_values (
torch.FloatTensor
形状为(batch_size, num_channels, height, width)
) — 像素值。可以使用 AutoImageProcessor 获取像素值。有关详细信息,请参阅 PvtImageProcessor.call()。 - output_attentions (
bool
,可选) — 是否返回所有注意力层的注意力张量。有关更多详细信息,请参阅返回的张量中的attentions
。 - output_hidden_states (
bool
,可选) — 是否返回所有层的隐藏状态。有关更多详细信息,请参阅返回的张量中的hidden_states
。 - return_dict (
bool
,可选) — 是否返回 ModelOutput 而不是普通元组。 - labels (
torch.LongTensor
形状为(batch_size,)
,可选) — 用于计算图像分类/回归损失的标签。索引应在[0, ..., config.num_labels - 1]
范围内。如果config.num_labels == 1
,则计算回归损失(均方误差损失),如果config.num_labels > 1
,则计算分类损失(交叉熵损失)。
返回
transformers.modeling_outputs.ImageClassifierOutput 或 tuple(torch.FloatTensor)
一个 transformers.modeling_outputs.ImageClassifierOutput 或一个 torch.FloatTensor
元组(如果传递了 return_dict=False
或 config.return_dict=False
),包含根据配置 (PvtV2Config) 和输入的不同元素。
-
loss (
torch.FloatTensor
形状为(1,)
,可选,在提供labels
时返回) — 分类(或如果 config.num_labels==1 则为回归)损失。 -
logits (
torch.FloatTensor
形状为(batch_size, config.num_labels)
) — 分类(或如果 config.num_labels==1 则为回归)分数(在 SoftMax 之前)。 -
hidden_states (
tuple(torch.FloatTensor)
,可选,在传递output_hidden_states=True
或config.output_hidden_states=True
时返回) —torch.FloatTensor
元组(一个用于嵌入的输出,如果模型具有嵌入层,以及每个阶段输出的一个)形状为(batch_size, sequence_length, hidden_size)
。模型在每个阶段输出处的隐藏状态(也称为特征图)。 -
attentions (
tuple(torch.FloatTensor)
,可选,在传递output_attentions=True
或config.output_attentions=True
时返回) —torch.FloatTensor
元组(每个层一个)形状为(batch_size, num_heads, patch_size, sequence_length)
。注意力 softmax 之后的注意力权重,用于计算自注意力头中的加权平均值。
PvtV2ForImageClassification 的前向方法,覆盖了 __call__
特殊方法。
虽然前向传递的配方需要在此函数中定义,但之后应该调用 Module
实例而不是它,因为前者负责运行预处理和后处理步骤,而后者则会静默地忽略它们。
示例
>>> from transformers import AutoImageProcessor, PvtV2ForImageClassification
>>> import torch
>>> from datasets import load_dataset
>>> dataset = load_dataset("huggingface/cats-image", trust_remote_code=True)
>>> image = dataset["test"]["image"][0]
>>> image_processor = AutoImageProcessor.from_pretrained("OpenGVLab/pvt_v2_b0")
>>> model = PvtV2ForImageClassification.from_pretrained("OpenGVLab/pvt_v2_b0")
>>> inputs = image_processor(image, return_tensors="pt")
>>> with torch.no_grad():
... logits = model(**inputs).logits
>>> # model predicts one of the 1000 ImageNet classes
>>> predicted_label = logits.argmax(-1).item()
>>> print(model.config.id2label[predicted_label])
LABEL_281
PvtModel
类 transformers.PvtV2Model
< 源代码 >( config: PvtV2Config )
参数
- config (~PvtV2Config) — 模型配置类,包含模型的所有参数。使用配置文件初始化不会加载与模型关联的权重,仅加载配置。查看 from_pretrained() 方法以加载模型权重。
不带任何特定头的原始隐藏状态的裸露 Pvt-v2 编码器输出。此模型是 PyTorch torch.nn.Module 的子类。将其用作常规 PyTorch 模块,并参考 PyTorch 文档以了解与一般用法和行为相关的所有事项。
前向传播
< 源代码 > ( pixel_values: FloatTensor output_attentions: Optional = None output_hidden_states: Optional = None return_dict: Optional = None ) → transformers.modeling_outputs.BaseModelOutput 或 tuple(torch.FloatTensor)
参数
- pixel_values (
torch.FloatTensor
形状为(batch_size, num_channels, height, width)
) — 像素值。可以使用 AutoImageProcessor 获取像素值。有关详细信息,请参阅 PvtImageProcessor.call()。 - output_attentions (
bool
,可选) — 是否返回所有注意力层的注意力张量。有关更多详细信息,请参阅返回张量下的attentions
。 - output_hidden_states (
bool
,可选) — 是否返回所有层的隐藏状态。有关更多详细信息,请参阅返回张量下的hidden_states
。 - return_dict (
bool
, 可选) — 是否返回 ModelOutput 而不是普通元组。
返回
transformers.modeling_outputs.BaseModelOutput 或 tuple(torch.FloatTensor)
一个 transformers.modeling_outputs.BaseModelOutput 或一个 torch.FloatTensor
的元组(如果传递了 return_dict=False
或当 config.return_dict=False
时),包含根据配置 (PvtV2Config) 和输入的不同元素。
-
last_hidden_state (
torch.FloatTensor
形状为(batch_size, sequence_length, hidden_size)
) — 模型最后一层输出的隐藏状态序列。 -
hidden_states (
tuple(torch.FloatTensor)
, 可选, 当传递output_hidden_states=True
或当config.output_hidden_states=True
时返回) —torch.FloatTensor
的元组(一个用于嵌入的输出,如果模型具有嵌入层,加上每一层的输出)形状为(batch_size, sequence_length, hidden_size)
。模型在每一层输出处的隐藏状态加上可选的初始嵌入输出。
-
attentions (
tuple(torch.FloatTensor)
, 可选, 当传递output_attentions=True
或当config.output_attentions=True
时返回) —torch.FloatTensor
的元组(每一层一个)形状为(batch_size, num_heads, sequence_length, sequence_length)
。注意力 softmax 之后的注意力权重,用于计算自注意力头中的加权平均值。
The PvtV2Model 正向传播方法,覆盖了 __call__
特殊方法。
虽然前向传递的配方需要在此函数中定义,但之后应该调用 Module
实例而不是它,因为前者负责运行预处理和后处理步骤,而后者则会静默地忽略它们。
示例
>>> from transformers import AutoImageProcessor, PvtV2Model
>>> import torch
>>> from datasets import load_dataset
>>> dataset = load_dataset("huggingface/cats-image", trust_remote_code=True)
>>> image = dataset["test"]["image"][0]
>>> image_processor = AutoImageProcessor.from_pretrained("OpenGVLab/pvt_v2_b0")
>>> model = PvtV2Model.from_pretrained("OpenGVLab/pvt_v2_b0")
>>> inputs = image_processor(image, return_tensors="pt")
>>> with torch.no_grad():
... outputs = model(**inputs)
>>> last_hidden_states = outputs.last_hidden_state
>>> list(last_hidden_states.shape)
[1, 256, 7, 7]