Keras深度学习框架第十二讲:迁移学习与微调

1、绪论

1.1 迁移学习的定义

深度学习的迁移学习是一种技术,它允许将一个任务上学到的知识或模型应用到另一个任务中。其核心思想是将一种任务中学习的特征或模型权重用于另一种任务,以实现知识的迁移和模型的优化。

迁移学习在深度学习中具有广泛的应用,特别是在数据量较少的情况下。通过利用在源领域(source domain)上学习到的知识,迁移学习可以帮助目标领域(target domain)上的学习任务。迁移学习的主要类型包括特征提取、微调和共享参数。

  • 特征提取:将源领域上训练好的模型的中间层输出作为特征提取器,然后在目标领域上训练新的分类器。这种方法允许我们重用已训练模型中的特征表示,以加速新任务的训练过程。
  • 微调(Fine-tuning):将源领域上训练好的模型的参数作为初始参数,在目标领域上继续训练模型。微调可以进一步调整模型的参数以适应新任务,从而提高模型在新任务上的性能。
  • 共享参数:将源领域和目标领域的数据同时输入模型,共享部分参数进行训练。这种方法允许模型同时学习两个任务的知识,并通过共享参数来实现知识的迁移。

迁移学习在深度学习中的应用场景非常广泛,包括图像分类、自然语言处理、语音识别和游戏AI等领域。通过迁移学习,我们可以减少训练数据量、节省训练时间并提高模型性能。

例如,在图像分类任务中,当源领域上有大量标注数据而目标领域上的数据较少时,我们可以使用迁移学习将源领域上的模型应用到目标领域上,从而提升目标领域的分类性能。同样地,在自然语言处理任务中,迁移学习也可以帮助我们利用在大规模语料库上预训练的模型来加速新任务的训练过程并提高性能。

1.2 迁移学习的流程

迁移学习通常用于那些数据集太小、无法从头开始训练一个完整模型的任务。

在深度学习的背景下,迁移学习的最常见形式是以下工作流程:

  • 从一个预先训练好的模型中取出层。
  • 冻结这些层,以避免在未来的训练轮次中破坏它们所包含的信息。
  • 在冻结的层之上添加一些新的、可训练的层。这些新层将学习如何将旧的特征转化为新数据集上的预测。
  • 在你的数据集上训练新添加的层。
  • 最后,一个可选的步骤是微调,它包括解冻你上面得到的整个模型(或其部分),并使用非常小的学习率在新数据上重新训练它。这可以通过逐步调整预训练特征以适应新数据来实现有意义的改进。

1.3 本文的主要内容

首先,我们将详细介绍Keras的可训练API,它是大多数迁移学习和微调工作流程的基础。

然后,我们将通过在一个预训练于ImageNet数据集的模型上,并在Kaggle的“猫狗分类”数据集上重新训练它来展示典型的工作流程。

1.4 可训练属性与不可训练属性

层和模型具有三个权重属性:

  • weights 是层中所有权重变量的列表。
  • trainable_weights 是那些意图在训练过程中通过梯度下降来更新以最小化损失的权重列表。
  • non_trainable_weights 是那些不打算训练的权重列表。通常,它们在模型的前向传播过程中被模型更新。

Dense 层是深度学习模型中的一个常见层,用于实现全连接层(也称为密集层或线性层)。它包含两个主要的可训练权重:

  • kernel:这是一个二维数组(或称为矩阵),用于存储该层中神经元的权重。这些权重在训练过程中通过反向传播和梯度下降来更新,以最小化损失函数。
  • bias:这是一个一维数组,用于存储每个神经元的偏置项。同样,这些偏置项也在训练过程中通过梯度下降来更新。

示例:Dense 层有两个可训练的权重(kernel(核)和 bias(偏置))。

layer = keras.layers.Dense(3)
layer.build((None, 4))  # Create the weights

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 2
trainable_weights: 2
non_trainable_weights: 0

在深度学习中,大多数层的权重默认都是可训练的(trainable),这意味着在训练过程中,这些权重会通过梯度下降等优化算法进行更新,以最小化损失函数。然而,也有一些特殊的层,如BatchNormalization层,它包含非训练权重(non-trainable weights)。

BatchNormalization层在训练过程中执行两个主要操作:标准化(normalization)和缩放/平移(scaling/shifting)。标准化是通过对输入数据进行变换,使其具有零均值和单位方差来实现的。这个变换的参数(即均值和方差)是在每个训练批次上计算的,并用于标准化当前批次的输入。这些均值和方差在训练过程中是不断更新的,但它们不是通过梯度下降来优化的,因此它们被视为非训练权重。

另一方面,BatchNormalization层还有另外两个可训练权重:缩放因子(gamma)和平移项(beta)。这些权重在训练过程中通过梯度下降进行更新,用于控制标准化后的数据应该如何被缩放和平移。这些权重对于调整模型的输出分布非常重要,可以帮助模型更好地拟合训练数据。

因此,BatchNormalization层通常包含两个可训练权重(gamma和beta)和两个非训练权重(输入数据的均值和方差)。

如果你想在自己的自定义层中使用非训练权重,你可以通过在定义层时创建tf.Variable对象并设置其trainable属性为False来实现。这样,这些权重就不会在训练过程中被优化算法更新。但是,请注意,在大多数情况下,你不需要直接使用非训练权重,除非你的层具有类似于BatchNormalization层的特殊需求。

layer = keras.layers.BatchNormalization()
layer.build((None, 4))  # Create the weights

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 4
trainable_weights: 2
non_trainable_weights: 2

可训练属性设置为不可训练
将trainable设置为False

layer = keras.layers.Dense(3)
layer.build((None, 4))  # Create the weights
layer.trainable = False  # Freeze the layer

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 2
trainable_weights: 0
non_trainable_weights: 2

不可训练属性的更新

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MUKAMO

你的鼓励是我们创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值