深度学习之迁移学习实现神奇宝贝识别

经过之前深度学习的实践,无论是自己搭建的CNN网络也好,还是通过迁移学习调用官方的网络模型也好,都有其优点以及不足。本次实验通过对各种常用的CNN网络模型进行调用,了解一下它们的特点,对比一下在对于同一数据集进行分类时的准确率。
本次所调用的CNN模型有:VGG16 VGG19 ResNet Densenet模型

1.导入库

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import os,PIL,pathlib
from tensorflow import keras
from tensorflow.keras import layers,models,Sequential,Input

2.加载数据

操作与之前的相似,将数据按照8:2的比例划分为训练集和测试集

data_dir = "E:/tmp/.keras/datasets/Pokemon_photos"
data_dir = pathlib.Path(data_dir)

img_count = len(list(data_dir.glob('*/*.png')))#总共219张照片
# print(img_count)

height = 224
width = 224
epochs = 20
batch_size = 8
train_data_gen = tf.keras.preprocessing.image.ImageDataGenerator(
    rescale=1./255,
    rotation_range=45,
    shear_range=0.2,
    zoom_range=0.2,
    validation_split=0.2,
    horizontal_flip=True
)
train_ds = train_data_gen.flow_from_directory(
    directory=data_dir,
    target_size=(height,width),
    batch_size=batch_size,
    shuffle=True,
    class_mode='categorical',
    subset='training'
)
test_ds = train_data_gen.flow_from_directory(
    directory=data_dir,
    target_size=(height,width),
    batch_size=batch_size,
    shuffle=True,
    class_mode='categorical',
    subset='validation'
)

3.自己搭建CNN网络

三层卷积池化层+Flatten+三层全连接层

#CNN
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(16,3,padding="same",activation="relu",input_shape=(height,width,3)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(32,3,padding="same",activation="relu"),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(64,3,padding="same",activation="relu"),
    tf.keras.layers.AveragePooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(1024,activation="relu"),
    tf.keras.layers.Dense(512,activation="relu"),
    tf.keras.layers.Dense(10,activation="softmax")
])

深度学习之迁移学习实现神奇宝贝识别_第1张图片
最终的模型准确率在80%左右,通过实验结果可以发现,增加epochs的个数,最终的模型准确率并没有得到提高,而是在震荡,而模型准确率最高的时候在epochs为20的时候。

4.官方模型

VGG16模型
VGG16和VGG19是VGG系列模型中最经典的两个模型,后者具有更深的层次。VGG系列的模型有以下特点:
①小卷积核:相比AlexNet,将卷积核全部替换为3x3,极少用了1x1。而3x3是最小的能够捕获像素八邻域信息的尺寸。
②小池化层:相比AlexNet,3x3的池化核全部换为2x2的池化核。
③层数更深:VGG16为例,3 → 64 → 126 → 256 → 512,卷积核专注于扩大通道数,3个通道的特征经过经过卷积层的提取扩散到了512个通道。
④层数更深:VGG16为例,3 → 64 → 126 → 256 → 512 ,卷积核专注于扩大通道数,3个通道的特征经过经过卷积层的提取扩散到了512个通道。
⑤全连接转1 × 1卷积:测试阶段可以接收任意宽或高为的输入。
这是相比于VGG模型之前的模型所做出的改变,那么为何要做这样的改变呢?

3x3卷积核
两个3x3的堆叠卷基层的有限感受野是5x5;三个3x3的堆叠卷基层的感受野是7x7,故可以通过小尺寸卷积层的堆叠替代大尺寸卷积层,并且感受野大小不变。多个小卷积可以提取出更大更深的卷积特征,并且减少模型参数数量。

2x2池化核
AlexNet的最大池化核为 3 × 3,步幅为2。VGGNet最大池化核为 2 × 2,步幅为2 22。小池化核带来的是更细节的信息捕获

1x1卷积核
测试阶段可以接收任意宽或高为的输入,消除输入的限制

调用官方VGG16模型,其中常用的几个参数解释如下:

VGG模型中包含的所有参数,在别的官方模型中,参数与之类似。
tf.keras.applications.vgg16.VGG16(
    include_top=True, weights='imagenet', input_tensor=None,
    input_shape=None, pooling=None, classes=1000,
    classifier_activation='softmax'
)

include_top:是否包括网络顶部的 3 个全连接层。
weights:默认不加载权重文件,"imagenet"加载官方权重文件,或者输入自己的权重文件路径。
classes:分类图像的类别数。
conv_base = tf.keras.applications.VGG16(weights = 'imagenet',include_top = False)
conv_base.trainable =False#不可训练
#模型搭建
model = tf.keras.Sequential()
model.add(conv_base)
model.add(tf.keras.layers.GlobalAveragePooling2D())
model.add(tf.keras.layers.Dense(1024,activation='relu'))
model.add(tf.keras.layers.Dense(10,activation='softmax'))

优化器的配置与前几篇博客的设置相同,在此不再赘述。
深度学习之迁移学习实现神奇宝贝识别_第2张图片
相比较自己搭建的CNN网络,VGG16模型准确率没有那么频繁的振动,最终模型准确率在80%。不过这是epochs=20的条件下,在epochs同样的条件下,训练效果应该更好。

调用官方VGG19模型

conv_base = tf.keras.applications.VGG19(weights = 'imagenet',include_top = False)
conv_base.trainable =False#不可训练
#模型搭建
model = tf.keras.Sequential()
model.add(conv_base)
model.add(tf.keras.layers.GlobalAveragePooling2D())
model.add(tf.keras.layers.Dense(1024,activation='relu'))
model.add(tf.keras.layers.Dense(10,activation='softmax'))

深度学习之迁移学习实现神奇宝贝识别_第3张图片
相比较起VGG16模型,VGG19模型充分体现了加深网络深度对于模型准确率的好处。模型准确率在80%以上,最高达到了90%。
当把epochs设置为40时,结果如下所示:
深度学习之迁移学习实现神奇宝贝识别_第4张图片
准确率最高为94.87%,效果不错。

ResNet50模型

在深层网络能够收敛的前提下,随着网络深度的增加,正确率开始饱和甚至下降,称之为网络的退化(degradation)问题。在一定程度上,加深网络模型可以增加模型的准确率,但是网络深度过深,准确率就会下降,这些退化并不是过拟合造成的。在极端条件下,如果增加的所有层都是前一层的直接复制(即 y=x),这种情况下深层网络的训练误差应该和浅层网络相等。因此,网络退化的根本原因还是优化问题。 为了解决优化的难题,提出了残差网络。残差网络可以理解为在前向网络中增加了一些快捷连接(shortcut connections)。这些连接会跳过某些层,将原始数据直接传到之后的层。新增的快捷连接不会增加模型的参数和复杂度。整个模型还是可以使用端到端的方法来训练(比如SGD),在实现上并不难。

conv_base = tf.keras.applications.ResNet50(weights = 'imagenet',include_top = False)
conv_base.trainable =False
#模型搭建
model = tf.keras.Sequential()
model.add(conv_base)
model.add(tf.keras.layers.GlobalAveragePooling2D())
model.add(tf.keras.layers.Dense(1024,activation='relu'))
model.add(tf.keras.layers.Dense(10,activation='softmax'))

深度学习之迁移学习实现神奇宝贝识别_第5张图片
这结果就很迷,训练集的准确率已经高达100%,但是测试集的准确率几乎为0。应该不是网络本身的问题,有些参数的设置博主并不是很理解,希望路过的大佬可以指点一二。在之前的一篇博客鸟类识别中,这样的情况也出现了,当时以为是过拟合,但现在看来并不是过拟合。

Densenet模型

这个模型是最近几年提出的网络模型,平常用的并不多,但是它的优点突出。
1、减轻了vanishing-gradient(梯度消失)
2、加强了feature的传递。
3、更有效地利用了feature。
4、一定程度上较少了参数数量。

Densenet模型在保证网络中层与层之间最大程度的信息传输的前提下,直接将所有层连接起来!在传统的卷积神经网络中,如果你有L层,那么就会有L个连接,但是在DenseNet中,会有L(L+1)/2个连接。简单讲,就是每一层的输入来自前面所有层的输出。如下图所示:
深度学习之迁移学习实现神奇宝贝识别_第6张图片

conv_base = tf.keras.applications.densenet.DenseNet121(weights = 'imagenet',include_top = False)
conv_base.trainable =False
#模型搭建
model = tf.keras.Sequential()
model.add(conv_base)
model.add(tf.keras.layers.GlobalAveragePooling2D())
model.add(tf.keras.layers.Dense(1024,activation='relu'))
model.add(tf.keras.layers.Dense(10,activation='softmax'))

深度学习之迁移学习实现神奇宝贝识别_第7张图片
该网络在训练集的准确率上已经达到了98%,但是在测试集的准确率在70%-80%之间,并没有VGG模型的准确率高。

总结:
本文只是对同一数据集利用不同的网络模型进行准确率的比较,并没有说某一网络模型一定好。任何一种网络模型都有其突出的优点以及各自的不足。在对于神奇宝贝的识别中,VGG19网络的准确率是最高的,并且没有出现振动或者过拟合的现象。

你可能感兴趣的:(机器学习,深度学习,人工智能,迁移学习)