使用 Resnet50 进行迁移学习的 Keras 模型

2025 年 7 月 22 日 | 阅读 8 分钟

迁移学习是一种机器学习框架,其中一个用于解决某个任务的预训练模型被应用于解决一个相关的任务。

在深度学习中,这意味着在一个海量数据上对一个神经网络模型进行训练以解决一个问题,然后重用部分已训练好的模型,通常是一个或多个层,来解决另一个相关的问题。这种方法可以大大缩短训练时间并提高模型在新任务上的性能。

迁移的层仅用作初始状态,其权重在训练新问题过程中保持不变或进行调整。当原始任务(例如,波兰共和国、WikiHalo)接触到大量标记数据以改进对新任务的学习时,由于两个挑战之间存在结构上的相似性,数据受限的情况会特别有效。

迁移学习中的图像识别

图像识别是迁移学习最常见的应用,在图像识别领域,作为 ImageNet 大型视觉识别挑战赛(ILSVRC)的一部分,强大的模型已经被训练和测试。

该竞赛通常被称为 ImageNet 或 ImageNet 竞赛,暗示着其在卷积神经网络(CNN)架构和训练方法研究中的核心作用。该竞赛中表现最佳的模型大多已在开放许可下公开,它们应该是用作计算机视觉任务中迁移学习源的理想选择。

这些预训练模型的重要性体现在几个方面:

学习到的特征表示

这些模型在超过一百万张分布在 1,000 个类别中的图像上进行了训练,因此它们已经获得了识别照片中有用且可泛化的特征的能力,包括边缘、纹理和形状。

高精度

这些模型可以被认为是图像分类的前沿,并且在它们被创建来完成的任务上表现出色。

可访问性

预训练权重可通过流行的 深度学习 库提供的简单 API 免费下载,以便在自定义应用程序中轻松集成和使用。

预训练模型的使用和预训练模型是什么?

预训练模型为许多深度学习应用提供了通用且通用的初始化点,它们的应用仅受限于您的想象力。

一个简单的解决方案是直接使用预训练模型,例如,将其嵌入到应用程序中并直接应用于新图像。

另一个典型的应用是特征提取。这种方法的思想是重用模型的某个层的输出来作为新分类器的输入,而不是模型的最终预测。这种做法基于这样一个事实:

  • 最简单的视觉模式,如边缘和纹理,是在早期卷积层中学习到的。
  • 中间层通过组合更简单的模式来识别更复杂的模式。
  • 这种解释,在特定上下文中,受限于特定层,取决于原始分类问题(例如,ImageNet)。

因此,您将用于提取特征的层应该对应于新任务与原始任务的相似性。如果新任务与 ImageNet 分类完全不同,则最好使用早期层提取特征。如果任务非常相似,您可以使用更多层,甚至可以是在输出分类之前的最后一个全连接层的输出。

使用预训练模型主要有两种方式:

  1. 独立特征提取器: 模型(或其一部分)被独立使用,将图像转换为特征向量。然后将这些向量作为新机器学习模型的输入。
  2. 灵活性: 将预训练模型插入到新网络中。您有两个选择:
    • 冻结层: 预训练的层在训练期间将保持不变。这会加快训练速度并避免过拟合。
    • 微调(权重初始化): 现有权重与新权重一起进行训练,通常以较低的学习率进行训练。这使得模型能够相对快速地迁移到新任务,并保留从初始训练中有用地获取的知识。

迁移学习模型

几款性能最佳的深度学习模型被引入图像识别领域,它们为众多计算机视觉应用中的迁移学习奠定了坚实的基础。最受欢迎的包括:

  • VGG(例如 VGG16、VGG19)
  • GoogLeNet 模型(例如 InceptionV3)
  • ResNet(例如 RESN50)

这些模型之所以受欢迎,不仅因为它们的性能,还因为它们带来了一些特殊的架构创新:

  • VGG: 提出了统一且极简的层架构。
  • GoogLeNet: 引入了多尺度处理的 Inception 块。
  • ResNet: 添加了残差连接,以实现更深的模型。

使用 Keras 预训练模型

Keras 提供了 Applications API,可以方便地访问这些和其他预训练模型。这些模型可能已经加载了预训练权重,也可能没有,输入数据可以根据预处理函数进行处理。

Keras Applications API 的重要功能

1. 加载预训练模型

当您第一次加载带有预训练权重的模型时,Keras 会获取权重,然后将它们本地缓存到 .keras/models/。在将来的运行中,它们将被重新使用。

2. 自定义公式

如果 include_top=False,可以使用 input_tensor 参数更改模型输入的尺寸。

3. 全局池化

您可以添加全局平均池化或最大池化,将最终的卷积特征图展平为 1D 特征向量。

4. 图像预处理

每个模型都要求以特定方式对用作输入的图像进行投影。使用相应模型模块的 preprocess-input() 函数。

5. 从头开始训练

如果您希望使用模型架构,但不想加载预训练权重,而是希望在您自己的数据上重新训练模型。

加载和使用 ResNet50 预训练模型

在 Keras 中导入 ResNet50 模型

ImageNet,一个包含 10,000 个类别(120 万张图像)的数据集,模型已在该数据集上进行了预训练。

输出

Model: "resnet50"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 conv1_pad (ZeroPadding2D)      (None, 230, 230, 3)  0           []                               
 conv1_conv (Conv2D)            (None, 112, 112, 64) 9472        ['conv1_pad[0][0]']              
 conv1_bn (BatchNormalization)  (None, 112, 112, 64) 256         ['conv1_conv[0][0]']             
 conv1_relu (Activation)        (None, 112, 112, 64) 0           ['conv1_bn[0][0]']               
 ...
 avg_pool (GlobalAveragePooling2D) (None, 2048)      0           ['conv5_block3_out[0][0]']       
 predictions (Dense)            (None, 1000)         2049000     ['avg_pool[0][0]']               
==================================================================================================
Total params: 25,636,712
Trainable params: 25,583,592
Non-trainable params: 53,120

使用 ResNet50 进行预测

现在是时候在示例图像上测试模型了。

输出

1. African_elephant (89.32%)
2. tusker (10.45%)
3. Indian_elephant (0.21%)

预训练模型的使用场景

在介绍了如何在 Keras 中加载预训练模型后,现在是时候讨论这些模型的实际应用了。

在这些演示中,我们将重点介绍 ResNet50 模型。它是一个非常流行的架构,同时又非常强大且易于理解,因此是学习和实验的绝佳架构。

1. ResNet50 分类器

相同的模型可以直接应用于将新图像分类到 ImageNet 大型视觉识别挑战赛(ILSVRC)使用的 1,000 个类别中的任何一个。在给定的示例中,我们将使用 ResNet50 模型对一张照片进行分类。

输出

Doberman (35.72%) 

2. 特征提取器(独立预处理器)ResNet50

可以使用预训练的 ResNet50 模型来提取有意义的特征。这些特征本质上是一组数字向量,以高级方式表示图像,并可用作训练另一个模型(例如,用于执行聚类任务的自定义分类器)的输入。

输出

(1, 2048) 

3. 使用 ResNet 作为新模型的特征提取器进行领域自适应

预训练的 ResNet50 模型可以包含在某些新的神经网络结构中,在那里它可以充当特征提取器。之后,可以为新任务(例如,分类为 10 个类别)添加自定义分类器层。

输出

conv5_block3_out (Activation)   (None, 10, 10, 2048)
flatten (Flatten)               (None, 204800)        0
dense (Dense)                   (None, 1024)          209717248
dense_1 (Dense)                 (None, 10)            10250
Total params: ~233 million
Trainable params: ~233 million
Non-trainable params: 0