TF2.0图像分类实战(四)VGGNet

VGGNet创新点

VGGNet是牛津大学计算机视觉组(Visual Geometry Group)和Google DeepMind公司的研究员一起研发的的深度卷积神经网络。VGGNet探索了卷积神经网络的深度与其性能之间的关系,通过反复堆叠33的小型卷积核和22的最大池化层,VGGNet成功地构筑了16~19层深的卷积神经网络。VGGNet相比之前state-of-the-art的网络结构,错误率大幅下降,并取得了ILSVRC 2014比赛分类项目的第2名和定位项目的第1名。

VGGNet论文中全部使用了33的卷积核和22的池化核,通过不断加深网络结构来提升性能。下图所示为VGGNet各级别的网络结构图,和每一级别的参数量,从11层的网络一直到19层的网络都有详尽的性能测试。
在这里插入图片描述
虽然从A到E每一级网络逐渐变深,但是网络的参数量并没有增长很多,这是因为参数量主要都消耗在最后3个全连接层。前面的卷积部分虽然很深,但是消耗的参数量不大,不过训练比较耗时的部分依然是卷积,因其计算量比较大。

VGGNet拥有5段卷积,每一段内有2~3个卷积层,同时每段尾部会连接一个最大池化层用来缩小图片尺寸。每段内的卷积核数量一样,越靠后的段的卷积核数量越多:64 – 128 – 256 – 512 – 512。其中经常出现多个完全一样的33的卷积层堆叠在一起的情况,这其实是非常有用的设计。
在这里插入图片描述
如上图所示,两个3
3的卷积层串联相当于1个55的卷积层,即一个像素会跟周围55的像素产生关联,可以说感受野大小为55。而3个33的卷积层串联的效果则相当于1个77的卷积层。除此之外,3个串联的33的卷积层,拥有比1个7*7的卷积层更少的参数量,只有后者的55%。

最重要的是,3个33的卷积层拥有比1个77的卷积层更多的非线性变换(前者可以使用三次ReLU激活函数,而后者只有一次),使得CNN对特征的学习能力更强。

作者在对比各级网络时总结出了以下几个观点。

LRN层作用不大。

越深的网络效果越好。

11的卷积也是很有效的,但是没有33的卷积好,大一些的卷积核可以学习更大的空间特征。

整体代码

import tensorflow as tf
import os
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import layers
import matplotlib.pyplot as plt


# 构建数据集
def getDatas():
    image_path = "./monkey/"  # monkey数据集路径
    train_dir = image_path + "training/training/"  # 训练集路径
    validation_dir = image_path + "validation/validation/"  # 验证集路径
    # test_dir = image_path + "test"  # 测试集路径

    # 定义训练集图像生成器,并进行图像增强
    train_image_generator = ImageDataGenerator(rotation_range=40,
                                               width_shift_range=0.2,
                                               height_shift_range=0.2,
                                               rescale=1. / 255,
                                               shear_range=0.2,
                                               zoom_range=0.2,
                                               horizontal_flip=True,
                                               fill_mode='nearest')

    # 使用图像生成器从文件夹train_dir中读取样本,对标签进行one-hot编码
    train_data_gen = train_image_generator.flow_from_directory(directory=train_dir,
                                                               batch_size=batch_size,
                                                               shuffle=True,
                                                               target_size=(im_height, im_width),
                                                               class_mode='categorical')
    print(train_data_gen)
    # 训练集样本数
    # total_train = train_data_gen.n

    # 定义验证集图像生成器,对图像进行预处理
    validation_image_generator = ImageDataGenerator(rescale=1. / 255)  # 归一化

    # 使用图像生成器从验证集validation_dir中读取样本
    val_data_gen = validation_image_generator.flow_from_directory(directory=validation_dir,
                                                                  batch_size=batch_size,
                                                                  shuffle=True,
                                                                  target_size=(im_height, im_width),
                                                                  class_mode='categorical')
    print(val_data_gen)
    # 验证集样本数
    # total_val = val_data_gen.n
    return train_data_gen, val_data_gen


def base(x, filters, flags):
    x = layers.Conv2D(filters, kernel_size=(3, 3), padding='same')(x)
    x = layers.BatchNormalization()(x)
    x = layers.Activation('relu')(x)
    if flags is True:
        x = layers.MaxPool2D(pool_size=(2, 2), strides=(2, 2), padding='same')(x)
        x = layers.Dropout(0.2)(x)
    return x


# 定义模型
def VGG16():
    image_input = tf.keras.layers.Input(shape=(224, 224, 3))
    x = base(image_input, 64, flags=False)
    x = base(x, 64, flags=True)
    x = base(x, 128, flags=False)
    x = base(x, 128, flags=True)
    x = base(x, 256, flags=False)
    x = base(x, 256, flags=False)
    x = base(x, 256, flags=True)
    x = base(x, 512, flags=False)
    x = base(x, 512, flags=False)
    x = base(x, 512, flags=True)
    x = base(x, 512, flags=False)
    x = base(x, 512, flags=False)
    x = base(x, 512, flags=True)
    x = layers.Flatten()(x)
    x = layers.Dense(512, activation='relu')(x)
    x = layers.Dropout(0.2)(x)
    x = layers.Dense(512, activation='relu')(x)
    x = layers.Dropout(0.2)(x)
    x = layers.Dense(10, activation='softmax')(x)
    net = tf.keras.Model(image_input, x)

    return net


model = VGG16()
model.summary()


if __name__ == '__main__':

    # 训练参数
    im_height = 224
    im_width = 224
    batch_size = 8
    epochs = 50
    learning_rate = 0.001


    # 获得数据集
    train_data_gen_, val_data_gen_ = getDatas()
    # 编译模型
    model.compile(optimazer=tf.keras.optimizers.Adam(learning_rate=learning_rate),
                  loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False),  # 交叉熵损失函数
                  metrics=["categorical_accuracy"])  # 评价函数

    # # 断点续训
    checkpoint_save_path = "./checkpoint/mobilenetv2.ckpt"
    if os.path.exists(checkpoint_save_path + '.index'):
        print('--------------load the model---------------')
        model.load_weights(checkpoint_save_path)

    # 保存模型
    cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
                                                     save_weights_only=True,
                                                     save_best_only=True)

    # 开始训练
    # history = model.fit(x=train_data_gen_, epochs=epochs, validation_data=val_data_gen_, callbacks=[cp_callback])  # 此方法把数据全部加载进来
    history = model.fit_generator(train_data_gen_,
                                  steps_per_epoch=1098 // batch_size, epochs=epochs, initial_epoch=0,
                                  validation_data=val_data_gen_,
                                  validation_steps=272 // batch_size,
                                  callbacks=[cp_callback])

    # 记录训练和验证集的准确率和损失值
    history_dict = history.history
    train_loss = history_dict["loss"]
    train_accuracy = history_dict["accuracy"]
    val_loss = history_dict["val_loss"]
    val_accuracy = history_dict["val_accuracy"]

    # 绘制损失值
    plt.figure()
    plt.plot(range(epochs), train_loss, label='train_loss')
    plt.plot(range(epochs), val_loss, label='val_loss')
    plt.legend()
    plt.xlabel('epochs')
    plt.ylabel('loss')

    # 绘制准确率
    plt.figure()
    plt.plot(range(epochs), train_accuracy, label='train_accuracy')
    plt.plot(range(epochs), val_accuracy, label='val_accuracy')
    plt.legend()
    plt.xlabel('epochs')
    plt.ylabel('accuracy')
    plt.show()
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值