EfficientNet是谷歌在2019年提出的一项新型模型缩放方法,该方法使用一种简单但高效的复合系数(compound coefficient)以更加结构化的方式扩展 CNN。与任意扩展网络维度(如宽度、深度、分辨率)的传统方法不同,该新方法使用固定的一组缩放系数扩展每个维度,该方法极大地提升了模型的准确率和效率。并开发出了一系列模型——EfficientNet B0~B7。
EfficientNet论文链接:https://arxiv.org/pdf/1905.11946.pdf
Tensorflow实现源代码链接:https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet
PyTorch实现源代码链接:https://github.com/lukemelas/EfficientNet-PyTorch
卷积神经网络(ConvNets,简写CNN)通常是在固定的资源预算下开发的,如果有更多的资源可用,则会进行扩展以获得更高的精度。在这篇论文中,系统地研究了模型缩放,并发现仔细平衡网络的深度、宽度和分辨率可以获得更好的性能。基于这一观察结果,提出了一种新的标度方法,使用简单而高效的复合系数来均匀地标度深度/宽度/分辨率的所有维度。证明了该方法在扩展MobileNets和ResNet方面的有效性。
为了进一步研究,使用神经架构搜索设计了一个baseline网络,并将其扩展获得一系列被称为EfficientNets模型,它的精度和效率比之前所有的卷积网络都好。尤其EfficientNet-B7在ImageNet上获得了最先进的 84.4%的top-1精度 和 97.1%的top-5精度,同时比之前最好的CNN缩小了8.4倍、速度提高了6.1倍。EfficientNets也可以很好的迁移,并且实现了最先进的精度——CIFAR-100(91.7%)、Flowers(98.8%)和其他3个迁移学习数据集上传输良好,参数少了一个数量级。
放大CNN被广泛用于获得更好的精度。例如,ResNet可以通过使用更多的层,从ResNet-18增加到ResNet-200;最近,GPipe将baseline模型放大4倍,实现了84.3%的ImageNet top-1精度。然而,扩展CNN的过程从来没有被很好地理解过,目前有很多方法可以做到这一点。最常见的方法是根据对流的深度和宽度。另一种不太常见但越来越流行的方法是通过图像分辨率来放大模型。在以前的工作中,通常只缩放深度、宽度和图像大小三个维度中的一个。虽然可以任意缩放两个或三个维度,但是任意缩放需要繁琐的手工调整,而且仍然会产生次优的精度和效率。
在这篇论文中,我们想要研究和重新思考扩大CNN的过程。特别地,我们研究了中心问题:是否有一种原则性的方法来扩大卷积神经网络,从而达到更好的准确性和效率? 我们的实证研究表明,平衡网络宽度/深度/分辨率的所有维度是至关重要的,而令人惊讶的是,这种平衡可以通过简单地以恒定的比例缩放每个维度来实现。在此基础上,我们提出了一种简单而有效的复合标度方法。与常规方法中任意缩放这些因子不同,我们的方法使用一组固定的缩放系数来均匀地缩放网络的宽度、深度和分辨率。例如,如果我们想使用 2 N 2^{N} 2N倍的计算资源,然后我们可以简单地对网络扩大 α N α^{N} αN,宽度扩大 β N β^{N} βN和图像分辨率扩大 γ N γ^{N} γN,α,β,γ是由原来的小模型上做微小的网格搜索决定的常量系数。Figure2说明了我们的缩放方法与传统方法的区别。
直观来讲,如果图像尺寸变大,复合的缩放方法会很有意义,因为当图像尺寸变大意味着网络需要更多层来增加接受野,同时需要更多的通道来捕捉更大图像上更多细粒度的模式信息。事实上,以前的理论和实证结果两者表明网络之间存在一定的关系宽度和深度,但据我们所知,我们是首先要凭经验量化三者之间的关系网络宽度,深度和分辨率的尺寸。
我们在已经存在的MobileNets和ResNets上展示了我们的缩放方法可以工作得很好,值得注意的是,模型缩放的高效性严重地依赖于baseline网络,为了进一步研究,我们使用网络结构搜索发展了一种新的baseline网络,然后将它缩放来获得一系列模型,称之为EfficientNets。
Figure 1总结了ImageNet的表现,EfficientNets由于其他CNN网络,尤其地,我们的EfficientNet-B7超越了之前最好的GPipe的精度,但是参数量少了8.4倍、速度快了6.1倍。相比于广泛使用的ResNet-50,我们的EfficientNets-B4在相近的FLOPS下将top-1精度从76.3%提高到了82.6%。除了ImageNet,EfficientNets在其他数据集上表现也很好,在8个广泛应用的数据集中的5个实现了最先进的精度,然而比存在的卷积网络的参数量减少了21倍。
CNN精度:自从AlexNet赢得2012的ImageNet竞赛,ConvNets随着变得更大获得了更高的精度,同时GoogleNet使用6.8M的参数获得了74.8%的top-1精度,SENet使145M参数获得了82.7%的top-1精度。最近,GPipe进一步提高了精度——使用了557M的参数获得了84.3%的top-1验证精度:它如此的大以至于需要将网络划分使用特定的并行化手段训练,然后将每一部分传递到一个不同的加速器。然而这些模型主要是为ImageNet设计,但是将其迁移到其他应用上时效果也很好。
CNN效率:深度网络的参数过多,模型压缩是一种通用的方法减小模型大小——平衡精度和效率。当移动网络变得无处不在时,我们也通常要手动设计高效的CNN,比如SqueezeNets、MobileNets、ShuffleNets。最近,神经网络结构搜索在设计高效的CNN变得越来越流行,并且通过广泛搜索网络宽度、深度、卷积核类型和大小得到了比手动设计的模型更高的精度。然而,目前还不清楚怎么将这些技术应用到更大的模型中,通常要更大的设计空间和更贵的微调成本,在本篇论文中,我们旨在研究效率设计更大规模的CNN,为了实现这个目标,我们采用模型缩放。
模型缩放:有很多的方法因不同的资源限制对CNN进行缩放:ResNet可以通过调整深度(缩小到ResNet-18,放大到ResNet-200),WideResNet和MobileNets可以通过对宽度(#channels)缩放。公认的是更大的输入图像尺寸有利于提高精度,同时需要更多的计算量。尽管之前的研究展示了网络深度和宽度对CNN的表现力很重要,它仍然是一个开放的问题来高效缩放CNN获得更好的效率和精度。我们的工作系统地研究了CNN对网络深度、宽度和分辨率这三个维度进行了缩放。
在本节中,我们将阐述缩放问题,研究不同的方法,并提出新的缩放方法。
卷积层 i i i 可以用公式 Y i = F i ( X i ) Y_i =F_i(X_i) Yi=Fi(Xi)定义, F i F_i Fi代表卷积操作, Y i Y_i Yi表示输出张量, X i X_i Xi表示输入张量, < H i , W i , C i >
其中, N N N 是分类网络, X X X表示输入, F i F_i Fi是基础网络层, L i L_i Li表示在第 i i i 个stage中基础网络层 F i F_i Fi的重复次数,总共有s个stage。图2(a)展示了一种代表性的CNN,其空间维度,即feature map的尺寸逐层递减,但是通道维度是逐渐增加的,举个例子,从最开始的输入维度 < 224 , 224 , 3 > <224,224,3> <224,224,3>变化到最终的输出维度 < 7 , 7 , 512 > <7,7,512> <7,7,512>。
不像规则的CNN设计,大多聚焦于发现最好的基础网络层 F i F_i Fi,然后再利用模型缩放在不改变预先在baseline网络定义好的 F i F_i Fi的前提下扩展网络深度 L i L_i Li、宽度 C i C_i Ci、分辨率 ( H i , W i ) (H_i,W_i) (Hi,Wi)。通过固定 F i F_i Fi,模型缩放简化了资源约束条件,但是它仍然有一个比较大的搜索空间 < L i , C i , H i , W i >
其中,这里的 w , d , r w,d,r w,d,r是缩放网络分别对宽度、深度、分辨率的缩放系数, F i ^ \hat{F_i} Fi^, L i ^ \hat{L_i} Li^, H i ^ \hat{H_i} Hi^, W i ^ \hat{W_i} Wi^, C i ^ \hat{C_i} Ci^是预先在baseline网络中定义好的参数。
深度(d):缩放网络深度在许多CNN都有使用,直觉上更深的网络可以捕获到更丰富和更复杂的特征,在新任务上也可以泛化的更好。然而,更深的网络由于梯度消失问题(这里我更倾向于说成是网络退化问题)也更难训练。尽管有一些技术,例如跨层连接、批量归一化等可以有效减缓训练问题,但是深层网络的精度回报减弱了:举个例子,ResNet-1000和ResNet-101具有类似的精度,即使它的层数更多。Figure 3(中间的图)展示了我们在使用不同的深度系数d缩放网络的研究结果,更近一步的表明了精度回报的减弱问题。
宽度(w):缩放网络宽度也是一种常用的手段,正如之前讨论过的,更宽的网络可以捕捉到更细粒度的特征从而易于训练。然而,非常宽而又很浅的网络在捕捉高层次特征时有困难,我们的实验结果Figure 3(左)表明了当网络宽度随着w变大时,精度很快就饱和了。
分辨率(r):使用更高分辨率的输入图像,CNN可能可以捕捉到更细粒度的模式。从最早的 224x224,现在有些CNN为了获得更高的精度选择使用 229x229 或者 331x331。目前,GPipe使用 480x480 的分辨率获得了最先进的ImageNet精度,更好的精度比如 600x600 也被广泛使用在目标检测网络中。Figure 3(右)展示了缩放网络分辨率对精度的影响,同样可以看到在非常高的分辨率时网络精度回报会减弱。
由此,我们得到 Observation 1:对网络深度、宽度和分辨率中的任何温度进行缩放都可以提高精度,但是当模型足够大时,这种放大的收益会减弱。
我们经验上可以观察到不同缩放维度之间是不独立的,直观上来讲,对于分辨率更高的图像,我们应该增加网络深度,因为需要更大的感受野来帮助捕获更多像素点的类似特征,同时也应该增加网络宽度来获得更细粒度的特征。这些直觉指导着我们去协调平衡不同缩放维度而不是传统的单个缩放维度。
为了验证我们的直觉,我们在不同的网络深度和分辨率下比较了宽度变化的影响,正如Figure 4中所示,如果我们在 d=1.0 和 r=1.0 时仅仅缩放网络宽度,精度很快就饱和了。但是在d=2.0 和 r=2.0时在相同的FLOPS下宽度缩放就可以获得更好的精度。这些结果导致我们得到了第二个观察结果。
Observation 2:为了追去更好的精度和效率,在缩放时平衡网络所有维度至关重要。
事实上,之前的一些工作已经开始在追去任意缩放网络深度和宽度,但是他们仍然需要复杂的人工微调。在本篇论文中,我们提出了一个新的复合缩放方法——使用一个复合系数 ϕ 统一缩放网络宽度、深度和分辨率(公式3):
此处的 α,β,γ 都是由一个很小范围的网络搜索得到的常量,直观上来讲,ϕ是一个特定的系数,可以控制用于资源的使用量, α,β,γ 决定了具体是如何分配资源的。值得注意的是,常规卷积op的计算量是和d, w 2 w^{2} w2, r 2 r^{2} r2成正比的,加倍深度会使得FLOPS加倍,但是加倍宽度和分辨率会使得FLOPS加4倍。由于卷积ops经常在CNN中占据了大部分计算量,使用等式(3)缩放CNN将会使得整体计算量近似增加 ( α ⋅ β 2 ⋅ γ 2 ) ϕ (α ⋅ β^{2} ⋅ γ^{2})^{ϕ} (α⋅β2⋅γ2)ϕ倍,在本篇论文中,我们对任意ϕ增加了约束 ( α ⋅ β 2 ⋅ γ 2 ) (α ⋅ β^{2} ⋅ γ^{2}) (α⋅β2⋅γ2) ≈ 2,整体的计算量近似增加了 2 ϕ 2^{ϕ} 2ϕ倍。
因为模型缩放不改变baseline网络中的 F i ^ \hat{F_i} Fi^,所以有一个好的baseline网络是很重要的,我们使用之前的ConvNets对我们的缩放方法做了评估,但是为了更好验证我们的缩放方法的高效性,我们也提出了一种基于移动应用的baseline模型——EfficientNet。
受到MnasNet的启发,我们也开发了一种多目标的神经网络结构搜索同时优化精度和FLOPS,我们的搜索空间和MnasNet相同,同时我们的优化目标为 A C C ( m ) × [ F L O P S ( m ) / T ] w ACC(m)×[FLOPS(m)/T] ^{w} ACC(m)×[FLOPS(m)/T]w,这里 A C C ( m ) ACC(m) ACC(m)和 F L O P S ( m ) FLOPS(m) FLOPS(m)分别是模型m的精度和计算量,T 是目标计算量,w=−0.07 是一个超参数用来权衡精度和FLOPS。不像MnasNet中的优化目标,这里优化的是FLOPS而不是延迟,因为我们没有说是要在特定的硬件平台上做加速。我们的搜索方法得到了一个高效的网络,我们称之为EfficientNet-B0,因为我们使用的搜索空间和MnasNet相似,所以得到的网络结构也很相似,不过我们的EfficientNet-B0稍微大了点,因为我们的FLOPS预算也比MnasNet中大(400M)。table 1展示了EfficientNet-B0的结构,它的主要构建块就是移动倒置瓶颈MBConv (Sandler et al., 2018; Tan et al., 2019),此外,我们还添加了挤压和激励优化(Hu et al., 2018)。
然后以EfficientNet-B0为baseline模型,将我们的复合缩放方法应用到它上面,分为两步:
值得注意的是,直接在一个大模型上搜索得到 α , β , γ α,β,γ α,β,γ可能会导致一个更好的表现,但是搜索成本会很高,我们的方法解决了这个问题:只在小的baseline网络中做了一次搜索得到 α , β , γ α,β,γ α,β,γ (step1),然后对于其他的模型都使用的是相同的 α , β , γ α,β,γ α,β,γ (step2),只是通过ϕ来调整模型的大小和FLOPS。
在这一节中,我们将首先评估现有的CNN和新提出的EfficientNets的缩放方法。
作为概念的证明,我们首先将我们的缩放方法应用到广泛使用的MobileNets和ResNet 。Table 3显示了以不同方式缩放它们的ImageNet结果。与其他一维尺度变换方法相比,我们的复合尺度变换方法提高了所有这些模型的精度,表明了我们提出的方法对于一般现有CNN的有效性。
我们在ImageNet上训练我们的有效网络模型,使用类似的设置(Tan等人,2019) :
Table 2(见上)显示了所有从相同基线Efficient - b0扩展而来的Efficient - net模型的性能。我们的有效网模型通常使用一个数量级的更少的参数和拖鞋比其他具有类似精度的卷积神经网络。其中,我们的Effective net - b7在66M参数、37B FLOPS的情况下,实现了84.4%的top1 / 97.1%的top-5精度,比之前最好的GPipe精度高了8.4x smaller(Huang et al., 2018)。
Figure 1和Figure 5 (Figure 1-Figure 4见上,Figure 5见下)展示了典型CNN的参数-准确性和FLOPS-准确性曲线,其中我们的比例 EfficientNet 模型在参数和FLOPS远少于其他CNN的情况下获得了更好的准确性。值得注意的是,我们的 EfficientNet 模型不仅体积小,而且计算成本更低。例如,我们的EfficientNet-B3比ResNeXt- 101 (Xie et al., 2017)使用18x fewer FLOPS实现更高的精度。
为了验证计算成本,我们还测量了真实CPU上几个典型CNN的推理延迟,如Table 4所示,其中我们报告了20次运行的平均延迟。我们的EfficientNet-B1比广泛使用的ResNet-152 (He et al., 2016)快5.7x faster,而EfficientNet-B7比GPipe (Huang et al., 2018)快6.1x faster,这表明我们的efficient net在真实的硬件上确实是快的。
我们还在一个常用的传输学习数据集列表上评估了我们的EfficientNet,如Table 6所示。我们从(Kornblith et al., 2019)和(Huang et al., 2018)借用了相同的训练设置,在新数据集上使用ImageNet预先训练的检查点和微调。
Table 5显示了转移学习性能:
Figure 6比较了各种模型的精度-参数曲线。总的来说,我们的 EfficientNet 在参数比现有模型少一个数量级的情况下,始终能够获得更好的精度,包括ResNet 、DenseNet 、Inception 和NASNet 。
为了将我们提出的缩放方法从 EfficientNet 构中分离出来,Figure 8 比较了同一 EfficientNet-B0 基线网络中不同缩放方法的ImageNet性能。一般来说,所有的尺度变换方法都可以在增加 FLOPS 的代价下提高精度,但是我们的复合尺度变换方法可以进一步提高精度,比其他单维度尺度变换方法提高2.5%,这说明了我们提出的复合尺度变换方法的重要性。
为了进一步了解为什么我们的复合缩放方法比其他方法更好,Figure 7 比较了几种具有代表性的模型的类激活图。所有这些模型都是从相同的基线进行缩放的,它们的统计数据如Table 7 所示。从ImageNet验证集中随机选取图像。如图所示,复合缩放模型更倾向于关注具有更多对象细节的相关区域,而其他模型要么缺乏对象细节,要么无法捕获图像中的所有对象。
在这篇论文中,我们系统地研究了CNN的缩放,并发现仔细平衡网络的宽度、深度和分辨率是一个很重要但又缺失的部分,这阻碍了我们获得更好的精度和效率。为了解决这个问题,我们提出了一个简单而高效的复合缩放方法,它使我们能够更有原则地将基线CNN缩放到任何目标资源约束,同时保持模型的效率。通过这种复合缩放方法,我们证明了一个移动尺寸的 EfficientNet 模型可以非常有效地进行缩放,在ImageNet和5个常用的传输学习数据集上,以一个数量级更少的参数和FLOPS来超越最先进的精度。
论文学习小结:
目前我主要在kaggle的一个比赛上用的EfficientNetB7,用于图像分类;
安装并导入相关库:
# Install and import necessary libraries
!pip install efficientnet
import tensorflow as tf
import tensorflow.keras.layers as L
import efficientnet.tfkeras as efn
from sklearn import metrics
from keras.callbacks import ModelCheckpoint
不同数据集不同的处理方法,这里就不细说了,得到相应的train_dataset,valid_dataset,test_dataset;
设置好EPOCHS,BATCH_SIZE,IMAGE_SIZE,Learning rate,lr_schedule;
其中我用的是EfficientNerB7,就把IMAGE_SIZE=768;
lr_schedule由keras.callbacks.LearningRateSchedule()得到的;
之后就可以迁移EfficientNetB7进行训练了;
# model
with strategy.scope():
model = tf.keras.Sequential([
efn.EfficientNetB7(
input_shape=(IM_Z, IM_Z, 3),
weights='imagenet',
include_top=False
),
L.GlobalAveragePooling2D(),
L.Dense(train_labels.shape[1], activation='softmax')
])
model.compile(
optimizer='adam',
loss = 'categorical_crossentropy',
metrics=['categorical_accuracy']
)
model.summary()
# save model
ch_efb7 = ModelCheckpoint(filepath="model_efb7.h5", save_weights_only=True,
verbose=1)
# train model
history = model.fit(
train_dataset_1,
epochs=EPOCHS,
callbacks=[lr_schedule, ch_efb7],
# STEPS_PER_EPOCH_1 = train_labels.shape[0] // BATCH_SIZE
steps_per_epoch=STEPS_PER_EPOCH_1,
# 我没有用验证集
# validation_data=valid_dataset_1
)
最后训练的结果挺好的:
3 EfficientNet的Pytorch应用(暂未使用Pytorch版本的,先占坑)
革命尚未成功,同志仍需努力!