1、通过EfficientNet进行微调以实现图像分类概述
通过EfficientNet进行微调以实现图像分类,是一个使用EfficientNet作为预训练模型,并通过微调(fine-tuning)来适应特定图像分类任务的过程。一下是对相关重要术语的解释。
- EfficientNet:这是一个高效的卷积神经网络(CNN)架构,旨在通过统一缩放网络深度、宽度和分辨率等维度来优化性能和效率。EfficientNet有多个预训练的变体,如EfficientNet-B0到EfficientNet-B8,它们在多个图像分类任务上取得了很好的效果。
- 微调(Fine-tuning):在深度学习中,微调通常涉及使用预训练模型(如EfficientNet)的权重作为起点,并在特定数据集上进一步训练该模型。微调可以加速训练过程,因为它利用了预训练模型在大量数据上学到的通用特征。
- 图像分类:这是计算机视觉中的一个基本任务,涉及将输入图像分配给预定义的一组类别中的一个。例如,一个图像分类模型可能被训练来识别图像中的对象(如猫、狗、汽车等)或场景(如森林、海滩、城市等)。
1.1 EfficientNet简介
EfficientNet,最初由Tan和Le在2019年提出,是目前最高效的模型之一(即在ImageNet和常见的图像分类迁移学习任务上达到最先进的准确率时所需的浮点运算量(FLOPs)最少)。
最小的基本模型类似于MnasNet,后者通过显著更小的模型达到了接近最高水平的性能。通过引入一种启发式的方法来缩放模型,EfficientNet提供了一系列模型(B0到B7),这些模型在各种规模上代表了效率和准确性的良好组合。这种缩放启发式方法(复合缩放,详情参见Tan和Le,2019)允许以效率为导向的基本模型(B0)在每个尺度上超越其他模型,同时避免了广泛的超参数网格搜索。
模型的最新更新总结可以在这里找到,其中应用了各种增强方案和半监督学习方法来进一步提高模型在ImageNet上的性能。这些模型的扩展可以通过更新权重而无需改变模型架构来使用。
1.2 EfficientNet的B0到B7变体
(如果你只对使用这些模型感兴趣,可以跳过本节中关于“复合缩放”的详细解释)
基于原始论文,人们可能会认为EfficientNet是一个通过任意选择论文中Eq.(3)中的缩放因子来创建的连续模型家族。然而,分辨率、深度和宽度的选择也受到许多因素的限制:
分辨率:分辨率如果不能被8、16等整除,会导致某些层边界附近的零填充,从而浪费计算资源。这尤其适用于模型的较小变体,因此B0和B1的输入分辨率被选为224和240。
深度和宽度:EfficientNet的构建块要求通道大小是8的倍数。
资源限制:当深度和宽度可以继续增加时,内存限制可能会限制分辨率。在这种情况下,增加深度和/或宽度但保持分辨率仍然可以提高性能。
因此,EfficientNet模型的每个变体的深度、宽度和分辨率都是精心挑选的,并已被证明能产生良好的结果,尽管它们可能与复合缩放公式显著不同。因此,Keras实现(详细如下)仅提供这8个模型,B0到B7,而不是允许任意选择宽度/深度/分辨率参数。
1.3 Keras中的EfficientNet实现
自Keras v2.3起,已经内置了EfficientNet B0到B7的实现。要使用EfficientNetB0对ImageNet的1000类图像进行分类,可以运行:
from tensorflow.keras.applications import EfficientNetB0
model = EfficientNetB0(weights='imagenet')
这个模型接受形状为(224, 224, 3)的输入图像,输入数据的范围应该在[0, 255]之间。标准化是模型的一部分。
由于在ImageNet上训练EfficientNet需要大量的资源和一些不属于模型架构本身的技巧,因此Keras实现默认加载了通过AutoAugment训练获得的预训练权重。
对于B0到B7的基础模型,输入形状是不同的。以下是每个模型所需的输入形状列表:
以下是B0到B7基础模型的分辨率的表格翻译:
基础模型 | 分辨率 |
---|---|
EfficientNetB0 | 224 |
EfficientNetB1 | 240 |
EfficientNetB2 | 260 |
EfficientNetB3 | 300 |
EfficientNetB4 | 380 |
EfficientNetB5 | 456 |
EfficientNetB6 | 528 |
EfficientNetB7 | 600 |
当模型用于迁移学习时,Keras实现提供了一个选项来移除顶层:
model = EfficientNetB0(include_top=False, weights='imagenet')
这个选项排除了最后一层的Dense层,该层将倒数第二层的1280个特征转化为对1000个ImageNet类别的预测。通过用自定义层替换顶层,可以在迁移学习的工作流程中将EfficientNet用作特征提取器。
在模型构造函数中另一个值得注意的参数是drop_connect_rate
,它控制用于随机深度的dropout率。这个参数在微调时作为额外正则化的切换器,但不会影响已加载的权重。例如,当需要更强的正则化时,可以尝试:
model = EfficientNetB0(weights='imagenet', drop_connect_rate=0.4)
默认值为0.2 。
2、数据准备
本文将演示将EfficientNetB0用于斯坦福狗数据集。
EfficientNet能够处理广泛的图像分类任务。这使其成为迁移学习的良好模型。作为一个端到端的例子,我们将展示如何在斯坦福狗数据集上使用预训练的EfficientNetB0。
斯坦福狗数据集的下载地址如下:
http://vision.stanford.edu/aditya86/ImageNetDogs/
2.1 设置
import numpy as np
import tensorflow_datasets as tfds
import tensorflow as tf # For tf.data
import matplotlib.pyplot as plt
import keras
from keras import layers
from keras.applications import EfficientNetB0
# IMG_SIZE is determined by EfficientNet model choice
IMG_SIZE = 224
BATCH_SIZE = 64
2.2 加载数据
本文的演示从tensorflow_datasets(以下简称TFDS)加载数据。Stanford Dogs数据集在TFDS中作为stanford_dogs提供。它包含20,580张图像,这些图像属于120个狗品种类别(其中12,000张用于训练,8,580张用于测试)。
只需更改下面的dataset_name
,您还可以尝试将此笔记本用于TFDS中的其他数据集,如cifar10、cifar100、food101等。当图像远小于EfficientNet的输入大小时,我们可以简单地对输入图像进行上采样。Tan和Le在2019年的研究表明,即使输入图像保持较小,增加分辨率的迁移学习结果也会更好。
dataset_name = "stanford_dogs"
(ds_train, ds_test), ds_info = tfds.load(
dataset_name, split=["train", "test"], with_info=True, as_supervised=True
)
NUM_CLASSES = ds_info.features["label"].num_classes
当数据集包含各种大小的图像时,我们需要将它们调整为统一的大小。Stanford Dogs数据集仅包含至少200x200像素大小的图像。在这里,我们将图像调整为EfficientNet所需的输入大小。
ize = (IMG_SIZE, IMG_SIZE)
ds_train = ds_train.map(lambda image, label: (tf.image.resize(image, size), label))
ds_test = ds_test.map(lambda image, label: (tf.image<