是否可以从中间层开始训练 CNN(通常和 Keras)?
Is it possible to train a CNN starting at an intermediate layer (in general and in Keras)?
我正在使用 mobilenet v2 在我的图像上训练模型。除了几层之外,我已经冻结了所有层,然后添加了额外的层用于训练。我希望能够从中间层而不是从头开始训练。我的问题:
- 是否可以提供最后一个冻结层的输出作为
训练输入(它将是 (?, 7,7,1280) 的张量)?
- 如何指定训练从第一个可训练的开始
(非冻结)层?在这种情况下,mbnetv2_conv.layer[153].
- 在这种情况下 y_train 是什么?我不太明白y_train
在训练过程中被使用——一般来说,什么时候
CNN 参考 y_train?
加载 mobilenet v2
image_size = 224
mbnetv2_conv = MobileNetV2(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))
# Freeze all layers except the last 3 layers
for layer in mbnetv2_conv.layers[:-3]:
layer.trainable = False
# Create the model
model = models.Sequential()
model.add(mbnetv2_conv)
model.add(layers.Flatten())
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(3, activation='softmax'))
model.summary()
# Build an array (?,224,224,3) from images
x_train = np.array(all_images)
# Get layer output
from keras import backend as K
get_last_frozen_layer_output = K.function([mbnetv2_conv.layers[0].input],
[mbnetv2_conv.layers[152].output])
last_frozen_layer_output = get_last_frozen_layer_output([x_train])[0]
# Compile the model
from keras.optimizers import SGD
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['acc'])
# how to train from a specific layer and what should y_train be?
model.fit(last_frozen_layer_output, y_train, batch_size=2, epochs=10)
是的,你可以。两种不同的方式。
首先,困难的方法让您构建两个新模型,一个包含所有冻结层,一个包含所有可训练层。将 Flatten() 层添加到 frozen-layers-only 模型。并且您将逐层复制 mobilenet v2 中的权重以填充 frozen-layers-only 模型的权重。然后,您将通过 frozen-layers-only 模型 运行 输入图像,以 CSV 或 pickle 形式将输出保存到磁盘。现在这是您的 trainable-layers 模型的输入,您可以像上面那样使用 model.fit() 命令对其进行训练。完成训练后保存重量。然后你将不得不用两组层构建原始模型,并将权重加载到每一层中,并保存整个过程。大功告成!
但是,更简单的方法是将模型的权重与架构分开保存:
model.save_weights(filename)
然后在将其添加到新的空模型之前修改 MobileNetV2 中层的 layer.trainable 属性:
mbnetv2_conv = MobileNetV2(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))
for layer in mbnetv2_conv.layers[:153]:
layer.trainable = False
model = models.Sequential()
model.add(mbnetv2_conv)
然后用
重新加载权重
newmodel.load_weights(filename)
这让您可以调整 mbnetv2_conv 模型中的哪些层将在运行中训练,然后只需调用 model.fit() 即可继续训练。
我正在使用 mobilenet v2 在我的图像上训练模型。除了几层之外,我已经冻结了所有层,然后添加了额外的层用于训练。我希望能够从中间层而不是从头开始训练。我的问题:
- 是否可以提供最后一个冻结层的输出作为 训练输入(它将是 (?, 7,7,1280) 的张量)?
- 如何指定训练从第一个可训练的开始 (非冻结)层?在这种情况下,mbnetv2_conv.layer[153].
- 在这种情况下 y_train 是什么?我不太明白y_train 在训练过程中被使用——一般来说,什么时候 CNN 参考 y_train?
加载 mobilenet v2
image_size = 224
mbnetv2_conv = MobileNetV2(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))
# Freeze all layers except the last 3 layers
for layer in mbnetv2_conv.layers[:-3]:
layer.trainable = False
# Create the model
model = models.Sequential()
model.add(mbnetv2_conv)
model.add(layers.Flatten())
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(3, activation='softmax'))
model.summary()
# Build an array (?,224,224,3) from images
x_train = np.array(all_images)
# Get layer output
from keras import backend as K
get_last_frozen_layer_output = K.function([mbnetv2_conv.layers[0].input],
[mbnetv2_conv.layers[152].output])
last_frozen_layer_output = get_last_frozen_layer_output([x_train])[0]
# Compile the model
from keras.optimizers import SGD
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['acc'])
# how to train from a specific layer and what should y_train be?
model.fit(last_frozen_layer_output, y_train, batch_size=2, epochs=10)
是的,你可以。两种不同的方式。
首先,困难的方法让您构建两个新模型,一个包含所有冻结层,一个包含所有可训练层。将 Flatten() 层添加到 frozen-layers-only 模型。并且您将逐层复制 mobilenet v2 中的权重以填充 frozen-layers-only 模型的权重。然后,您将通过 frozen-layers-only 模型 运行 输入图像,以 CSV 或 pickle 形式将输出保存到磁盘。现在这是您的 trainable-layers 模型的输入,您可以像上面那样使用 model.fit() 命令对其进行训练。完成训练后保存重量。然后你将不得不用两组层构建原始模型,并将权重加载到每一层中,并保存整个过程。大功告成!
但是,更简单的方法是将模型的权重与架构分开保存:
model.save_weights(filename)
然后在将其添加到新的空模型之前修改 MobileNetV2 中层的 layer.trainable 属性:
mbnetv2_conv = MobileNetV2(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))
for layer in mbnetv2_conv.layers[:153]:
layer.trainable = False
model = models.Sequential()
model.add(mbnetv2_conv)
然后用
重新加载权重newmodel.load_weights(filename)
这让您可以调整 mbnetv2_conv 模型中的哪些层将在运行中训练,然后只需调用 model.fit() 即可继续训练。