《AN IMAGE IS WORTH 16X16 WORDS: TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE》该论文提出使用一个直接应用于图像块的纯 Transformer 来进行图像分类任务。Vision Transformer (ViT) 在大量数据上进行预训练后,在多个基准测试中均优于最先进的卷积网络,同时训练所需的计算资源更少。
代码地址:
在本文中,将使用CNN和Vision Transformer方法,在猫狗数据集上训练一个视觉分类器。
Transformer 因其计算效率和可扩展性而成为 NLP 领域的首选模型。在计算机视觉领域,卷积神经网络 (CNN) 架构仍然占据主导地位,但一些研究人员尝试将 CNN 与自注意力机制相结合。作者尝试将标准 Transformer 直接应用于图像,发现在中等规模的数据集上训练时,这些模型的准确率与 ResNet 类架构相比略逊一筹。然而,在更大规模的数据集上训练时,Vision Transformer (ViT) 取得了优异的成绩,并在多个图像识别基准测试中接近或超越了当前最佳水平。

图 1描述了一个模型,该模型通过将二维图像转换为扁平化的二维块序列来处理二维图像。然后,这些块通过可训练的线性投影映射到一个恒定大小的潜在向量。一个可学习的嵌入被添加到块序列的前面,其在 Transformer 编码器输出的状态作为图像表示。然后,该图像表示通过分类头进行预训练或微调。添加位置嵌入以保留位置信息,嵌入向量序列作为 Transformer 编码器的输入,该编码器由交替的多头自注意力层和多层感知器 (MLP) 块组成。
过去,CNN 长期以来一直是图像处理任务的首选。它们擅长通过卷积层捕捉局部空间模式,从而实现分层特征提取。CNN 擅长从大量图像数据中学习,并在图像分类、目标检测和分割等任务中取得了显著成功。
虽然 CNN 在各种计算机视觉任务中都有着良好的记录,并且能够有效地处理大规模数据集,但 Vision Transformers 在全局依赖性和上下文理解至关重要的场景中具有优势。然而,Vision Transformer 通常需要更大量的训练数据才能达到与 CNN 相当的性能。此外,由于 CNN 具有可并行的特性,因此计算效率更高,更适用于实时且资源受限的应用。
示例:CNN与Vision Transformer
首先,将下载的数据集进行压缩,使用以下命令克隆 vision-transformer GitHub 仓库。该仓库在 vision_tr 目录下包含 Vision Transformers 所需的所有代码。
bash
!git clone https://github.com/RustamyF/vision-transformer.git
!mv vision-transformer/vision_tr .
下载的数据需要清理并准备用于训练我们的图像分类器。以下实用函数用于清理并以 Pytorch 的 DataLoader 格式加载数据。
python
import torch.nn as nn
import torch
import torch.optim as optim
from torchvision import datasets, models, transforms
from torch.utils.data import DataLoader, Dataset
from PIL import Image
from sklearn.model_selection import train_test_split
import os
class LoadData:
def __init__(self):
self.cat_path = 'A/Cat'
self.dog_path = 'A/Dog'
def delete_non_jpeg_files(self, directory):
for filename in os.listdir(directory):
if not filename.endswith('.jpg') and not filename.endswith('.jpeg'):
file_path = os.path.join(directory, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
print('deleted', file_path)
except Exception as e:
print('Failed to delete %s. Reason: %s' % (file_path, e))
def data(self):
self.delete_non_jpeg_files(self.dog_path)
self.delete_non_jpeg_files(self.cat_path)
dog_list = os.listdir(self.dog_path)
dog_list = [(os.path.join(self.dog_path, i), 1) for i in dog_list]
cat_list = os.listdir(self.cat_path)
cat_list = [(os.path.join(self.cat_path, i), 0) for i in cat_list]
total_list = cat_list + dog_list
train_list, test_list = train_test_split(total_list, test_size=0.2)
train_list, val_list = train_test_split(train_list, test_size=0.2)
print('train list', len(train_list))
print('test list', len(test_list))
print('val list', len(val_list))
return train_list, test_list, val_list
# data Augumentation
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
])
class dataset(torch.utils.data.Dataset):
def __init__(self, file_list, transform=None):
self.file_list = file_list
self.transform = transform
# dataset length
def __len__(self):
self.filelength = len(self.file_list)
return self.filelength
# load an one of images
def __getitem__(self, idx):
img_path, label = self.file_list[idx]
img = Image.open(img_path).convert('RGB')
img_transformed = self.transform(img)
return img_transformed, label
CNN方法
该图像分类器的 CNN 模型由三层二维卷积组成,卷积核大小为 3,步长为 2,最大池化层也为 2。卷积层之后是两个全连接层,每个层由 10 个节点组成。以下代码片段演示了此结构:
scss
class Cnn(nn.Module):
def __init__(self):
super(Cnn, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(3, 16, kernel_size=3, padding=0, stride=2),
nn.BatchNorm2d(16),
nn.ReLU(),
nn.MaxPool2d(2)
)
self.layer2 = nn.Sequential(
nn.Conv2d(16, 32, kernel_size=3, padding=0, stride=2),
nn.BatchNorm2d(32),
nn.ReLU(),
nn.MaxPool2d(2)
)
self.layer3 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=3, padding=0, stride=2),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(2)
)
self.fc1 = nn.Linear(3 * 3 * 64, 10)
self.dropout = nn.Dropout(0.5)
self.fc2 = nn.Linear(10, 2)
self.relu = nn.ReLU()
def forward(self, x):
out = self.layer1(x)
out = self.layer2(out)
out = self.layer3(out)
out = out.view(out.size(0), -1)
out = self.relu(self.fc1(out))
out = self.fc2(out)
return out
训练使用 Tesla T4 (g4dn-xlarge) GPU 机器进行,共进行了 10 个训练周期。Jupyter Notebook可在项目的GitHub 代码库中找到,其中包含训练循环的代码。以下是每个周期的训练循环结果。

视觉转型方法
Vision Transformer 架构采用可定制尺寸设计,可根据具体需求进行调整。对于这种规模的图像数据集来说,该架构仍然很大。
ini
from vision_tr.simple_vit import ViT
model = ViT(
image_size=224,
patch_size=32,
num_classes=2,
dim=128,
depth=12,
heads=8,
mlp_dim=1024,
dropout=0.1,
emb_dropout=0.1,
).to(device)
视觉转换器中的每个参数都起着关键作用,如下所述:
- image_size=224: 此参数指定模型输入图像的期望尺寸(宽度和高度)。在本例中,图像的预期尺寸为 224x224 像素。
- patch_size=32: 图像被分割成更小的块,此参数定义每个块的大小(宽度和高度)。在本例中,每个块为 32x32 像素。
- num_classes=2: 此参数表示分类任务中的类别数。在本例中,模型旨在将输入分为两类(猫和狗)。
- dim=128: 它指定模型中嵌入向量的维数。嵌入捕获每个图像块的表示。
- depth=12: 此参数定义 Vision Transformer 模型(编码器模型)的深度或层数。深度越高,提取特征就越复杂。
- heads=8: 该参数表示模型自注意力机制中注意力头的数量。
- mlp_dim=1024: 它指定模型中多层感知器 (MLP) 隐藏层的维数。MLP 负责在自注意力机制之后转换 token 表征。
- dropout=0.1: 此参数控制 dropout 率,这是一种用于防止过拟合的正则化技术。它在训练期间随机将一部分输入单元设置为 0。
- emb_dropout=0.1: 它定义了专门应用于 token 嵌入的 dropout 率。dropout 有助于防止在训练期间过度依赖特定的 token。
使用Tesla T4 (g4dn-xlarge) GPU 机器对用于分类任务的 Vision Transformer 进行 20 个训练周期的训练。由于训练损失函数的收敛速度较慢,因此训练周期为 20 个周期(而非 CNN 的 10 个周期)。以下是每个周期的训练循环结果。

CNN 方法在 10 个时期内达到了 75% 的准确率,而视觉转换模型达到了 69% 的准确率,并且训练时间明显更长。
Coovally AI模型训练与应用平台
当然在Coovally平台上你可以直接进行模型训练和部署,无需配置环境、修改配置文件等繁琐操作,一键上传数据集,使用模型进行训练与结果预测,全程高速零代码!

而且可以多次设置实验参数,无论是学术研究中的小规模探索,还是产业项目中的快速落地,Coovally都能大幅提升开发效率,加速成果转化。

Coovally平台整合了国内外开源社区1000+模型算法 和各类公开识别数据集,无论是YOLO系列模型还是Transformer系列视觉模型算法,平台全部包含,均可一键调用或下载!
结论
总而言之,比较 CNN 和 Vision Transformer 模型时,在模型大小、内存需求、准确率和性能方面存在显著差异。CNN 模型传统上以其紧凑的尺寸和高效的内存利用率而闻名,这使得它们适用于资源受限的环境。它们已被证明在图像处理任务中非常有效,并在各种计算机视觉应用中展现出卓越的准确率。另一方面,Vision Transformer 提供了一种强大的方法来捕捉图像中的全局依赖关系和上下文理解,从而提升了某些任务的性能。然而,与 CNN 相比,Vision Transformer 的模型大小和内存需求往往更大。虽然它们可能达到令人印象深刻的准确率,尤其是在处理更大的数据集时,但计算需求可能会限制它们在资源有限的情况下的实用性。最终,在 CNN 和 Vision Transformer 模型之间进行选择取决于当前任务的具体要求,并考虑可用资源、数据集大小以及模型复杂度、准确率和性能之间的权衡等因素。随着计算机视觉领域的不断发展,这两种架构都有望取得进一步的进步,使研究人员和从业人员能够根据他们的特定需求和限制做出更明智的选择。