首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >转移学习只适用于可训练设置为false的情况。

转移学习只适用于可训练设置为false的情况。
EN

Stack Overflow用户
提问于 2020-04-18 16:54:44
回答 1查看 2.4K关注 0票数 1

我有两个模型初始化如下

代码语言:javascript
复制
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'])

代码语言:javascript
复制
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。不幸的是,可训练设置为true的模型没有学习数据。

当我使用model.fit时

代码语言:javascript
复制
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

在几个时代内,该模型的精度可达65%左右。然而,使用model2,它应该能够做出更好的预测(因为有更多可训练的参数),我得到:

代码语言:javascript
复制
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层的计算梯度在这两种情况下都应该是非常相似的,为什么精度这么低呢?长时间的训练不会有任何改善。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-18 18:40:42

试试这个:

  1. 培训第一个模型,它将trainable设置为False。你不必把它训练到饱和,所以我从你的5个时代开始。
  2. 返回并将所有trainable参数设置为True。然后,根据文件,您可以重建和重新编译模型,以使这些更改生效。
  3. 继续关于重新构建的模型的培训,该模型现在有所有可用于调优的参数。

在传输过程中,学习完全冻结被转移的层以保存它们是非常普遍的。在培训的早期阶段,您的额外层不知道该做什么。这意味着,当它到达传输层时,会产生一个噪音梯度,这将很快“使”它们脱离以前调得很好的重量。

如果把所有的代码放在一起,它看起来会是这样的。

代码语言:javascript
复制
# 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()

您可能需要调整微调阶段的学习速度。这不是必要的开始,只是一些需要记住的事情。

第三种选择是使用区分性学习率,这是由杰里米·霍华德和塞巴斯蒂安·鲁德在ULMFiT纸中提出的。思想是,在传输学习中,你通常希望后面的层比先前的层学习得更快。所以你实际上把学习速度设置为不同层次的不同。library库具有一个PyTorch实现,它通过将模型划分为“层组”并允许为每个层组设置不同的参数来工作。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61292890

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档