机器视觉基于卷积神经网络之VGG迁移学习(附源码可直接运行)

机器视觉基于卷积神经网络之VGG迁移学习

源码在文末,可直接运行

迁移学习

迁移学习:利用数据、任务和模型之间的了解,将旧领域中学习或训练的模型应用到新领域的过程。

注意:这两个任务的输入具有相同的性质:图像或语音或其他内容。

原模型(具有较好的基础参数)--->修改原模型的输出结果--->得到新的模型(适用于新的情形)

  • 当有海量数据资源时,不能使用迁移学习。可以使用深度学习直接训练稳健的模型
  • 迁移学习可以降低训练成本,站在巨人的肩膀上,从头训练需要较长时间且需要依赖较大的GPU资源。

微调(fine-tuning)

微调:

  • 无需大量调整即可调整模型参数
  • 调整模型结构,无需大量调整

预训练模型(pre-trained model):就是用来进行迁移学习的样本模型。
https://github.com/tensorflow/models/tree/master/research/slim

迁移学习步骤

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4c4fIGlU-1648475306806)(picture/img1.png)]

  1. 搭建自己的网络,根据预训练好的模型修改最终输出结构,加载并训练模型的模型参数
  2. 根据数据大小调整
  3. 如果待训练模型数据量小,那么我们可以选择将预训练模型的所有的层进行freeze(可以通过Tensorflow的trainable=False参数实现),而剩下的输出层部分可以选择调整参数训练。
  4. 如果待训练模型数据量大,那么我们可以将预训练模型中一半或者大部分的层进行freeze,而剩下的部分的layer可以进行新任务数据基础的微调。

VGG

该项目基于现有VGG模型

  1. 准备训练和测试集
  2. 修改模型分类层
  3. freeze原始VGG模型
  4. 训练模型
  5. 输入数据以进行预测

准备训练和测试集

相关api

  • ImageDataGenerator()
  • 定义数据转换和数据扩充
  • 为图像产生批量张量值并提供数据增强
  • rescale=1.0 / 255,:标准化
  • zca_whitening=False: # zca白化的作用是针对图片进行PCA降维操作,减少图片的冗余信息
  • rotation_range=20:默认0, 旋转角度,在这个角度范围随机生成一个值
  • width_shift_range=0.2,:默认0,水平平移
  • height_shift_range=0.2:默认0, 垂直平移
  • shear_range=0.2:# 平移变换
  • zoom_range=0.2:
  • horizontal_flip=True:水平翻转
  • train_generator = ImageDataGenerator()
  • flow(x, y, batch_size)
  • 直接从文件中读取
  • flow_from_directory(
  • directory=path,# 读取目录
  • target_size=(h,w),# 目标形状
  • batch_size=size,# 批数量大小
  • class_mode=‘binary’, # 目标值格式
  • shuffle=True)
  • 从本地读取
  • 该api要求数据存储格式固定
data/
    train/
        dogs/
            dog001.jpg
            dog002.jpg
            ...
        cats/
            cat001.jpg
            cat002.jpg
            ...
    validation/
        dogs/
            dog001.jpg
            dog002.jpg
            ...
        cats/
            cat001.jpg
            cat002.jpg
            ...

注意这里在进行数据增强后,在训练的时候也要将增强数据放进去,该使用fit_generator(),而不是fit()

修改模型分类层

VGG-notop模型

运行代码后
在根目录下有一个.keras,其中的models文件夹中就生成一个VGG的notop模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z26HHEK4-1648475306807)(picture/img.png)]

  • notop模型不包含最后三个全连接层,专门用来fine-tuning,不需要我们来自主进行删除

VGG16源码片

 if include_top:
    # Classification block
    x = layers.Flatten(name='flatten')(x)
    x = layers.Dense(4096, activation='relu', name='fc1')(x)
    x = layers.Dense(4096, activation='relu', name='fc2')(x)

    imagenet_utils.validate_activation(classifier_activation, weights)
    x = layers.Dense(classes, activation=classifier_activation,
                     name='predictions')(x)
  else:
    if pooling == 'avg':
      x = layers.GlobalAveragePooling2D()(x)
    elif pooling == 'max':
      x = layers.GlobalMaxPooling2D()(x)

 # Ensure that the model takes into account
  # any potential predecessors of `input_tensor`.
  if input_tensor is not None:
    inputs = layer_utils.get_source_inputs(input_tensor)
  else:
    inputs = img_input
  # Create model.
  model = training.Model(inputs, x, name='vgg16')
  
  # Load weights.
  if weights == 'imagenet':
    if include_top:
      weights_path = data_utils.get_file(
          'vgg16_weights_tf_dim_ordering_tf_kernels.h5',
          WEIGHTS_PATH,
          cache_subdir='models',
          file_hash='64373286793e3c8b2b4e3219cbf3544b')
    else:
      weights_path = data_utils.get_file(
          'vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5',
          WEIGHTS_PATH_NO_TOP,
          cache_subdir='models',
          file_hash='6d6bbae143d832006294945121d1f1fc')
    model.load_weights(weights_path)
  elif weights is not None:
    model.load_weights(weights)

  return model

下面是VGG16(imgenet)模型报告
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eap5iMzo-1648475306807)(picture/img2.png)]

全局平均池化(GobalAveragePooling2D)

在迁移学习中,只需要训练后的全连接层,所以不需要大量的参数,使用过多的参数会导致过拟合。
例如:输出大少为shape=[8,8,2048],通过全局平均池化后,将88的64位向量进行取均值,所以原本的882048就转变成了12048
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KyBGK8e4-1648475306808)(picture/pooling.png)]

冻结预训练模型

如果我们模型的测试集很大,可以把模型的所有参数取出来一起训练;
如果我们模型的测试集很小,那么模型的前层就被冻结了,只训练全连接层的参数

做法:将要冻结的每层中的trainable参数设置为False

layer.trainable = False  
# 将基类模型中的每一层进行冻结
for layer in self.base_model.layer:
    layer.trainable = False

训练模型

  • 编译模型
  • 优化器:Adam
  • optimizer=keras.optimizers.Adam()
  • loss损失计算:交叉熵损失
  • loss=keras.losses.sparse_categorical_crossentropy
  • 评估矩阵
  • metrics=[‘accuracy’]
  • 训练模型
  • 数据增强过,需要使用fit_generator()
  • 在fit_generator()的callbacks中可以加入ModelCheckpoint进行记录每次迭代的准确率,fit()是加不进去这个monitor的
  • 在新版本的tensorflow中fit_generator()已经被弃用了,fit()合并了fit_generator()的作用

ModelCheckpoint

  • 这里检测验证准确率“val_acc”(注意在新版本中,这里可能要改成“val_accuracy”)
  • 只保留权重参数
  • 只保留最好的模型
  • 自动检测最大准确率与最小的loss
modelckpt = keras.callbacks.ModelCheckpoint('./ckpt/transfer_{epoch:02d}-{val_acc:.2f}.h5',
                                                     monitor='val_acc',
                                                     save_weights_only=True,
                                                     save_best_only=True,
                                                     mode='auto',
                                                     period=1)

输入数据以进行预测

训练好模型后,需要保存模型,然后加载模型使用

  • 保存模型
model.save_weights("./xxx.h5")
  • 负载模型
model.load_weights("./xxx.h5")

源代码

项目源码_Github
运行环境:tensorflow-2.3.0,keras-2.8.0

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2022年3月30日 下午6:13
下一篇 2022年3月30日 下午6:27

相关推荐