使用PyTorch进行迁移学习的实用指南

在本文中,我们将学习使用一种称为迁移学习的技术将预训练模型适应于自定义分类任务我们将使用PyTorch演示图像分类任务,并比较在3个预训练模型Vgg16、ResNet50和ResNet152上的迁移学习

与Naresh和Gaurav共同撰写。

本文将涵盖迁移学习的什么,为什么以及如何。

  • 什么是迁移学习
  • 为什么要使用迁移学习
  • 如何在真实分类任务中使用迁移学习

具体而言,我们将涵盖迁移学习的以下方面。

  • 迁移学习思想背后的动机及其好处。
  • 建立基础模型选择的直觉。(notebook)
  • 讨论不同选择及其权衡。
  • 使用PyTorch实现图像分类任务。(notebook)
  • 各种基础模型的性能比较。
  • 了解更多关于迁移学习和当前技术水平的资源

迁移学习是一个庞大且不断发展的领域,本文只涵盖了其中的一些方面。然而,有许多深度学习在线社区讨论迁移学习。例如,这里有一篇很好的文章介绍了如何利用迁移学习达到比从头开始训练模型更高的基准。

目标读者和先决条件

  • 您熟悉基本的机器学习(ML)概念,例如定义和训练分类模型
  • 您熟悉PyTorch和torchvision

在下一部分中,我们将正式介绍迁移学习,并通过示例进行解释。

什么是迁移学习?

从这个页面,

“迁移学习是一种机器学习方法,其中为一项任务开发的模型被重用作第二项任务上模型的起点。”

深度学习模型是一组由权重组成的网络,这些权重在训练过程中使用损失函数进行优化。网络的权重通常在训练过程开始之前随机初始化。在迁移学习中,我们使用已经在相关任务上进行了训练的预训练模型。这为我们提供了一组初始权重,这些权重很可能比随机初始化的权重表现更好。我们进一步为我们特定的任务优化预训练的权重。

Jeremy Howard(来自fast.ai)说。

“在任何情况下,您都应该以预训练的模型开始您的神经网络训练,并进行微调。您真的不想从随机权重开始,因为那意味着您正在使用一个根本不知道如何做任何事情的模型!通过预训练,您可以使用比从头开始少1000倍的数据。”

下面,我们将看到如何将迁移学习的概念视为与人类相关。

迁移学习的人类类比

  • 模型训练:孩子出生后,需要一段时间才能学会站立、平衡和行走。在此期间,他们经历了建立身体肌肉和大脑学习理解和内化站立、平衡和行走技能的阶段。他们经历了多次尝试,有些成功,有些失败,才达到了能够以某种程度的一致性站立、平衡和行走的阶段。这类似于训练深度学习模型,当它在训练该任务时需要很长时间(训练时期)来学习通用任务(例如将图像分类为1000个ImageNet类之一)。
  • 迁移学习:已经学会走路的孩子会发现学习相关高级技能,如跳跃和奔跑,要容易得多。迁移学习类似于人类学习的这个方面,其中利用已经学会通用技能的预训练模型来有效地训练其他相关任务。

现在,我们已经建立了对迁移学习的直观理解和与人类学习的比拟,让我们看一下为什么要在ML模型中使用迁移学习。

我为什么要使用迁移学习?

许多视觉AI任务,例如图像分类、图像分割、物体定位或检测,仅在它们分类、分割或检测的特定对象方面有所不同。在这些任务上训练的模型已经学会了它们训练数据集中对象的特征。因此,它们可以轻松地适应相关任务。例如,训练用于识别图像中汽车存在的模型可以被微调以识别猫或狗。

迁移学习的主要优点在于能够帮助你在任务中取得更好的准确性。我们可以将其优点分解如下:

  • 训练效率:当你使用已经学习了数据的通用特征的预训练模型时,你只需要对模型进行微调以适应你的具体任务,这可以更快地完成(即使用更少的训练周期)。
  • 模型准确性:使用迁移学习可以让你相比使用相同数量的资源从头开始训练模型获得显著的性能提升。不过,选择适合你特定任务的预训练模型是很重要的。
  • 训练数据大小:由于预训练模型已经学习了很多与你的任务特定特征重叠的特征,你可以使用更少的领域特定数据来训练预训练模型。如果你的特定任务没有那么多有标签数据,这是很有用的。

那么,在实践中我们如何进行迁移学习呢?下一节将在 PyTorch 中实现迁移学习,以进行花卉分类任务。

使用 PyTorch 进行迁移学习

要使用 PyTorch 进行迁移学习,我们首先需要选择一个数据集和一个预训练的视觉模型,用于图像分类。本文重点介绍使用 torch-vision(与 PyTorch 一起使用的领域库)。让我们了解一下在哪里可以找到这些预训练模型和数据集。

在哪里可以找到用于图像分类的预训练视觉模型?

有很多网站提供高质量的预训练图像分类模型。例如:

  1. Torchvision
  2. PyTorch 图像模型

本文将使用来自 torchvision 的预训练模型。值得学习一些有关这些模型是如何训练的。接下来让我们探讨这个问题!

torchvision 模型预训练在哪些数据集上?

对于涉及图像的视觉任务,torchvision 模型通常在 ImageNet 数据集上进行预训练。由研究人员和模型预训练视觉模型使用的最流行的 ImageNet 子集包含约 1.2M 张图像,跨越 1000 个类别。由于以下原因,ImageNet 分类被用作预训练任务:

  1. 其向研究界提供了可用性
  2. 它包含的图像的广度和多样性
  3. 其被各种研究人员使用,因此使用 Imagenet 1k 分类作为常见基准是有吸引力的

你可以在这个维基百科页面上了解有关 ImageNet 挑战的历史背景和有关完整数据集的信息。

在使用预训练模型时需要考虑法律问题

ImageNet 仅用于非商业研究目的(https://image-net.org/download)。因此,不清楚是否可以合法地将在 ImageNet 上预训练的模型权重用于商业目的。如果你打算这样做,请寻求法律建议。

现在,我们知道了可以在哪里找到我们用于迁移学习的预训练模型,让我们看看我们可以获取用于自定义分类任务的数据集的地方。

数据集:牛津花卉 102

我们将使用 Flowers 102 数据集来说明如何使用 PyTorch 进行迁移学习。我们将训练一个模型,将 Flowers 102 数据集中的图像分类为 102 个类别之一。这是一个多类别(单标签)分类问题,预测的类别是互斥的。我们将利用 Torchvision 来完成这个任务,因为它已经为我们提供了这个数据集。

Flowers 102 数据集来自牛津大学的 Visual Geometry Group。请查看该页面以获取数据集使用的许可条款。

接下来,让我们看一下这个过程涉及的高级步骤。

迁移学习是如何工作的?

图像分类任务的迁移学习可以被视为三个步骤的序列,如图 1 所示。这些步骤如下:

  1. 替换分类器层:在这个阶段,我们需要用我们自己的“分类头”替换我们预训练模型的最后一个“分类头”,并且我们的“分类头”必须有正确数量的输出特征(在这个例子中是102)。
  2. 特征提取:在这个阶段,我们会冻结(使这些层不可训练)模型中除新添加的分类层之外的所有层,并只训练这个新添加的层。
  3. 微调:在这个阶段,我们会释放模型中的一些子集(释放一个层意味着可训练)。在这篇文章中,我们会释放模型中的所有层,并像训练任何机器学习(ML)PyTorch模型一样训练它们。

每个阶段都有很多额外的细节和差异,我们需要了解和关注。我们很快就会深入探讨这些细节。现在,让我们深入研究以下两个关键阶段,即特征提取和微调。

特征提取和微调

您可以在这里找到有关特征提取和微调的更多信息。

  1. 迁移学习中特征提取和微调的区别是什么?
  2. 避免遗忘的学习

下面的图示形象地说明了特征提取和微调。

现在我们已经对自定义分类任务、我们将用于此任务的预训练模型以及迁移学习的工作方式有了很好的理解,让我们看一些执行迁移学习的具体代码。

展示代码

在本节中,您将学习探索性模型分析、初始模型选择、如何定义模型、执行迁移学习步骤(上面讨论过),以及如何防止过度拟合的概念。我们将讨论此数据集的训练/验证/测试分割,并解释结果。

这个实验的完整代码可以在这里找到(使用预训练模型进行Flowers102分类)。探索性模型分析部分在一个单独的笔记本中。

探索性模型分析

与数据科学中的探索性数据分析类似,迁移学习中的第一步是探索性模型分析。在这一步中,我们探索所有可用于图像分类任务的预训练模型,并确定每个模型的结构。

通常,很难知道哪个模型在我们的任务中表现最佳,因此尝试几个看起来很有前途或适用于我们情况的模型并不罕见。在这个假设的情况下,让我们假设模型大小不重要(我们不想在移动设备或这样的边缘设备上部署这些模型)。我们先看一下torchvision中可用的预训练分类模型列表。

classification_models = torchvision.models.list_models(module=torchvision.models)

print(len(classification_models), "classification models:", classification_models)

将打印出

80个分类模型:['alexnet','convnext_base','convnext_large','convnext_small','convnext_tiny','densenet121','densenet161','densenet169','densenet201','efficientnet_b0','efficientnet_b1','efficientnet_b2','efficientnet_b3','efficientnet_b4','efficientnet_b5','efficientnet_b6','efficientnet_b7','efficientnet_v2_l','efficientnet_v2_m','efficientnet_v2_s','googlenet','inception_v3','maxvit_t','mnasnet0_5','mnasnet0_75','mnasnet1_0','mnasnet1_3','mobilenet_v2','mobilenet_v3_large','mobilenet_v3_small','regnet_x_16gf','regnet_x_1_6gf','regnet_x_32gf','regnet_x_3_2gf','regnet_x_400mf','regnet_x_800mf','regnet_x_8gf','regnet_y_128gf','regnet_y_16gf','regnet_y_1_6gf','regnet_y_32gf','regnet_y_3_2gf','regnet_y_400mf','regnet_y_800mf','regnet_y_8gf','resnet101','resnet152','resnet18','resnet34','resnet50','resnext101_32x8d','resnext101_64x4d','resnext50_32x4d','shufflenet_v2_x0_5','shufflenet_v2_x1_0','shufflenet_v2_x1_5','shufflenet_v2_x2_0','squeezenet1_0','squeezenet1_1','swin_b','swin_s','swin_t','swin_v2_b','swin_v2_s','swin_v2_t','vgg11','vgg11_bn','vgg13','vgg13_bn','vgg16','vgg16_bn','vgg19','vgg19_bn','vit_b_16','vit_b_32','vit_h_14','vit_l_16','vit_l_32','wide_resnet101_2','wide_resnet50_2']

哇!这是一个相当庞大的模型列表可供选择!如果您感到困惑,请不要担心-在下一节中,我们将看看选择执行迁移学习的初始模型时要考虑的因素。

初始模型选择

现在,我们有一个包含80个候选模型的列表可供选择,我们需要将其缩小到少数可以运行实验的模型。预训练模型骨干的选择是一个超参数,我们可以(并且应该)通过运行实验来探索多个选项,以查看哪个效果最好。运行实验是昂贵且耗时的,并且我们不太可能尝试所有模型,这就是为什么我们试图将列表缩小到3-4个模型开始。

我们决定从以下预训练模型骨干开始。

  1. Vgg16:135M参数
  2. ResNet50:23M参数
  3. ResNet152:58M参数

以下是我们选择这3个模型的原因。

  1. 我们不受模型大小或推理延迟的限制,因此我们不需要找到超级高效的模型。如果您想要移动设备的各种视觉模型的比较研究,请阅读题为“移动设备上AI模型和框架的比较和基准”的论文。
  2. 我们选择的模型在视觉ML社区中相当受欢迎,往往是用于分类任务的不错选择。您可以使用这些模型论文的引用计数作为这些模型可能有效的体面代理。但是,请注意潜在的偏见,其中长时间存在的AlexNet等模型的论文会有更多引用,即使默认选择不会使用它们进行任何严肃的分类任务。
  3. 即使在模型架构内部,也往往有许多不同的风味或模型尺寸。例如,EfficientNet被裁剪为B0到B7。有关这些裁剪的详细信息,请参阅特定模型的论文。

torchvision中可用的预训练分类模型的各种论文的引用计数。

  1. Resnet:165k
  2. AlexNet:132k
  3. Vgg16:102k
  4. MobileNet:19k
  5. Vision Transformers:16k
  6. EfficientNet:12k
  7. ShuffleNet:6k

如果您想了解可能影响预训练模型选择的因素的更多信息,请阅读以下文章:

  1. 4个用于计算机视觉的预训练CNN模型与迁移学习
  2. 如何为您的卷积神经网络选择最佳预训练模型?
  3. 代表性深度神经网络架构的基准分析

让我们来看看这些模型的分类头。

vgg16 = torchvision.models.vgg16_bn(weights=None)

resnet50 = torchvision.models.resnet50(weights=None)

resnet152 = torchvision.models.resnet152(weights=None)

print(“vgg16 \n “, vgg16.classifier)

print(“resnet50 \n “, resnet50.fc)

print(“resnet152 \n “, resnet152.fc)

vgg16

Sequential(

(0): Linear(in_features=25088, out_features=4096, bias=True)

(1): ReLU(inplace=True)

(2): Dropout(p=0.5, inplace=False)

(3): Linear(in_features=4096, out_features=4096, bias=True)

(4): ReLU(inplace=True)

(5): Dropout(p=0.5, inplace=False)

(6): Linear(in_features=4096, out_features=1000, bias=True)

)

resnet50

Linear(in_features=2048, out_features=1000, bias=True)

resnet152

Linear(in_features=2048, out_features=1000, bias=True)

您可以在此处找到用于探索模型的完整笔记本。

由于我们将在三个预训练模型上运行实验,并分别对每个模型执行迁移学习,因此让我们定义一些抽象和类,以帮助我们运行和跟踪这些实验。

定义一个 PyTorch 模型来包装预训练模型

为了方便探索,我们将定义一个名为 Flowers102Classifier 的 PyTorch 模型,并在本练习中使用它。我们将逐步向这个类添加功能,直到达到我们的最终目标。可以在这里找到 Flowers 102 分类的迁移学习的完整笔记本。

下面的部分将深入探讨执行迁移学习所需的每个机械步骤。

用新的分类头替换旧的分类头

这些模型的现有分类头在 ImageNet 分类任务上进行了预训练,具有 1000 个输出特征。我们用于花卉分类的自定义任务有 102 个输出特征。因此,我们需要用具有 102 个输出特征的新分类头(层)替换最终的分类头。

我们的类的构造函数将包括使用预训练权重从 torchvision 加载所需的预训练模型的代码,并将分类头替换为 102 个类的自定义分类头。

def __init__(self, backbone, load_pretrained):
    super().__init__()
    assert backbone in backbones
    self.backbone = backbone
    self.pretrained_model = None
    self.classifier_layers = []
    self.new_layers = []

    if backbone == "resnet50":
        if load_pretrained:
            self.pretrained_model = torchvision.models.resnet50(
                weights=torchvision.models.ResNet50_Weights.IMAGENET1K_V2
            )
        else:
            self.pretrained_model = torchvision.models.resnet50(weights=None)
        # end if

        self.classifier_layers = [self.pretrained_model.fc]
        # 用于 Flowers 102 数据集的 102 类分类器替换最终层。
        self.pretrained_model.fc = nn.Linear(
            in_features=2048, out_features=102, bias=True
        )
        self.new_layers = [self.pretrained_model.fc]
    elif backbone == "resnet152":
        if load_pretrained:
            self.pretrained_model = torchvision.models.resnet152(
                weights=torchvision.models.ResNet152_Weights.IMAGENET1K_V2
            )
        else:
            self.pretrained_model = torchvision.models.resnet152(weights=None)
        # end if

        self.classifier_layers = [self.pretrained_model.fc]
        # 用于 Flowers 102 数据集的 102 类分类器替换最终层。
        self.pretrained_model.fc = nn.Linear(
            in_features=2048, out_features=102, bias=True
        )
        self.new_layers = [self.pretrained_model.fc]
    elif backbone == "vgg16":
        if load_pretrained:
            self.pretrained_model = torchvision.models.vgg16_bn(
                weights=torchvision.models.VGG16_BN_Weights.IMAGENET1K_V1
            )
        else:
            self.pretrained_model = torchvision.models.vgg16_bn(weights=None)
        # end if

        self.classifier_layers = [self.pretrained_model.classifier]
        # 用于 Flowers 102 数据集的 102 类分类器替换最终层。
        self.pretrained_model.classifier[6] = nn.Linear(
            in_features=4096, out_features=102, bias=True
        )
        self.new_layers = [self.pretrained_model.classifier[6]]

由于我们将执行特征提取后进行微调,因此我们将新添加的层保存到 self.new_layers 列表中。这将帮助我们根据正在进行的操作设置那些层的权重是否可训练。

现在,我们已经用具有随机初始化权重的新分类头替换了旧的分类头,我们需要训练这些权重,以便模型可以进行准确的预测。这包括特征提取和微调,我们将在下一节中介绍它。

迁移学习(可训练参数和学习率)

迁移学习涉及按特定顺序运行特征提取和微调。让我们更深入地了解为什么它们需要按这种顺序运行以及如何处理各种迁移学习阶段的可训练参数。

特征提取:我们将模型中所有层的权重的 requires_grad 设置为 False,并仅将新添加层的 requires_grad 设置为 True。

我们使用学习率为1e-3的方法,对新层进行16次迭代的训练。这样可以确保新层能够根据网络特征提取器的权重进行调整和适应。重要的是要冻结网络的其余层,只训练新的层,以免使网络忘记已经学到的内容。如果不冻结之前的层,它们最终会被重新训练,使用随机初始化的垃圾权重,这会影响到新分类层所学到的内容。

微调:我们将模型中所有层的权重的requires_grad设置为True。我们使用8次迭代对整个网络进行训练。但是,在这种情况下,我们采用了不同的学习率策略。我们通过降低学习率(LR)来使LR随着向输入层(远离输出分类头)的移动而逐渐减小。我们在向模型向上移动时,通过降低学习率来向模型的初始层逼近,因为这些初始层已经学习了关于图像的基本特征,对于大多数计算机视觉任务是通用的。因此,初始层的学习率非常低,以避免干扰它们已经学到的内容。当我们向下移动模型到达分类头时,模型正在学习特定任务,因此训练后面的层使用更高的学习率是有意义的。在这里,可以采用不同的策略,在我们的案例中,我们使用了2种不同的策略来说明它们的有效性。

  1. VGG16: 对于vgg16网络,我们将LR从1e-4线性降低到LR=1e-7(比分类层低1000倍)。由于在特征提取阶段中有44层,因此每个层被分配一个LR,其值为(1e-7-1e-4)/44=2.3e-6,比前一层低。
  2. ResNet: 对于ResNet(50/152)网络,我们从LR=1e-4开始指数衰减LR。我们将LR每向上移动一层就降低3倍。

下面是fine_tune()函数的代码,用于冻结特征提取和微调的层。

def fine_tune(self, what: FineTuneType):
    # requires_grad参数控制在模型训练期间是否可以训练该参数。
    m = self.pretrained_model
    for p in m.parameters():
        p.requires_grad = False
    if what is FineTuneType.NEW_LAYERS:
        for l in self.new_layers:
            for p in l.parameters():
                p.requires_grad = True
    elif what is FineTuneType.CLASSIFIER:
        for l in self.classifier_layers:
            for p in l.parameters():
                p.requires_grad = True
    else:
        for p in m.parameters():
            p.requires_grad = True

在PyTorch中,为每个层设置不同的学习率的方法是指定需要该学习率的权重,然后将其传递给在迁移学习期间将使用的优化器。在我们的笔记本中,我们使用Adam优化器。下面的get_optimizer_params()方法获取优化器参数,以传递给我们将使用的Adam(或其他)优化器。

def get_optimizer_params(self):
    """此方法仅在模型微调期间使用,当我们需要为模型中的层设置线性或指数衰减学习率(LR)时使用。
    我们将学习率指数衰减,当我们远离最后一个输出层时,将其降低到前一个值的三分之一。
    """
    options = []
    if self.backbone == "vgg16":
        # 对于vgg16,我们从最后一层开始使用学习率为1e-3,然后将学习率降低到第一个卷积层的1e-7。中间的学习率是线性衰减的。
        lr = 0.0001
        options.append(
            {
                "params": self.pretrained_model.classifier.parameters(),
                "lr": lr,
            }
        )
        final_lr = lr / 1000.0
        diff_lr = final_lr - lr
        lr_step = diff_lr / 44.0
        for i in range(43, -1, -1):
            options.append(
                {
                    "params": self.pretrained_model.features[i].parameters(),
                    "lr": lr + lr_step * (44 - i),
                }
            )
        # end for
    elif self.backbone in ["resnet50", "resnet152"]:
        # 对于resnet类模型,我们指数衰减学习率,并将其缩小到每一步的前一个值的三分之一。
        layers = ["conv1", "bn1", "layer1", "layer2", "layer3", "layer4", "fc"]
        lr = 0.0001
        for layer_name in reversed(layers):
            options.append(
                {
                    "params": getattr(self.pretrained_model, layer_name).parameters(),
                    "lr": lr,
                }
            )
            lr = lr / 3.0
        # end for
    # end if
    return options


# end def

代码片段:微调模型时每层使用不同的学习率。

一旦我们有了具有自己学习率的模型参数,我们可以通过一行代码将它们传递给优化器。默认使用 1e-8 的 LR 用于在 get_optimizer_params() 返回的字典中未指定权重的参数。

optimizer = torch.optim.Adam(fc.get_optimizer_params(), lr=1e-8)

代码片段:将带有自己 LR 的参数传递给 Adam 优化器。

现在我们知道了如何执行迁移学习,让我们看看在微调模型之前需要考虑的其他问题。这包括我们需要采取的步骤,以防止过拟合,并选择正确的训练/验证/测试拆分。

防止过拟合

在我们的笔记本中,我们使用以下数据增强技术来防止过拟合,并允许模型学习功能,以便可以对看不见的数据进行预测。

  1. 颜色抖动
  2. 水平翻转
  3. 旋转
  4. 剪切

验证拆分没有应用任何数据增强。

还应该探索权重衰减,这是一种通过减少模型的复杂性来防止过拟合的正则化技术。

训练/验证/测试拆分

Flowers 102 数据集的作者建议训练/验证/测试拆分的大小为 1020/1020/6149。许多作者的做法不同。例如:

  1. 在 ResNet 反击论文中,作者使用训练+验证(2040 张图像)拆分作为训练集,并将测试集作为测试集。不清楚是否有验证拆分。
  2. 在此关于 Flowers 102 分类的文章中,作者使用大小为 6149 的测试拆分作为训练拆分。
  3. 在这个笔记本中,作者使用大小为 6552、818 和 819 的训练/验证/测试拆分。

了解每个作者在做什么的唯一方法是阅读论文或代码。

在我们的笔记本(本文中),我们使用大小为 6149 的拆分作为训练拆分,使用大小为 2040 的拆分作为验证拆分。我们没有使用测试拆分,因为我们并不真正想要竞争。

此时,您应该有能力访问此笔记本,执行上述所有步骤,并将其结果呈现出来供您查看。请随意在 Kaggle 或 Google Colab 上克隆笔记本并在 GPU 上运行它。如果您正在使用 Google Colab,则需要修复下载数据集和预训练模型以及微调模型的最佳权重的某些路径。

接下来,我们将看一下迁移学习实验的结果!

结果

结果有一些共同的主题,我们将在下面探讨。

  1. 仅进行特征提取步骤后,几乎所有网络的准确率在 91% 到 94% 之间。
  2. 几乎所有网络在微调步骤后都表现得非常好,实现了 96+% 的准确率。这表明微调步骤在迁移学习中非常有帮助。

我们的网络中的参数数量有显着差异,vgg16 为 135M 参数,ResNet50 为 23M 参数,ResNet152 为 58M 参数。这表明我们可能可以找到一个具有可比准确性和性能的更小的网络。

垂直红线表示我们从特征提取(16 个 epoch)切换到微调(8 个 epoch)的时期。您可以看到当我们切换到微调时,所有网络都显示了准确度的提高。这表明在特征提取后进行微调非常有效。

文章摘要

  1. 迁移学习是一种节俭而有效的方法,通过在类似但不相关的任务上使用预训练网络来训练您的网络
  2. Torchvision 提供了许多在 ImageNet 上预训练的模型供研究人员在迁移学习期间使用
  3. 在生产中使用预训练模型时要小心,以确保您不违反任何许可证或用于预训练模型的数据集的使用条款
  4. 迁移学习包括特征提取和微调,必须按特定顺序执行

想学更多吗?

现在我们已经知道了如何从预先在不同数据集上进行预训练的模型开始执行自定义任务的迁移学习,如果我们能避免使用单独的数据集进行预训练(预设任务),并使用我们自己的数据集来实现这一目的,那不是很好吗?结果表明,这是可行的!

最近,研究人员和从业者一直在使用自我监督学习作为一种进行模型预训练(学习预设任务)的方法,这种方法的好处是在训练模型时使用与目标数据集相同的分布,该模型应该在生产中进行消耗。如果您有兴趣了解更多关于自我监督预训练和分层预训练的内容,请参阅2021年的论文《自我监督预训练改进了自我监督预训练》。

如果您拥有特定任务的数据,则可以使用自我监督学习预训练您的模型,并不必担心使用ImageNet数据集进行预训练步骤,因此在使用ImageNet数据集方面保持清晰。

术语表

  • 分类头 :在PyTorch中,这是一个nn.Linear层,将众多输入特征映射到一组输出特征
  • 冻结权重 :使权重不可训练。在PyTorch中,通过设置requires_grad=False来完成
  • 解冻(或解冻)权重 :使权重可训练。在PyTorch中,通过设置requires_grad=True来完成
  • 自我监督学习 :一种训练ML模型的方法,使其可以在没有任何人工生成标签的数据上进行训练。标签可以是自动生成或机器生成的

参考文献和进一步阅读

  • 有关在PyTorch中微调预先训练模型的思路
  • 深入学习:微调
  • 自我监督学习和计算机视觉
  • 深度学习的迁移学习简介
  • 笔记本:探索性模型分析
  • 笔记本:使用迁移学习进行花卉102分类

Dhruv Matani是一位机器学习爱好者,专注于PyTorch、CNN、视觉、语音和文本AI。他是机器学习和数据基础设施的专家,作者在Efficient Deep Learning Book(https://efficientdlbook.com/)上撰写了一章关于高效PyTorch的内容。他的观点是他自己的观点,而不是他任何雇主的观点;过去、现在或未来。

Naresh对神经网络的“学习”方面非常感兴趣。他的工作集中在神经网络体系结构及其如何通过简单的拓扑变化增强其学习能力。在他长达十年的职业生涯中,他曾在微软、亚马逊和Citrix担任工程角色。他在深度学习领域已经有6-7年的经验。您可以在小猪AI(https://medium.com/u/1e659a80cffd)上找到他。

Gaurav是Google Research的高级软件工程师,他领导的研究项目旨在优化大型机器学习模型,以便在从微小的微控制器到基于Tensor Processing Unit(TPU)的服务器等各种设备上进行有效的训练和推理。他的工作对YouTube、Cloud、Ads、Chrome等超过10亿活跃用户产生了积极的影响。他还是Manning Publication即将出版的一本关于高效机器学习的书籍的作者。在加入Google之前,Gaurav在Facebook工作了4.5年,并为Facebook的搜索系统和大型分布式数据库做出了重大贡献。他拥有纽约州立大学计算机科学硕士学位。