【问题标题】:Transfer learning only works with trainable set to false迁移学习仅适用于可训练设置为 false
【发布时间】:2020-08-01 05:02:27
【问题描述】:

我有两个这样初始化的模型

vgg19 = keras.applications.vgg19.VGG19(
  weights='imagenet',
  include_top=False,
  input_shape=(img_height, img_width, img_channels))

for layer in vgg19.layers:
  layer.trainable = False

model = Sequential(layers=vgg19.layers)
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dense(512, activation='relu'))
model.add(Dense(10, activation='softmax'))

opt = Adam(learning_rate=0.001, beta_1=0.9)
model.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'])

vgg19_2 = keras.applications.vgg19.VGG19(
    weights='imagenet',
    include_top=False,
    input_shape=(img_height, img_width, img_channels))

model2 = Sequential(layers=vgg19_2.layers)
model2.add(Dense(1024, activation='relu'))
model2.add(Dense(512, activation='relu'))
model2.add(Dense(10, activation='softmax'))

opt = Adam(learning_rate=0.001, beta_1=0.9)
model2.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'])

换句话说,唯一的区别是第二个模型没有将 vgg19 层的可训练参数设置为 false。不幸的是,将 trainable 设置为 true 的模型无法学习数据。

当我使用 model.fit 我得到

Trainable set to false:
Epoch 1/51
2500/2500 [==============================] - 49s 20ms/step - loss: 1.4319 - accuracy: 0.5466 - val_loss: 1.3951 - val_accuracy: 0.5693
Epoch 2/51
2500/2500 [==============================] - 47s 19ms/step - loss: 1.1508 - accuracy: 0.6009 - val_loss: 0.7832 - val_accuracy: 0.6023
Epoch 3/51
2500/2500 [==============================] - 48s 19ms/step - loss: 1.0816 - accuracy: 0.6256 - val_loss: 0.6782 - val_accuracy: 0.6153
Epoch 4/51
2500/2500 [==============================] - 47s 19ms/step - loss: 1.0396 - accuracy: 0.6450 - val_loss: 1.3045 - val_accuracy: 0.6103

该模型在几个 epoch 内训练到大约 65% 的准确度。但是使用 model2 应该能够做出更好的预测(因为有更多可训练的参数)我得到:

Epoch 1/5
2500/2500 [==============================] - 226s 90ms/step - loss: 2.3028 - accuracy: 0.0980 - val_loss: 2.3038 - val_accuracy: 0.1008
Epoch 2/5
2500/2500 [==============================] - 311s 124ms/step - loss: 2.3029 - accuracy: 0.0980 - val_loss: 2.2988 - val_accuracy: 0.1017
Epoch 3/5
2500/2500 [==============================] - 306s 123ms/step - loss: 2.3029 - accuracy: 0.0980 - val_loss: 2.3052 - val_accuracy: 0.0997
Epoch 4/5
2500/2500 [==============================] - 321s 129ms/step - loss: 2.3029 - accuracy: 0.0972 - val_loss: 2.3028 - val_accuracy: 0.0997
Epoch 5/5
2500/2500 [==============================] - 300s 120ms/step - loss: 2.3028 - accuracy: 0.0988 - val_loss: 2.3027 - val_accuracy: 0.1007

当我尝试计算我的数据的权重梯度时,我只得到零。我知道将像 vgg 这样的大神经网络训练到最佳状态可能需要很长时间,但考虑到最后 3 层的计算梯度在两种情况下应该非常相似,为什么精度这么低?训练更多时间并没有改善。

【问题讨论】:

标签: machine-learning keras neural-network transfer-learning vgg-net


【解决方案1】:

试试这个:

  1. 训练第一个模型,将trainable 设置为False。您不必将其训练到饱和,因此我将从您的 5 个 epoch 开始。
  2. 返回并将所有vgg19 参数的trainable 设置为True。然后,per the documentation,您可以重建并重新编译模型以使这些更改生效。
  3. 继续对重建的模型进行训练,该模型现在具有可用于调整的所有参数。

在迁移学习中,为了保留它们而完全冻结迁移层是很常见的。在训练的早期阶段,您的附加层不知道该做什么。这意味着当它到达传输层时会有一个嘈杂的梯度,这将很快将它们从之前调整好的权重中“失谐”。

将它们放在一些代码中,它看起来像这样。

# Original code. Transfer VGG and freeze the weights.
vgg19 = keras.applications.vgg19.VGG19(
  weights='imagenet',
  include_top=False,
  input_shape=(img_height, img_width, img_channels))

for layer in vgg19.layers:
  layer.trainable = False

model = Sequential(layers=vgg19.layers)
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dense(512, activation='relu'))
model.add(Dense(10, activation='softmax'))

opt = Adam(learning_rate=0.001, beta_1=0.9)
model.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'])

model.fit()

# New second stage: unfreeze and continue training.
for layer in vgg19.layers:
  layer.trainable = True

full_model = Sequential(layers=model.layers)
full_model.compile(
    loss='categorical_crossentropy',
    optimizer=opt,
    metrics=['accuracy'])

full_model.fit()

您可能希望调整微调阶段的学习率。开始不是必须的,只是要记住一些事情。


第三种选择是使用判别式学习率,正如 Jeremy Howard 和 Sebastian Ruder 在ULMFiT paper 中介绍的那样。这个想法是,在迁移学习中,您通常希望后面的层比早期的迁移层学习得更快。所以你实际上为不同的层设置了不同的学习率。 fastai 库有a PyTorch implementation,它通过将模型划分为“层组”并为每个组允许不同的参数来工作。

【讨论】:

  • 以学习率=0.001 训练最后​​ 3 层,然后解冻并设置 lr=0.00001 解决了这个问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 2022-09-27
  • 2021-04-17
  • 2018-04-12
  • 2018-11-27
  • 2020-05-21
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
相关资源
最近更新 更多