YOLOS:大道至简,直接使用预训练ViT进行实时目标检测 | NeurIPS 2021

论文探索了在中型ImageNet-1k数据集上预训练的普通ViT到更具挑战性的COCO目标检测基准的可迁移性,提出了基于Vision TransformerYou Only Look at One Sequence(YOLOS)目标检测模型。在具有挑战性的COCO目标检测基准上的实验结果表明,2D目标检测可以以纯sequence-to-sequence的方式完成,并且附加的归纳偏置最小

来源:晓飞的算法工程笔记 公众号

论文: You Only Look at One Sequence: Rethinking Transformer in Vision through Object Detection

Introduction


Vision Transformer(ViT) 证明,直接继承自NLPTransformer编码器架构可以在大规模图像识别方面表现出色。以图像块嵌入序列作为输入,仅需少量的Fine-tune数据,ViT即可成功地从纯粹的sequence-to-sequence角度将足量数据预训练的视觉表达迁移到更具体的图像分类任务。

  一个自然的问题是:ViT能否直接迁移到更具挑战性的对象和区域级目标任务中,例如图像级识别之外的目标检测?

ViT-FRCNN是第一个使用预先训练的ViT作为Faster R-CNN目标检测器的主干网络,但这种设计无法摆脱对卷积神经网络(CNN)的依赖和2D归纳偏差。因为ViT-FRCNN需要将ViT的输出序列重新排列为2D空间特征图,依赖于区域池化操作(即RoIPoolRoIAlign)以及基于区域的CNN架构来解码ViT特征,用于对象和区域级别的感知。

  受现代CNN设计的启发,最近的一些工作将特征金字塔等设计引入到Vision Transformer中,这很大程度上提高了包括目标检测在内的密集预测任务的性能。但这些架构是以性能为导向的,不能反映Vision Transformer的特性。另外的一些如DEtection TRansformer(DETR) 的系列工作,使用随机初始化的Transformer来编码和解码CNN特征用于目标检测,也未揭示预训练Transformer的可迁移性。

  直观上,ViT旨在学习远距离依赖关系和全局上下文信息,而不是本地和区域级别的关系。此外,ViT缺乏现代CNN那样的分层架构来处理视觉实体尺寸的巨大变化。根据现有的研究,目前尚不清楚纯ViT是否可以将预训练的通用视觉表达从图像级识别转移到更复杂的2D目标检测任务。

  为了回答这个问题,论文提出了基于ViT架构的目标检测模型You Only Look at One Sequence(YOLOS),具有尽可能少的架构修改、区域先验以及目标任务相关归纳偏差。本质上,从预训练ViTYOLOS检测器的变化非常简单:

  • ViT中用于图像分类的 [ C L S ] [\mathrm{CLS}] [CLS] 标记替换为一百个用于目标检测的 [ D E T ] [\mathrm{DET}] [DET] 标记。
  • 按照DETR用二分匹配损失替换ViT的图像分类损失,以集合预测的方式进行目标检测。这可以避免像ViT-FRCNN那样将ViT的输出序列重新解释为2D特征图,以及防止在标签分配中引入启发式算法和2D空间结构的先验知识。而且,YOLOS的预测头可以摆脱复杂多样的设计,就像分类层一样紧凑。

YOLOS继承自ViT并不是为了成为另一个高性能目标检测器,而是为了揭示预训练的Transformer从图像识别到更具挑战性的目标检测任务的多功能性和可迁移性。具体来说,论文的主要贡献总结如下:

  • 使用中型ImageNet-1k作为唯一的预训练数据集,表明普通ViT可以成功迁移至复杂的目标检测任务,并以尽可能少的修改在COCO基准上达成有竞争力的结果。
  • 首次证明通过将一系列固定大小的非重叠图像块作为输入,也可以以纯sequence-to-sequence的方式完成2D目标检测。在现有的目标检测器中,YOLOS利用最小的2D归纳偏置。
  • 对于原始ViT,目标检测结果对预训练方法非常敏感并且检测性能远未饱和。因此,YOLOS也可以用作具有挑战性的基准任务来评估ViT的不同(标签监督和自监督)预训练策略。

You Only Look at One Sequence


YOLOS遵循原始ViT架构,并与DETR一样针对目标检测进行优化。YOLOS可以轻松适应NLP和计算机视觉中可用的各种Transformer架构,这种简单的设置并不是为了更好的检测性能而设计的,而是为了尽可能公正地准确揭示Transformer系列在目标检测中的特性。

  • Architecture

  模型架构如图 1 所示,从ViT分类器到YOLOS检测器的变化很简单:

  • 删除用于图像分类的 [ C L S ] [\mathrm{CLS}] [CLS] 标记,附加了一百个随机初始化的可学习检测标记 [ D E T ] [\mathrm{DET}] [DET] 到输入嵌入 [ P A T C H ] [\mathrm{PATCH}] [PATCH] 以进行目标检测。

  • 在训练过程中,将图像分类损失替换为二分匹配损失,以遵循DETR的设定预测方式进行目标检测。

  • Stem

  常规ViT接收1D序列嵌入作为输入,为了处理2D图像输入,将图像 x ∈ R H × W × C \mathbf{x}\in\mathbb{R}^{H\times W\times C} xR

### 使用预训练ViT模型提取图像特征的方法 在深度学习中,使用预训练模型进行特征提取是一种常见的迁移学习方法。对于视觉Transformer(ViT)模型,可以通过加载预训练权重并冻结模型的大部分层来提取图像特征[^4]。以下是基于PyTorch和TensorFlow实现的代码示例。 #### PyTorch 实现 以下代码展示了如何使用Hugging Face Transformers库中的预训练ViT模型提取图像特征: ```python from transformers import ViTFeatureExtractor, ViTModel import torch from PIL import Image import requests # 加载预训练ViT模型和特征提取器 feature_extractor = ViTFeatureExtractor.from_pretrained('google/vit-base-patch16-224') model = ViTModel.from_pretrained('google/vit-base-patch16-224') # 下载并加载测试图像 url = "http://images.cocodataset.org/val2017/000000039769.jpg" image = Image.open(requests.get(url, stream=True).raw) # 预处理图像 inputs = feature_extractor(images=image, return_tensors="pt") # 提取特征 with torch.no_grad(): outputs = model(**inputs) last_hidden_states = outputs.last_hidden_state # 获取最后一层的隐藏状态 pooled_output = outputs.pooler_output # 获取池化后的输出 print("Last Hidden States Shape:", last_hidden_states.shape) # (batch_size, sequence_length, hidden_size) print("Pooled Output Shape:", pooled_output.shape) # (batch_size, hidden_size) ``` 在上述代码中,`last_hidden_states`表示每个图像块的特征向量,而`pooled_output`是整个图像的全局特征向量[^4]。 #### TensorFlow 实现 以下是使用TensorFlow和Keras API加载预训练ViT模型并提取图像特征的代码示例: ```python import tensorflow as tf from tensorflow.keras.applications.vit import ViTBase16, preprocess_input from tensorflow.keras.preprocessing import image import numpy as np import requests from PIL import Image # 加载预训练ViT模型 model = ViTBase16(weights='imagenet', include_top=False) # 不包含顶层分类头 # 下载并加载测试图像 url = "http://images.cocodataset.org/val2017/000000039769.jpg" response = requests.get(url) img = Image.open(BytesIO(response.content)) img = img.resize((224, 224)) # 调整图像大小以匹配输入要求 # 预处理图像 x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) # 提取特征 features = model.predict(x) print("Features Shape:", features.shape) # 输出特征形状 ``` 在TensorFlow实现中,`include_top=False`参数确保模型不包含顶层分类头,从而允许我们直接获取中间层的特征向量。 ### 注意事项 - 在实际应用中,可能需要根据任务需求调整图像预处理步骤,例如调整图像大小或归一化方式。 - 如果需要对特征进行进一步处理(如降维或聚类),可以结合其他机器学习工具完成。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值