keras冻结_Keras: model实现固定部分layer,训练部分layer操作

本文介绍了如何在Keras中调整预训练的ResNet50模型,以适应新的分类任务(从1000类到500类)。通过设置模型的trainable属性,只让最后三层参与训练,提高训练效率。方法包括模型拆分和遍历设置trainable属性。同时,强调了避免直接在层构造时设置trainable=False,以及在加载权重时注意by_name=True的重要性。
摘要由CSDN通过智能技术生成

需求:Resnet50做调优训练,将最后分类数目由1000改为500。

问题:网上下载了resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5,更改了Resnet50后,由于所有层均参加训练,导致训练速度慢。实际上只需要训练最后3层,前面的层都不需要训练。

解决办法:

①将模型拆分为两个模型,一个为前面的notop部分,一个为最后三层,然后利用model的trainable属性设置只有后一个model训练,最后将两个模型合并起来。

②不用拆分,遍历模型的所有层,将前面层的trainable设置为False即可。代码如下:

for layer in model.layers[:-3]:

print(layer.trainable)

layer.trainable = False

注意事项:

①尽量不要这样:

layers.Conv2D(filters1, (1, 1), trainable=False)(input_tensor)

因为容易出错。。。

②加载notop参数时注意by_name=True.

补充知识:Keras关于训练冻结部分层

设置冻结层有两种方式。

(不推荐)是在搭建网络时,直接将某层的trainable设置为false,例如:

layers.Conv2D(filters1, (1, 1), trainable=False)(input_tensor)

在网络搭建完成时,遍历model.layer,然后将layer.trainable设置为False:

# 冻结网络倒数的3层

for layer in model.layers[:-3]:

print(layer.trainable)

layer.trainable = False

也可以根据layer.name来确定哪些层需要冻结,例如冻结最后一层和RNN层:

for layer in model.layers:

layerName=str(layer.name)

if layerName.startswith("RNN_") or layerName.startswith("Final_"):

layer.trainable=False

可以在实例化之后将网络层的 trainable 属性设置为 True 或 False。为了使之生效,在修改 trainable 属性之后,需要在模型上调用 compile()。

这是一个例子

x = Input(shape=(32,))

layer = Dense(32)

layer.trainable = False

y = layer(x)

frozen_model = Model(x, y)

# 在下面的模型中,训练期间不会更新层的权重

frozen_model.compile(optimizer='rmsprop', loss='mse')

layer.trainable = True

trainable_model = Model(x, y)

# 使用这个模型,训练期间 `layer` 的权重将被更新

# (这也会影响上面的模型,因为它使用了同一个网络层实例)

trainable_model.compile(optimizer='rmsprop', loss='mse')

frozen_model.fit(data, labels) # 这不会更新 `layer` 的权重

trainable_model.fit(data, labels) # 这会更新 `layer` 的权重

在网络搭建时,可以考虑最后一个分类层命名和分类数量关联,这样当费雷数量方式变化时,model.load_weight(“weight.h5”,by_name=True)不会加载最后一层

以上这篇Keras: model实现固定部分layer,训练部分layer操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持聚米学院。

在上一篇文章中,我们介绍了什么是语义分割以及语义分割的应用场景。本文将带领大家进一步了解如何用Python实现语义分割。 我们将使用Python中的OpenCV和深度学习框架Keras实现语义分割。我们将训练一个卷积神经网络模型,该模型将使用图像作为输入,并将输出像素级别的标签。我们将使用PASCAL VOC 2012数据集来进行训练和测试。 首先,我们需要下载数据集。可以从以下链接下载: http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar 下载完成后,将其解压缩到本地文件夹中。我们将使用其中的训练集和验证集来训练和测试我们的模型。 接下来,我们需要安装所需的Python库。在终端窗口中运行以下命令: ``` pip install opencv-python numpy keras ``` 我们还需要下载一个预训练的VGG16模型,该模型的权重可以从以下链接下载: https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels.h5 下载完成后,将其保存到本地文件夹中。 现在,我们已经准备好开始实现语义分割了。首先,我们需要加载数据集。我们将使用PASCAL VOC 2012数据集中的图像和标签来训练我们的模型。以下是加载数据集的代码: ```python import os import cv2 import numpy as np # 加载训练集 def load_train_data(data_dir): # 加载图像和标签 images_dir = os.path.join(data_dir, 'JPEGImages') labels_dir = os.path.join(data_dir, 'SegmentationClass') image_file_names = os.listdir(images_dir) label_file_names = os.listdir(labels_dir) image_file_names.sort() label_file_names.sort() images = [] labels = [] for image_file_name, label_file_name in zip(image_file_names, label_file_names): if image_file_name[:-4] != label_file_name[:-4]: raise ValueError('Image and label file names do not match.') image_file_path = os.path.join(images_dir, image_file_name) label_file_path = os.path.join(labels_dir, label_file_name) image = cv2.imread(image_file_path) label = cv2.imread(label_file_path, cv2.IMREAD_GRAYSCALE) images.append(image) labels.append(label) return np.array(images), np.array(labels) # 加载验证集 def load_val_data(data_dir): # 加载图像和标签 images_dir = os.path.join(data_dir, 'JPEGImages') labels_dir = os.path.join(data_dir, 'SegmentationClass') image_file_names = os.listdir(images_dir) label_file_names = os.listdir(labels_dir) image_file_names.sort() label_file_names.sort() images = [] labels = [] for image_file_name, label_file_name in zip(image_file_names, label_file_names): if image_file_name[:-4] != label_file_name[:-4]: raise ValueError('Image and label file names do not match.') image_file_path = os.path.join(images_dir, image_file_name) label_file_path = os.path.join(labels_dir, label_file_name) image = cv2.imread(image_file_path) label = cv2.imread(label_file_path, cv2.IMREAD_GRAYSCALE) images.append(image) labels.append(label) return np.array(images), np.array(labels) ``` 接下来,我们需要对数据集进行预处理。我们将使用VGG16模型的预处理函数对图像进行预处理,并将标签转换为one-hot编码。以下是预处理数据集的代码: ```python from keras.applications.vgg16 import preprocess_input from keras.utils import to_categorical # 预处理训练集 def preprocess_train_data(images, labels): # 对图像进行预处理 images = preprocess_input(images) # 将标签转换为one-hot编码 labels = to_categorical(labels) return images, labels # 预处理验证集 def preprocess_val_data(images, labels): # 对图像进行预处理 images = preprocess_input(images) # 将标签转换为one-hot编码 labels = to_categorical(labels) return images, labels ``` 现在,我们已经准备好开始构建我们的模型了。我们将使用VGG16作为我们的基础模型,只需要去掉最后一层全连接层即可。我们将在基础模型之上添加一些卷积层和上采样层来构建我们的语义分割模型。以下是构建模型的代码: ```python from keras.models import Model from keras.layers import Input, Conv2D, Conv2DTranspose # 构建模型 def build_model(input_shape, num_classes): # 加载VGG16模型 base_model = VGG16(input_shape=input_shape, include_top=False) # 取消VGG16模型的最后一层 base_model.layers.pop() # 冻结VGG16模型的所有层 for layer in base_model.layers: layer.trainable = False # 添加卷积层和上采样层 x = base_model.output x = Conv2D(256, (3, 3), activation='relu', padding='same')(x) x = Conv2D(256, (3, 3), activation='relu', padding='same')(x) x = Conv2D(256, (3, 3), activation='relu', padding='same')(x) x = Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(x) x = Conv2D(128, (3, 3), activation='relu', padding='same')(x) x = Conv2D(128, (3, 3), activation='relu', padding='same')(x) x = Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(x) x = Conv2D(64, (3, 3), activation='relu', padding='same')(x) x = Conv2D(64, (3, 3), activation='relu', padding='same')(x) x = Conv2D(num_classes, (1, 1), activation='softmax')(x) # 创建模型 model = Model(inputs=base_model.input, outputs=x) return model ``` 接下来,我们需要训练我们的模型。我们将使用交叉熵损失函数和Adam优化器来训练模型。以下是训练模型的代码: ```python from keras.optimizers import Adam # 训练模型 def train_model(model, images, labels, val_images, val_labels, batch_size, epochs): # 编译模型 model.compile(optimizer=Adam(lr=1e-4), loss='categorical_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(images, labels, batch_size=batch_size, epochs=epochs, validation_data=(val_images, val_labels)) ``` 最后,我们需要使用我们的模型来进行预测。以下是预测图像的代码: ```python # 使用模型预测图像 def predict_image(model, image): # 对图像进行预处理 image = preprocess_input(image[np.newaxis, ...]) # 进行预测 pred = model.predict(image) # 将预测结果转换为标签 pred = np.argmax(pred, axis=-1) # 返回预测结果 return pred[0] ``` 现在,我们已经完成了语义分割的Python实现。我们可以使用以下代码来运行我们的程序: ```python from keras.applications.vgg16 import VGG16 DATA_DIR = 'path/to/data' WEIGHTS_FILE = 'path/to/weights.h5' IMAGE_FILE = 'path/to/image.jpg' # 加载数据集 train_images, train_labels = load_train_data(os.path.join(DATA_DIR, 'train')) val_images, val_labels = load_val_data(os.path.join(DATA_DIR, 'val')) # 预处理数据集 train_images, train_labels = preprocess_train_data(train_images, train_labels) val_images, val_labels = preprocess_val_data(val_images, val_labels) # 构建模型 model = build_model(train_images[0].shape, train_labels.shape[-1]) # 训练模型 train_model(model, train_images, train_labels, val_images, val_labels, batch_size=16, epochs=10) # 保存模型权重 model.save_weights(WEIGHTS_FILE) # 加载模型权重 model.load_weights(WEIGHTS_FILE) # 加载图像 image = cv2.imread(IMAGE_FILE) # 进行预测 pred = predict_image(model, image) # 显示预测结果 cv2.imshow('Prediction', pred) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这就是语义分割的Python实现。希望本文可以帮助大家更好地了解和应用语义分割技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值