FasterNet实战:使用FasterNet实现图像分类任务
Posted AI浩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FasterNet实战:使用FasterNet实现图像分类任务相关的知识,希望对你有一定的参考价值。
文章目录
摘要
论文翻译:https://wanghao.blog.csdn.net/article/details/129485972?spm=1001.2014.3001.5502
官方源码: https://github.com/JierunChen/FasterNet
FasterNet全新的神经网络家族,在多个处理平台上运行速度更快,精度更高,优于MobileVit等网络,基于新提出新的Partial卷积(PConv),大型网络FasterNet-L达到了83.5%的top-1精度,与Swin-B相当,同时在GPU上具有更高推断吞吐量,以及在CPU上节省42%的计算时间。网络架构如下:
这篇文章主要讲解如何使用FasterNet完成图像分类任务,接下来我们一起完成项目的实战。本例选用的模型是fasternet_s,在植物幼苗数据集上实现了96%的准确率。
通过这篇文章能让你学到:
- 如何使用数据增强,包括transforms的增强、CutOut、MixUp、CutMix等增强手段?
- 如何实现FasterNet模型实现训练?
- 如何使用pytorch自带混合精度?
- 如何使用梯度裁剪防止梯度爆炸?
- 如何使用DP多显卡训练?
- 如何绘制loss和acc曲线?
- 如何生成val的测评报告?
- 如何编写测试脚本测试测试集?
- 如何使用余弦退火策略调整学习率?
- 如何使用AverageMeter类统计ACC和loss等自定义变量?
- 如何理解和统计ACC1和ACC5?
- 如何使用EMA?
- 如果使用Grad-CAM 实现热力图可视化?
如果基础薄弱,对上面的这些功能难以理解可以看我的专栏:经典主干网络精讲与实战
这个专栏,从零开始时,一步一步的讲解这些,让大家更容易接受。
安装包
安装timm
使用pip就行,命令:
pip install timm
本文实战用的timm里面的模型。
安装 grad-cam
pip install grad-cam
数据增强Cutout和Mixup
为了提高成绩我在代码中加入Cutout和Mixup这两种增强方式。实现这两种增强需要安装torchtoolbox。安装命令:
pip install torchtoolbox
Cutout实现,在transforms中。
from torchtoolbox.transform import Cutout
# 数据预处理
transform = transforms.Compose([
transforms.Resize((224, 224)),
Cutout(),
transforms.ToTensor(),
transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])
需要导入包:from timm.data.mixup import Mixup,
定义Mixup,和SoftTargetCrossEntropy
mixup_fn = Mixup(
mixup_alpha=0.8, cutmix_alpha=1.0, cutmix_minmax=None,
prob=0.1, switch_prob=0.5, mode='batch',
label_smoothing=0.1, num_classes=12)
criterion_train = SoftTargetCrossEntropy()
参数详解:
mixup_alpha (float): mixup alpha 值,如果 > 0,则 mixup 处于活动状态。
cutmix_alpha (float):cutmix alpha 值,如果 > 0,cutmix 处于活动状态。
cutmix_minmax (List[float]):cutmix 最小/最大图像比率,cutmix 处于活动状态,如果不是 None,则使用这个 vs alpha。
如果设置了 cutmix_minmax 则cutmix_alpha 默认为1.0
prob (float): 每批次或元素应用 mixup 或 cutmix 的概率。
switch_prob (float): 当两者都处于活动状态时切换cutmix 和mixup 的概率 。
mode (str): 如何应用 mixup/cutmix 参数(每个’batch’,‘pair’(元素对),‘elem’(元素)。
correct_lam (bool): 当 cutmix bbox 被图像边框剪裁时应用。 lambda 校正
label_smoothing (float):将标签平滑应用于混合目标张量。
num_classes (int): 目标的类数。
EMA
EMA(Exponential Moving Average)是指数移动平均值。在深度学习中的做法是保存历史的一份参数,在一定训练阶段后,拿历史的参数给目前学习的参数做一次平滑。具体实现如下:
import logging
from collections import OrderedDict
from copy import deepcopy
import torch
import torch.nn as nn
_logger = logging.getLogger(__name__)
class ModelEma:
def __init__(self, model, decay=0.9999, device='', resume=''):
# make a copy of the model for accumulating moving average of weights
self.ema = deepcopy(model)
self.ema.eval()
self.decay = decay
self.device = device # perform ema on different device from model if set
if device:
self.ema.to(device=device)
self.ema_has_module = hasattr(self.ema, 'module')
if resume:
self._load_checkpoint(resume)
for p in self.ema.parameters():
p.requires_grad_(False)
def _load_checkpoint(self, checkpoint_path):
checkpoint = torch.load(checkpoint_path, map_location='cpu')
assert isinstance(checkpoint, dict)
if 'state_dict_ema' in checkpoint:
new_state_dict = OrderedDict()
for k, v in checkpoint['state_dict_ema'].items():
# ema model may have been wrapped by DataParallel, and need module prefix
if self.ema_has_module:
name = 'module.' + k if not k.startswith('module') else k
else:
name = k
new_state_dict[name] = v
self.ema.load_state_dict(new_state_dict)
_logger.info("Loaded state_dict_ema")
else:
_logger.warning("Failed to find state_dict_ema, starting from loaded model weights")
def update(self, model):
# correct a mismatch in state dict keys
needs_module = hasattr(model, 'module') and not self.ema_has_module
with torch.no_grad():
msd = model.state_dict()
for k, ema_v in self.ema.state_dict().items():
if needs_module:
k = 'module.' + k
model_v = msd[k].detach()
if self.device:
model_v = model_v.to(device=self.device)
ema_v.copy_(ema_v * self.decay + (1. - self.decay) * model_v)
加入到模型中。
#初始化
if use_ema:
model_ema = ModelEma(
model_ft,
decay=model_ema_decay,
device='cpu',
resume=resume)
# 训练过程中,更新完参数后,同步update shadow weights
def train():
optimizer.step()
if model_ema is not None:
model_ema.update(model)
# 将model_ema传入验证函数中
val(model_ema.ema, DEVICE, test_loader)
针对没有预训练的模型,容易出现EMA不上分的情况,这点大家要注意啊!
项目结构
FasterNet_Demo
├─data1
│ ├─Black-grass
│ ├─Charlock
│ ├─Cleavers
│ ├─Common Chickweed
│ ├─Common wheat
│ ├─Fat Hen
│ ├─Loose Silky-bent
│ ├─Maize
│ ├─Scentless Mayweed
│ ├─Shepherds Purse
│ ├─Small-flowered Cranesbill
│ └─Sugar beet
├─models
│ ├─__init__.py
│ └─fasternet.py
├─mean_std.py
├─makedata.py
├─train.py
├─cam_image.py
└─test.py
models:来源官方代码,对面的代码做了一些适应性修改。增加了一些加载预训练,调用模型的逻辑。
mean_std.py:计算mean和std的值。
makedata.py:生成数据集。
ema.py:EMA脚本
train.py:训练PoolFormer模型
cam_image.py:热力图可视化
为了能在DP方式中使用混合精度,还需要在模型的forward函数前增加@autocast(),如果使用GPU训练导入包from torch.cuda.amp import autocast,如果使用CPU,则导入from torch.cpu.amp import autocast。
计算mean和std
为了使模型更加快速的收敛,我们需要计算出mean和std的值,新建mean_std.py,插入代码:
from torchvision.datasets import ImageFolder
import torch
from torchvision import transforms
def get_mean_and_std(train_data):
train_loader = torch.utils.data.DataLoader(
train_data, batch_size=1, shuffle=False, num_workers=0,
pin_memory=True)
mean = torch.zeros(3)
std = torch.zeros(3)
for X, _ in train_loader:
for d in range(3):
mean[d] += X[:, d, :, :].mean()
std[d] += X[:, d, :, :].std()
mean.div_(len(train_data))
std.div_(len(train_data))
return list(mean.numpy()), list(std.numpy())
if __name__ == '__main__':
train_dataset = ImageFolder(root=r'data1', transform=transforms.ToTensor())
print(get_mean_and_std(train_dataset))
数据集结构:
运行结果:
([0.3281186, 0.28937867, 0.20702125], [0.09407319, 0.09732835, 0.106712654])
把这个结果记录下来,后面要用!
生成数据集
我们整理还的图像分类的数据集结构是这样的
data
├─Black-grass
├─Charlock
├─Cleavers
├─Common Chickweed
├─Common wheat
├─Fat Hen
├─Loose Silky-bent
├─Maize
├─Scentless Mayweed
├─Shepherds Purse
├─Small-flowered Cranesbill
└─Sugar beet
pytorch和keras默认加载方式是ImageNet数据集格式,格式是
├─data
│ ├─val
│ │ ├─Black-grass
│ │ ├─Charlock
│ │ ├─Cleavers
│ │ ├─Common Chickweed
│ │ ├─Common wheat
│ │ ├─Fat Hen
│ │ ├─Loose Silky-bent
│ │ ├─Maize
│ │ ├─Scentless Mayweed
│ │ ├─Shepherds Purse
│ │ ├─Small-flowered Cranesbill
│ │ └─Sugar beet
│ └─train
│ ├─Black-grass
│ ├─Charlock
│ ├─Cleavers
│ ├─Common Chickweed
│ ├─Common wheat
│ ├─Fat Hen
│ ├─Loose Silky-bent
│ ├─Maize
│ ├─Scentless Mayweed
│ ├─Shepherds Purse
│ ├─Small-flowered Cranesbill
│ └─Sugar beet
新增格式转化脚本makedata.py,插入代码:
import glob
import os
import shutil
image_list=glob.glob('data1/*/*.png')
print(image_list)
file_dir='data'
if os.path.exists(file_dir):
print('true')
#os.rmdir(file_dir)
shutil.rmtree(file_dir)#删除再建立
os.makedirs(file_dir)
else:
os.makedirs(file_dir)
from sklearn.model_selection import train_test_split
trainval_files, val_files = train_test_split(image_list, test_size=0.3, random_state=42)
train_dir='train'
val_dir='val'
train_root=os.path.join(file_dir,train_dir)
val_root=os.path.join(file_dir,val_dir)
for file in trainval_files:
file_class=file.replace("\\\\","/").split('/')[-2]
file_name=file.replace("\\\\","/").split('/')[-1]
file_class=os.path.join(train_root,file_class)
if not os.path.isdir(file_class):
os.makedirs(file_class)
shutil.copy(file, file_class + '/' + file_name)
for file in val_files:
file_class=file.replace("\\\\","/").split('/')[-2]
file_name=file.replace("\\\\","/").split('/')[-1]
file_class=os.path.join(val_root,file_class)
if not os.path.isdir(file_class):
os.makedirs(file_class)
shutil.copy(file, file_class + '/' + file_name)
完成上面的内容就可以开启训练和测试了。
FasterNet:CVPR2023年最新的网络,基于部分卷积PConv,性能远超MobileNet,MobileVit
文章目录
摘要
为了设计快速神经网络,许多工作都专注于减少浮点运算(FLOPs)的数量。然而,我们观察到这样的flop减少并不一定会导致类似水平的延迟减少。这主要源于低效的低浮点运算每秒(FLOPS)。为了实现更快的网络,我们重新考察了流行的运算符,并证明了这样低的FLOPS主要是由于运算符频繁的内存访问,特别是深度卷积。因此,我们提出了一种新的部分卷积(PConv),通过同时减少冗余计算和内存访问,更有效地提取空间特征。在PConv的基础上,我们进一步提出了fastternet,这是一种新的神经网络家族,它在各种设备上获得了比其他网络更高的运行速度,而不影响各种视觉任务的准确性。例如,在ImageNet- 1k上,我们的小型FasterNet-T0分别比GPU、CPU和ARM处理器上的MobileViT-XXS快3:1×、3:1×和2:5×,同时精度提高了2:9%。我们的大型fastnet - l达到了令人印象深刻的83:5%的top-1精度,与新兴的Swin-B相当,同时在GPU上具有49%的更高推断吞吐量,以及在CPU上节省42%的计算时间。代码可从https://github.com/JierunChen/FasterNet获得。
1、简介
神经网络在图像分类、检测和分割等各种计算机视觉任务中得到了快速发展。虽然它们令人印象深刻的性能支持了许多应用程序,但追求具有低延迟和高吞吐量的快速神经网络是一个蓬勃发展的趋势,以获得良好的用户体验、即时响应、安全原因等。
怎样才能更快?与要求更昂贵的计算设备相比,研究人员和从业者更喜欢设计具有成本效益的快速神经网络,降低计算复杂度,主要以浮点运算(FLOPs)的数量衡量。MobileNets [24, 25, 54], ShuffleNets[46, 84]和GhostNet[17]等利用深度卷积(DWConv)[55]和/或组卷积(GConv)[31]来提取空间特征。然而,在减少FLOPs的过程中,操作符经常会受到内存访问增加的副作用的影响。MicroNet[33]进一步分解和稀疏化网络,将其flop推到极低的水平。尽管在FLOPs上有所改进,但这种方法的分片计算效率很低。此外,上述网络通常伴有额外的数据操作,如拼接、洗牌和池化,这些操作的运行时间对小型模型来说往往很重要。
除了上述纯卷积神经网络(cnn)外,人们对使视觉transformer (vit)[12]和多层感知器(MLPs)架构[64]更小和更快的兴趣正在出现。例如,MobileViTs[48, 49, 70]和MobileFormer[6]通过将DWConv与改进的注意力机制相结合来降低计算复杂度。然而,他们仍然存在上述DWConv的问题,并且还需要专门的硬件支持修改后的注意力机制。使用高级但耗时的规范化和激活层也可能限制它们在设备上的速度。
所有这些问题共同导致了以下问题:这些“快速”的神经网络真的很快吗?为了回答这个问题,我们来看看延迟和FLOPs之间的关系
Latency
=
F
L
O
P
s
F
L
O
P
S
,
(1)
\\text Latency =\\fracF L O P sF L O P S \\text , \\tag1
Latency =FLOPSFLOPs, (1)
其中FLOPS是浮点运算每秒(floating-point operations per second)的缩写,用于衡量有效的计算速度。虽然有很多方法试图减少FLOPs,但很少考虑同时优化FLOPs以实现真正的低延迟。为了更好地理解这种情况,我们比较了典型神经网络在英特尔CPU上的flop。图2中的结果表明,许多现有的神经网络存在低FLOPS问题,它们的FLOPS通常低于流行的ResNet50。在如此低的flop情况下,这些“快”的神经网络实际上还不够快。FLOPs的减少不能准确地转化为延迟的减少。在某些情况下,没有任何改善,甚至会导致更糟糕的延迟。例如,CycleMLP-B1[5]的FLOPs是ResNet50[20]的一半,但运行更慢(即CycleMLPB1与ResNet50: 111.9ms与69.4ms)。请注意,FLOPs和延迟之间的这种差异在以前的工作[46,48]中也被注意到了,但仍未部分解决,因为他们采用了DWConv/GConv和各种具有低FLOPs的数据操作。人们认为没有更好的选择。
本文旨在通过开发一种简单而快速且有效的运算符来消除这种差异,该运算符可以用更少的运算符来维持较高的运算符。具体来说,在计算速度方面重新检查了现有的操作符,特别是DWConv。我们发现导致低FLOPS问题的主要原因是频繁的内存访问。本文提出一种新的部分卷积(PConv),作为一种有竞争力的替代方案,减少了计算冗余以及内存访问的数量。图1说明了我们的PConv的设计。它利用了特征图中的冗余,并系统地仅对部分输入通道应用常规卷积(Conv),而对其余通道保持不变。本质上,PConv比常规Conv具有更低的FLOPs,而比DWConv/GConv具有更高的FLOPs。换句话说,PConv更好地利用了设备上的计算能力。PConv在提取空间特征方面也很有效,本文后面的经验验证了这一点。
我们进一步介绍fastnet,它主要建立在我们的PConv之上,作为一个新的网络家族,在各种设备上高速运行。特别是,我们的fastnet实现了分类、检测和分割任务的最先进性能,同时具有更低的延迟和更高的吞吐量。例如,我们的小型fastnet - t0在GPU、CPU和ARM处理器上分别比MobileViT-XXS[48]快3:1×、3:1×和2:5×,而在ImageNet-1k上比MobileViT-XXS[48]快2:9%。我们的大型fastnet - l达到了83.5%的top-1精度,与新兴的Swin-B[41]不相上下,同时在GPU上提供了更高49%的吞吐量,并节省了42%的CPU计算时间。综上所述,我们的贡献如下:
- 我们指出了实现更高的失败次数而不仅仅是为了更快的神经网络而减少失败次数的重要性。
- 我们引入了一个简单但快速和有效的算子PConv,它有很大的潜力来取代现有的go-to - choice DWConv。
- 我们引入了fastnet,它在各种设备上运行良好且普遍快速,如GPU、CPU和ARM处理器。
- 我们对各种任务进行了广泛的实验,并验证了我们的PConv和fastnet的高速和有效性。
2、相关工作
我们简要回顾了之前关于快速和高效神经网络的工作,并将其与之区分开来。
CNN。cnn是计算机视觉领域的主流架构,尤其是在实际部署时,快速和准确同样重要。虽然已经有大量的研究[7,8,21,33,55,56,83,86]来实现更高的效率,但它们背后的原理或多或少是执行低秩近似。具体来说,群卷积[31]和深度可分离卷积 [55] (由深度卷积和逐点卷积组成)可能是最受欢迎的。它们已被广泛应用于移动/面向边缘的网络,如MobileNets [24,25,54], ShuffleNets [46,84], GhostNet [17], EfficientNets [61,62], TinyNet [18], Xception [8], CondenseNet [27,78], TVConv [4], MnasNet[60],和FBNet[74]。虽然它们利用滤波器中的冗余来减少参数和FLOPs的数量,但在增加网络宽度以补偿精度下降时,它们会受到内存访问增加的影响。相反,我们考虑了特征映射中的冗余,并提出了一种局部卷积来同时减少失败和内存访问。
ViT、MLP和变体。自从Dosovitskiy等人[12]将变压器的应用范围[69]从机器翻译[69]或预测[73]扩展到计算机视觉领域以来,人们对ViT的研究兴趣日益浓厚。后续的许多工作尝试在训练设置[58,65,66]和模型设计[15,40,41,72,85]方面改进ViT。一个显著的趋势是通过降低注意力算子的复杂性[1,29,45,63,68],将卷积纳入ViTs[6,10,57],或同时进行[3,34,49,52]来追求更好的准确度-潜伏期权衡。此外,还有一些研究[5,35,64]提出用简单的mlp算子代替注意力。然而,它们经常进化成类似cnn的[39]。在本文中,我们重点分析卷积运算,尤其是DWConv,原因如下:第一,注意力相对于卷积的优势不明确或存在争议[42,71]。其次,基于注意力的机制通常比卷积机制运行得慢,因此对当前行业不利[26,48]。最后,DWConv在许多混合模型中仍然是热门的选择,因此值得仔细研究。
4、实验结果
我们首先研究我们的PConv的计算速度和它的有效性,当与PWConv结合。然后,我们综合评估我们的fastnet在分类、检测和分割任务中的性能。最后,我们进行了一项简短的消融研究。
为了对延迟和吞吐量进行基准测试,我们选择了以下三种典型的处理器,它们涵盖了广泛的计算能力:GPU (2080Ti)、CPU (Intel i9-9900X,使用单线程)和ARM (Cortex-A72,使用单线程)。我们报告了批大小为1的输入的延迟和批大小为32的输入的吞吐量。在推断过程中,只要适用,BN层都会合并到它们的相邻层。
4.1. PConv是快速的,但具有很高的FLOPS
下面我们展示了我们的PConv是快速的,更好地利用了设备上的计算能力。具体来说,我们将10层纯PConv叠加在一起,以典型维度的特征图作为输入。然后我们在GPU、CPU和ARM处理器上测量FLOPs和延迟/吞吐量,这也允许我们进一步计算FLOPs。我们对其他卷积变异体重复相同的过程并进行比较。
表1中的结果显示,对于高失败次数和低失败次数,PConv总体上是一个有吸引力的选择。它只有常规Conv的 1 16 \\frac116 161 FLOPs,在GPU、CPU和ARM上分别比DWConv高14×、6.5×和22.7× FLOPs。我们不惊讶地看到,常规Conv有最高的失败,因为它已经不断地优化了多年。然而,它的总失败次数和延迟/吞吐量是无法承受的。尽管GConv和DWConv的失败次数显著减少,但失败次数也大幅减少。此外,它们倾向于增加通道的数量来补偿性能下降,然而,这增加了它们的延迟。
4.2. PConv与PWConv同时有效
接下来,我们展示了一个PConv后跟一个PWConv是有效的近似一个正则Conv来转换特征映射。为此,我们首先将ImageNet-1k val分割图像输入到预训练的ResNet50中,构建4个数据集,并在4个阶段中分别提取第1次Conv 3 × 3前后的特征图。每个特征图数据集被进一步划分为train (70%), val(10%)和test(20%)子集。然后,我们构建了一个由PConv和PWConv组成的简单网络,并在具有均方误差损失的特征地图数据集上训练它。为了比较,我们还在相同的设置下构建和训练了DWConv + PWConv和GConv + PWConv网络。
从表2可以看出,PConv + PWConv的测试损失最小,这意味着它们在特征变换中可以更好地逼近一个规则的Conv。研究结果还表明,仅从特征地图的一部分捕获空间特征是充分和有效的。PConv在设计快速有效的神经网络方面显示出巨大的潜力。
4.3. fastnet对ImageNet-1k分类
为了验证我们的fastnet的有效性和效率,我们首先在大规模的ImageNet-1k分类数据集[53]上进行实验。它涵盖了1k类的常见对象,包含约1.3M的标记图像用于训练和50k的标记图像用于验证。我们使用AdamW优化器[44]训练我们的模型300个时期。对于fastnet - m /L,我们将批量大小设置为2048,对于其他变异体,我们将批量大小设置为4096。我们使用峰值为0:001的余弦学习率调度器[43]·批大小=1024和20个周期的线性预热。我们应用常用的正则化和增强技术,包括权重衰减[32]、随机深度[28]、标签平滑[59]、Mixup[81]、Cutmix[80]和Rand增强[9],对不同的fastnet变异体具有不同的幅度。为了减少训练时间,我们对前280个训练周期使用192×192分辨率,其余20个周期使用224×224分辨率。为了公平的比较,我们没有使用知识蒸馏[23]和神经架构搜索[87]。我们报告了使用224 × 224分辨率和0.9作物比的中心作物在验证集上的top-1精度。详细的训练和验证设置见附录。
图7和表3展示了我们的fastnet相对于最先进的分类模型的优越性。图7中的权衡曲线清楚地表明,fastnet在平衡所有被检测网络的精度和延迟/吞吐量方面达到了最新的水平。从另一个角度来看,当具有相似的top-1精度时,fastnet在各种设备上运行的速度比各种CNN, ViT和MLP模型更快。如表3所示,fastnet - t0在GPU、CPU和ARM处理器上分别比MobileViT-XXS[48]快3:1×、3:1×和2:5×,同时比MobileViT-XXS[48]更精确2:9%。我们的大型fastnet - l实现了83.5%的top-1精度,与新兴的Swin-B[41]和ConvNeXt-B[42]相当,同时在GPU上有49%和39%的高推断吞吐量,以及节省42%和22%的CPU计算时间。鉴于如此有前景的结果,我们强调,我们的fastnet在架构设计方面比许多其他模型要简单得多,这表明了设计简单而强大的神经网络的可行性。
4.4. 下游任务的fastnet
为了进一步评估fastnet的泛化能力,我们在具有挑战性的COCO数据集[36]上进行了对象检测和实例分割的实验。作为一种惯例,我们使用ImageNet预训练的fastnet作为骨干,并配备流行的掩码R-CNN检测器[19]。为了突出骨干本身的有效性,我们只需遵循PoolFormer[79],并采用AdamW优化器,1×训练计划(12个周期),批大小为16,和其他训练设置,而无需进一步的超参数调优。
表4显示了fastnet与代表性模型的比较结果。fastnet通过具有更低的延迟和更高的平均精度(AP),始终优于ResNet和ResNext。具体来说,与标准基线ResNet50相比,fastnet节省了36%的计算时间,并产生了+1.9+1.9的框AP和+2.4+2.4的掩码AP。fastnet也对ViT变体具有竞争力。在类似的失败情况下,fastnet - l将PVT-Large的延迟减少了一半,即在GPU上从152毫秒减少到74毫秒,并实现+1.1+1.1更高的框AP和+0.4+0.4更高的mask AP。
4.5、消融实现
我们对部分比值r的值以及激活层和归一化层的选择进行了简单的消融研究。我们在ImageNet top-1准确性和设备上的延迟/吞吐量方面比较了不同的变体。结果汇总于表5中。对于部分比率r,我们默认为所有fastnet变体将其设置为
1
4
\\frac14
41 ,这在类似的复杂性下实现了更高的准确性、更高的吞吐量和更低的延迟。过大的偏比r会使PConv退化为常规的Conv,而过小的偏比r会使PConv对空间特征的捕获效果降低。对于规范化层,我们选择BatchNorm而不是LayerNorm,因为BatchNorm可以合并到其相邻的卷积层中,从而更快地进行推断,而在我们的实验中,BatchNorm与LayerNorm一样有效。对于激活函数,我们经验地发现GELU比ReLU更适合fastnet - t0 /T1模型。然而,fastnett2 /S/M/L则相反。由于篇幅的限制,我们在表5中只展示了两个示例。我们推测,GELU通过具有较高的非线性来增强fastnet - t0 /T1,而对于较大的fastnet变体,这种优势逐渐消失。
5、结论
在本文中,我们研究了许多已建立的神经网络遭受每秒低浮点运算(FLOPS)这一常见且尚未解决的问题。我们回顾了一个瓶颈运算符,DWConv,并分析了它导致减速的主要原因——频繁的内存访问。为了克服这一问题并实现更快的神经网络,我们提出了一种简单而快速有效的算子PConv,它可以很容易地插入到许多现有的网络中。我们进一步介绍了我们的通用fastnet,建立在我们的PConv之上,在各种设备和视觉任务上实现了最先进的速度和精度权衡。我们希望我们的PConv和fastnet将激发更多关于简单而有效的神经网络的研究,超越学术界,直接影响行业和社区。
附录
在本附录中,我们提供了关于实验设置、完整的比较图、架构配置、PConv实现、与相关工作的比较、局限性和未来工作的进一步细节。
A. ImageNet-1k实验设置
我们在表6中提供了ImageNet-1k训练和评估设置。它们可以用于再现我们在表3和图7中的主要结果。不同的fastnet变体在正则化和增强技术的大小上有所不同。幅度随模型增大而增大,以缓解过拟合,提高精度。需要注意的是,在表3和图7的比较作品中,MobileViT、EdgeNext、PVT、CycleMLP、ConvNeXt、Swin等大部分也采用了这种先进的训练技术(ADT)。有些甚至严重依赖超参数搜索。对于其他无ADT的,如ShuffleNetV2, MobileNetV2, GhostNet,虽然比较不完全公平,但我们纳入它们作为参考。
B.下游任务实验设置
对于COCO2017数据集上的对象检测和实例分割,我们为我们的fastnet骨干配备了流行的Mask R-CNN检测器。我们使用ImageNet-1k预训练权重初始化骨干和Xavier初始化附加层。详细设置见表7。
C. ImageNet-1k上的完整比较图
图8为ImageNet-1k上的完整对比图,这是本文中图7的扩展,延迟范围更大。图8显示了一致的结果,在GPU、CPU和ARM处理器上,fastnet在平衡精度和延迟/吞吐量方面比其他算法做了更好的权衡。
D.详细的架构配置
我们在表8中给出了详细的架构配置。虽然不同的fastnet变体共享一个统一的体系结构,但它们在网络宽度(通道的数量)和网络深度(每个阶段的fastnet块的数量)方面有所不同。体系结构末尾的分类器用于分类任务,但在其他下游任务中被删除。
E. PConv的实现
我们在清单1中提供了基于pytorch的PConv实现。有两种向前传球选择,即向前切片和向前分猫。前向切片选择写入卷积输出来代替输入,这是用于更快的推断,但不是用于训练,因为就地操作修改梯度计算。相比之下,前向分割猫选择将卷积输出与不变的特征映射连接起来,这保留了中间梯度计算,并用于训练。表9显示了这两个选择在推理过程中的速度比较。前向切片实现比另一种运行更快,特别是对于小型模型和更强大的计算设备,例如GPU上的fastnet - t0。
F.更多与相关工作的比较
提高FLOPS。还有一些其他的作品[11,76]也在研究FLOPS的问题,并试图改进它。它们通常遵循现有的操作符,并试图找到它们合适的配置,例如,RepLKNet[11]只是增加内核大小,而TRT-ViT[76]则在体系结构中对不同的块进行重新排序。相比之下,本文提出了一种新颖高效的PConv,为FLOPS的改进开辟了新的方向和潜在的更大空间。
PConv与GConv。PConv在原理上相当于一个修改的GConv[31],它只作用于一个组,而不影响其他组。虽然很简单,但这种改变在以前还没有被探索过。它还可以防止操作符对内存的过度访问,并且在计算上更加高效。从低秩近似的角度来看,PConv通过进一步降低滤波器内部冗余度来改进GConv,而不局限于滤波器间冗余[16]。
fastnet vs. ConvNeXt。在用PConv替换DWConv后,我们的fastnet看起来类似于ConvNeXt[42]。然而,他们的动机是不同的。当ConvNeXt通过试错寻找更好的结构时,我们在PConv之后附加PWConv以更好地聚合来自所有信道的信息。此外,ConvNeXt遵循ViT,使用更少的激活函数,而我们有意地从PConv和PWConv的中间去掉它们,以减少它们在逼近常规Conv时的误差。
有效推理的其他范例。我们的工作重点是高效的网络设计,与其他范式正交,如神经架构搜索[13],网络修剪[50]和知识蒸馏[23]。它们可以在本文中得到更好的应用。然而,我们选择不这样做,以保持我们的核心思想为中心,并使成绩获得明确和公平。
其他的部分/掩模卷积也可以。有几个作品[14,37,38]与我们的PConv有相似的名字。然而,它们在目标和方法上有很大的不同。例如,他们在部分像素上应用过滤器以排除无效斑块[38],实现自我监督学习[14],或合成新图像[37],而我们的目标是通道维度,以实现高效推断。
G.局限性和未来工作
我们已经证明了PConv和fastnet与现有的操作和网络竞争是快速和有效的。然而,本文有一些次要的技术限制。首先,PConv设计为只对部分输入通道进行正则卷积,而对其余通道保持不变。因此,偏卷积的步幅应始终为1,以使卷积输出的空间分辨率与未触及通道的空间分辨率对齐。注意,对空间分辨率进行下采样仍然是可行的,因为在架构中可能会有额外的下采样层。其次,虽然我们提供了PConv前向传递的两种实现,但我们认为它们不一定是最优的。可能会有更高效、运行速度更快的实现,例如,使用channel-last张量格式、自定义c++和CUDA扩展。最后,我们的fastnet简单地建立在卷积算子的基础上,其接受域可能有限。未来可努力扩大其接受域,并与其他操作相结合,以追求更高的精度。
以上是关于FasterNet实战:使用FasterNet实现图像分类任务的主要内容,如果未能解决你的问题,请参考以下文章
Java Socket实战之六 使用NIO包实现Socket通信