使用 VGG16 和 Keras 进行迁移学习2025 年 7 月 3 日 | 阅读 12 分钟 迁移学习是深度学习中一种很好的技术,它将学习解决一个问题的模型重新用作解决类似但不同问题的初始点。它利用了之前训练过的模型的经验,从而实现更快的训练和更高的性能,尤其是在用于训练的数据不充足的情况下。 微调在此概念上进行了扩展,通过调整预训练权重以适应新任务,在新任务上训练预训练模型。当需要训练通常需要大量数据集和大量计算能力的深度神经网络时,微调和迁移学习都非常有用。 深度学习中迁移学习的必要性在以下情况中,迁移学习至关重要: 数据有限 当可用数据不足以从头开始构建深度神经网络时。 时间和资源效率 训练端到端深度模型计算量大且耗时。 性能增强 预训练模型几乎总是效果更好,因为它们从已经学习到的特征而不是随机权重开始。 迁移学习过程迁移学习使得使用预训练模型成为可能,从而在处理不充足数据时最大限度地减少训练时间并最大限度地提高性能。所涉及的常见步骤包括两个方面: 特征提取 在这种情况下,采用固定的特征提取器,即预训练模型。学习到的权重不更新;只有最后一个分类器层在新任务上重新训练。这种方法利用了模型基于大量数据所获得的精细而广泛的特征。 微调 在此步骤中,预训练模型的几个最高层被解冻,然后与新的分类器层一起重新训练。这将使模型能够使其获得的特征适应新任务,这通常会带来改进的性能。 Keras 在 Keras.applications 包中提供了主流预训练模型的使用,例如 VGG16、ResNet50 和 InceptionV3。这些模型适用于特征提取或可以微调以适应任何应用程序,因此,它们为开发人员提供了许多选项来利用深度学习,同时拥有少量数据。 微调模型微调模型是为了修改预训练模型并使其在新特定任务上表现良好。它们通常有以下步骤: 1. 加载预训练模型 它从用大数据(例如图像问题中的 ImageNet)预训练的模型开始。 2. 添加自定义层 在预训练基础上添加新层,以满足新任务的需求(即不同数量的输出类)。 3. 冻结预训练层 暂时冻结原始层,使其权重在训练的第一阶段保持不变。 4. 训练自定义层 只在新数据上训练新添加的层,以学习特定于任务的模式。 5. 解冻部分层 缓慢解冻一个或多个预训练层以进行微调。 6. 以较低的学习率重新训练 以降低的学习率继续训练模型,这表示微小的修改和性能增强,而不会牺牲有用的学习特征。 Keras 中迁移学习和微调的实现分解 Keras 上微调预训练模型的步骤 - 让我们使用 CIFAR-10 数据集和 VGG16 模型来说明如何实现: 步骤 1:加载预处理数据 首先读取 CIFAR-10 数据集,该数据集包含 60,000 张 10 类的彩色图像。预处理涉及将像素值标准化到 [0, 1] 范围,以帮助模型高效训练。此外,类标签将转换为独热编码格式,以对应于分类任务中预期的输出形状。 步骤 2:加载预训练模型并添加自定义层 然后,下载源代码并加载已使用 ImageNet 训练的 VGG16 模型。删除其最终(完全连接)层,因为它们与原始分类问题相关。在预训练基座之上,放置特定层以捕获任务特定模式,例如全局平均池化层和顶部的一个或多个密集层以捕获任务特定模式,以及带有 softmax 激活的最终输出层以对 CIFAR-10 类进行分类。 步骤 3:冻结预训练层 为了开始训练,预训练 VGG16 基座中的所有层都应该冻结。这会抑制它们权重的更新,从而允许模型移植 ImageNet 上的特征。使用合适的优化器(例如 Adam)和损失函数(例如分类交叉熵,通常用于解决多类分类问题)组装模型。 步骤 4:训练自定义层 当基础模型被冻结时,只训练作为自定义层添加的层。除了学习 CIFAR-10 特定表示之外,此步骤还使我们能够记住预训练模型的通用特征。训练多个 epoch,以确保新层开始成功学习。 步骤 5:解冻部分层进行微调 完成原始训练后,可以选择性地解冻预训练模型的一些较高层,使它们更好地适应新任务。此步骤允许微调,在此期间,已冻结(已部分解冻)的层和特定层都使用此步骤进行训练。 步骤 6:重新训练模型 重新拟合模型以降低学习率,以克服微调的不稳定更新。接下来,在少量额外的 epoch 上重新训练整个模型。这将使网络能够磨练学习到的特征,并在提供的新任务上表现更好,同时不会干扰其在初始预训练中学习到的合理特征。 步骤 7:分析和绘制模型图 最后,使用一些验证或测试数据来评估模型的准确性和损失。为了分析训练行为,绘制训练和验证准确性以及损失随 epoch 变化的图表。这些图表可以检测过拟合或欠拟合,甚至可以看到训练中可能需要解决的趋势。 代码 输出 Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 26s 0us/step Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5 58889256/58889256 ━━━━━━━━━━━━━━━━━━━━ 7s 0us/step Epoch 1/5 1563/1563 [==============================] - 785s 501ms/stop - loss: 1.3160 - Accuracy: 0.5367 - val_loss: 1.2178 - val_accuracy: 0.5719 Epoch 2/5 1563/1563 [==============================] - 772s 494ms/stop - loss: 1.1445 - Accuracy: 0.5968 - val_loss: 1.1974 - val_accuracy: 0.5718 Epoch 3/5 1563/1563 [==============================] - 790s 505ms/stop - loss: 1.0635 - Accuracy: 0.6238 - val_loss: 1.1318 - val_accuracy: 0.6046 Epoch 4/5 1563/1563 [==============================] - 787s 503ms/stop - loss: 0.9995 - Accuracy: 0.6483 - val_loss: 1.1179 - val_accuracy: 0.6110 Epoch 5/5 1563/1563 [==============================] - 789s 505ms/stop - loss: 0.9467 - Accuracy: 0.6662 - val_loss: 1.1093 - val_accuracy: 0.6123 Epoch 1/5 1563/1563 [==============================] - 792s 506ms/stop - loss: 0.8030 - Accuracy: 0.7197 - val_loss: 1.0506 - val_accuracy: 0.6385 Epoch 2/5 1563/1563 [==============================] - 769s 492ms/stop - loss: 0.7705 - Accuracy: 0.7323 - val_loss: 1.0459 - val_accuracy: 0.6373 Epoch 3/5 1563/1563 [==============================] - 790s 505ms/stop - loss: 0.7548 - Accuracy: 0.7380 - val_loss: 1.0466 - val_accuracy: 0.6370 Epoch 4/5 1563/1563 [==============================] - 788s 504ms/stop - loss: 0.7410 - Accuracy: 0.7438 - val_loss: 1.0460 - val_accuracy: 0.6413 Epoch 5/5 1563/1563 [==============================] - 790s 506ms/stop - loss: 0.7280 - Accuracy: 0.7494 - val_loss: 1.0453 - val_accuracy: 0.6412 313/313 - 122s - loss: 1.0453 - Accuracy: 0.6412 - 122s/epoch - 390ms/step Validation Accuracy: 0.6412 Validation Loss: 1.0453 预训练模型的使用预训练模型提供了一种通用、强大的方法来开发深度学习应用程序。它们以各种方式使用,其使用方式取决于手头问题的性质以及您的数据与模型最初训练的数据集的相似程度。 一种典型的方法是直接将预训练模型用作分类器。例如,您可以使用在 ImageNet 上训练的预训练模型来分类新照片,而无需进一步训练。这适用于新任务与初始任务相似的情况。 它的另一个应用是作为特征提取器。可以使用通常是输出层之前的最后一个层之一的中间层的传感器输出,并与新的分类器配对和输入,而不是使用模型的最终预测。这将使您能够享受预训练模型学习到的密集和通用属性。 我们应该了解卷积神经网络的功能。前层具有较低级别的特征,例如颜色和边缘。更复杂的模式,如形状的纹理,由中间层捕获。在较低级别,这些信息被组合起来以进行更高级别的预测。您可以根据您的任务与原始任务的相似性选择哪个层的输出来进行特征提取。 在其他情况下,预训练模型本身可以作为特征提取工具。在这种情况下,模型或其组成部分之一提取图像以提供特征向量来训练另一个分类器。 或者,可以将预训练模型或模型的组成部分整合到新的神经网络中。您可以在训练期间冻结预训练层(然后这些层将继续拥有它们所拥有的知识),或者您可以使用较低的学习率进行更新。这种方法使得之前训练的模型可以为学习其他任务提供一个好的起点,后者可以被视为一种权重初始化。 简而言之,预训练模型使用的四个关键方向如下:
这两种方法都有其优点,它们在构建深度学习模型时节省了大量时间和资源。 预训练模型的应用既然我们熟悉了如何在 Keras 中加载预训练模型,那么是时候看看这些模型的一些用例了。 我们将在这些插图中采用 VGG16 模型;然而,它很简单并且具有良好的架构。其简单的架构可以作为演示预训练模型在实际任务中如何有用的完美选择。 示例 1:使用预训练模型进行分类直接利用预训练模型可以将新图像分类为 ImageNet 大型视觉识别挑战 (ILSVRC) 的 1,000 个类别之一。在此示例中,我们展示了如何将 VGG16 模型应用于图像。 步骤 1:加载和预处理图像 第一步是加载图片,然后将其大小调整为所需的 224x224 像素输入尺寸。然后将此图像转换为 NumPy 数组并重塑以具有批量维度(因为模型需要一批图像作为输入)。最后但同样重要的是,对图像进行预处理以符合 VGG16 所需的格式。 步骤 2:加载模型并进行预测 此时,加载预训练的 ImageNet 权重 VGG16 模型并预测图像的类别概率。并解码主要的预测标签。 输出 Doberman (33.59%) 这意味着模型估计图像很可能是一只杜宾犬,准确率约为 33.59%。这种基本但强大的方法能够通过模型在训练大规模数据集期间获得的深度知识快速分类图像。 示例 2:使用预训练模型处理器进行特征化还可以将预训练模型用作独立的特征提取器,其中将图像输入模型,结果可以被视为一组数字,这些数字表征了图像最显著的特征。它们反过来可以作为新机器学习或深度学习模型的输入。 一个例子是 VGG16 模型末尾附近的完全连接层,它生成高层输入图像的特征表示。我们可以删除最后一个输出层(这是一个进行分类的层),并将它前面的层(具有 4,096 个单元的层)作为我们的输出。该层具有关于图像的丰富特征集,并且该层可以完美地适应图像分类或对象检测等新任务。 步骤 1:准备图像 与分类情况一样,首先加载图像并将其尺寸更改为 224x224 像素,以及与 VGG16 模型兼容的格式。 步骤 2:修改模型 加载完整的 VGG16 模型并剥离最后一个 softmax 分类层。倒数第二个完全连接层将是新的输出层,它将召回特征向量。 输出 (1, 4096) 这意味着给定图像具有模型获得的 4,096 个特征向量。这些特征可以存储(例如以 .pkl 文件的形式),然后用作另一个深度学习模型的输入;换句话说,这些特征可以在深度学习中轻松重用,而无需再次训练模型。 示例 3:在新模型中使用预训练模型作为特征提取器预训练模型甚至可以作为特征提取器整合到新模型中。可以使用预训练架构(例如 VGG16)中的部分或全部层。然后,可以在顶部构建一些自定义层,从而创建一个特定于任务的新模型。 步骤 1:导入预训练模型 要以未训练的形式加载 VGG16 模型,即没有最终分类层的模型,您需要使用参数 include_top 为 False。这为您提供了一个卷积基座,它能够从输入图像中提取丰富的特征。此外,您可以根据新数据集定义输入大小。例如: 步骤 2:新层 加载基础模型后,可以通过 Keras 函数式 API 添加新层。您通常会展平输出并合并适合您的分类问题的密集层。 但是,您可以使用全局平均池化来替换展平,具体取决于用例。比较两种策略的性能。 步骤 3:模型训练 默认情况下,原始 VGG16 层和您的层都是可训练的。现在,您可以在数据上训练模型。 输出 flatten_1 (Flatten) (None, 41472) dense_1 (Dense) (None, 1024) dense_2 (Dense) (None, 10) Total params: 57,193,290 Trainable params: 57,193,290 下一主题Bagging 机器学习 |
我们请求您订阅我们的新闻通讯以获取最新更新。