Cats vs Dogs之使用迁移学习进行图像识别

前言:

前面介绍如何使用AlexNet 、VGG19 、 ResNet_152  、 InceptionV4 、DenseNet训练自己的数据集,接下来两节主要介绍如何使用迁移学习进行图像识别的任务。第一节是介绍使用单个模型进行图像识别的任务,第二节介绍使用融合模型进行图像是别的任务。

什么是迁移学习:

迁移学习(Transfer Learning):就是指利用已经训练好的开源网络模型比如常见的VGG系列、Resnet系列、GoogleNet系列等,利用这些网络和其已经在其他大型数据集上训练好的权重参数,将自己的任务数据集在这些迁移过来的网络上进行训练或者微调。这里迁移是指迁移网络模型和网络预训练的权重。

对于迁移学习我的理解就是当你的数据集和别人的数据集类似的时候,而且你们的目标也相似的时候,这个时候你就可以直接使用别人已经公开的源码和训练好的weigth进行你的任务。这样做的好处就是省时间,训练的快,省的你在不断地调参的过程了。

怎么使用迁移学习:

熟话说的好,工欲善其事,必先利其器,一个好的工具会让你事半功倍。所以本节我抛弃了一直使用的tensorflow,而改用keras进行这个任务。为啥呢?首先是因为keras中已经封装好了一些经典的图像识别的模型,例如ResNet50 InceptionV3 InceptionResNetV2 Xception VGG19。其次是因为如果你要是使用tensorflow的话,你可能还要幸幸苦苦地上网上找各个模型已经训练好的权重,但是使用keras的话只需要设置好相关的参数就可以自动下载已经训练好的模型了。最后呢是因为我看了大部分大佬开源的方案都是使用keras,实在不想画时间手撕一份没啥大意义的代码。

代码中模型和权重的选择,代码解释::

对于迁移学习而言最重要的是两个内容,首先是使用哪种模型,本代码提供多种可选架构ResNet50、InceptionV3、Xception、VGG19、InceptionResNetV2 包含了keras上所有图像识别模型了。其次是选择使用在那个数据集上训练好的权重(weight),这个是没办法选了因为keras只支持imagenet或者重头训练,所以只有选择在imagenet训练好的权重了。

程序的主要过程如下:

第一: 数据预处理,将数据分为训练集和验证集, 处理过程比较简单,执行这个python文件即可

第二: 使用ImageDataGenerator()和flow_from_directory()加载图像,函数的解释可以参考这个链接

第三: 使用chose_model选择指定的模型,weights(权重)只能选择imagenet和None,None表示不使用任何权重重新训练。imagenet表示使用在imagenet数据集上训练的weights(权重),include_top=False,因为imagenet的最后输出的类别是1000,而我们模型只输出一个类别。

第四:  for layer in base_model.layers:  layer.trainable = False因为使用已经训练好的模型,所以设置所有变量都设置为不可训练。 如果我们设置weights=None的话,我们要把layer.trainable = True

第五:  model.compile()定义损失函数和优化器

第六:  开始使用fit_generator()训练模型, fit_generator()函数的讲解可以参考这个链接

实验代码:

# -*- coding: utf-8 -*-
# @Time    : 2019/7/3 14:25
# @Author  : YYLin
# @Email   : [email protected]
# @File    : ResNet50_VGG-19_Inception_V4.py
from keras.applications.resnet50 import ResNet50
from keras.applications.inception_v3 import InceptionV3
from keras.applications.inception_resnet_v2 import InceptionResNetV2
from keras.applications.xception import Xception
from keras.applications.vgg19 import VGG19

from keras.preprocessing.image import ImageDataGenerator
import keras

batch_size = 64
size = 244
chose_model = 'InceptionV3'

train_data_generator = ImageDataGenerator(rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
valid_data_generator = ImageDataGenerator(rescale=1./255)

# 定义用于训练的相关数据
train_generator = train_data_generator.flow_from_directory('../Dataset/Cat_Vs_Dog/train', target_size=(size, size),
                                                           batch_size=batch_size, class_mode='binary')
valid_generator = valid_data_generator.flow_from_directory('../Dataset/Cat_Vs_Dog/valid', target_size=(size, size),
                                                           batch_size=batch_size, class_mode='binary')

print('train_generator.n // batch_size:', train_generator.n % batch_size)

# 可以加载的模型有 ResNet50 InceptionV3 InceptionResNetV2 Xception VGG19
if chose_model == 'ResNet50':
    base_model = ResNet50(weights='imagenet', include_top=False)
elif chose_model == 'InceptionV3':
    base_model = InceptionV3(weights='imagenet', include_top=False)
elif chose_model == 'InceptionResNetV2':
    base_model = InceptionResNetV2(weights='imagenet', include_top=False)
elif chose_model == 'Xception':
    base_model = Xception(weights='imagenet', include_top=False)
elif chose_model == 'VGG19':
    base_model = VGG19(weights='imagenet', include_top=False)

x = base_model.output
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dense(1024, activation='relu')(x)
predictions = keras.layers.Dense(1, activation='sigmoid')(x)

model = keras.Model(inputs=base_model.input, outputs=predictions)

# 因为我们使用的是之前的权重进行训练 所以需要设置 layer.trainable = False
for layer in base_model.layers:
    layer.trainable = False

model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])

model.fit_generator(
    train_generator,
    steps_per_epoch=train_generator.n // batch_size,
    epochs=20,
    workers=1,
    validation_data=valid_generator,
    validation_steps=valid_generator.n // batch_size
)

实验结果: 实验结果说明代码是正确的,以后碰到相同问题直接套用代码就可以了。

12个epoch之后ResNet50的结果:

使用ResNet50训练的时候,发现一个问题val_acc一直都是0.5从来没有变化过,而且训练集的loss和acc也几乎没有变化过,有可能是过拟合了,但是最有可能ResNet50模型的时候有问题。

15个epoch之后InceptionV3的结果:

说明使用InceptionV3在猫狗数据集上的效果还不错。

6个epoch之后InceptionResNetV2的结果:

 

1个epoch之后Xception的结果:

 

1个epoch之后VGG19的结果:

猜你喜欢

转载自blog.csdn.net/qq_41776781/article/details/94734240