Keras教学(5):使用Keras搭建GooletNet卷积神经网络

【写在前面】:大家好,我是【猪葛】
一个很看好AI前景的算法工程师
在接下来的系列博客里面我会持续更新Keras的教学内容(文末有大纲)
内容主要分为两部分
第一部分是Keras的基础知识
第二部分是使用Keras搭建FasterCNN、YOLO目标检测神经网络
代码复用性高
如果你也感兴趣,欢迎关注我的动态一起学习
学习建议:
有些内容一开始学起来有点蒙,对照着“学习目标”去学习即可
一步一个脚印,走到山顶再往下看一切风景就全明了了



本篇博客学习目标:1、理解GooletNet网络结构;2、学会自己搭建GooletNet网络结构





一、函数式API搭建GooletNet卷积神经网络

在搭建GooletNet卷积神经网络之前,我们要先弄明白这个网络的具体架构是什么样子的

1-1、 GooletNet简介

GoogLeNet卷积神经网络出自于《Going deeper with convolutions》这篇论文,是由谷歌公司Christian Szegedy、Yangqing Jia等人联合发表。其研究成果在2014年 ILSVRC 挑战赛 ImageNet 分类任务上获得冠军,而当时的亚军就是上一篇文中讲到的VGG系列。
很有意思的是,GoogLeNet名字是由Google的前缀Goog与LeNet的组合而来,这其实是对Yann LeCuns开拓性的LeNet-5网络的致敬。
GoogLeNet卷积神经网络的最大贡献在于,提出了非常经典的Inception模块。该网络结构的最大特点是网络内部计算资源的利用率很高。因此该设计允许在保持计算资源预算不变的情况下增加网络的深度和宽度,使得GoogLeNet网络层数达到了更深的22层,但是网络参数仅为AlexNet的1/12。

1-2、网络组成

1-2-1、Inception模块

模块的网络结构如图所示:

在这里插入图片描述

inception模块的网络结构有两种形式,论文中采取的是第二种形式

提示一点

  • 结构图中把卷积操作的卷积核大小都写清楚了,但是没有说明步长和padding,翻看论文可知,这里所有卷积步长都为1,padding都为'same', 激活函数都选择'relu';最大池化层的步长也为1padding也为'same';

因为这个代码模块经常用到,所以我将其封装成一个函数

from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, BatchNormalization, Concatenate, AveragePooling1D
from tensorflow.keras.layers import Dense, Flatten, Dropout, AveragePooling2D, Softmax
from tensorflow.keras.models import Model


def inception(x, filters):
    """
    inception模块
    :param x: 输入张量
    :param filters: 一个列表,元素表示卷积核的个数,int类型
    :return: 输出张量
    """
    # 对应结构图从左边计算的第一条分支
    branch1 = Conv2D(filters[0], (1, 1), 1, 'same', activation='relu')(x)

    # 对应结构图从左边计算的第二条分支
    branch2 = Conv2D(filters[1], (1, 1), 1, 'same', activation='relu')(x)
    branch2 = Conv2D(filters[2], (3, 3), 1, 'same', activation='relu')(branch2)

    # 对应结构图从左边计算的第三条分支
    branch3 = Conv2D(filters[3], (1, 1), 1, 'same', activation='relu')(x)
    branch3 = Conv2D(filters[4], (5, 5), 1, 'same', activation='relu')(branch3)

    # 对应结构图从左边计算的第四条分支
    branch4 = MaxPooling2D((3, 3), 1, 'same')(x)
    branch4 = Conv2D(filters[5], (1, 1), 1, 'same')(branch4)

    # 将每个分支的最后一维堆叠起来,对应结构图中的是“Filter concatenate”
    y = Concatenate()([branch1, branch2, branch3, branch4])

    return y

1-2-2、辅助分类器

考虑到网络的深度较大,以有效方式将梯度传播回所有层的能力有限,可能会产生梯度弥散现象。因此在网络中间层设计了两个辅助分类器,希望以此激励网络在较低层进行分类,从而增加了被传播回的梯度信号,避免出现梯度弥散。
在训练过程中,它们的损失将以折扣权重添加到网络的总损失中(辅助分类器的损失加权为0.3)。 在测试过程中,这些辅助网络将被丢弃。其网络结构如下:

在这里插入图片描述

提示下面四点

  • 第一层是AveragePooling2D平均池化层,大小是(5, 5), 步长是1, padding'valid'
  • 第二层是卷积层,卷积核个数是128,大小是(1, 1), 步长是1, padding'same'
  • 第三层、第四层都为全连接层,节点分别为1024、1000,激活函数都选择'relu'
  • 最后一层是softmax激活层

因为这个辅助分类器要使用到两次,所以我也将其封装成一个函数

from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, BatchNormalization, Concatenate, AveragePooling1D
from tensorflow.keras.layers import Dense, Flatten, Dropout, AveragePooling2D, Softmax
from tensorflow.keras.models import Model
def y_branch_loss(x):
    """
    辅助分类器
    :param x: 输入张量
    :return: 输出张量
    """
    # 每一行代码代表一层网络
    y_branch = AveragePooling2D((5, 5), 3)(x)
    y_branch = Conv2D(128, (1, 1), 1, 'same', activation='relu')(y_branch)
    y_branch = Dense(1024, activation='relu')(y_branch)
    y_branch = Dense(1000, activation='relu')(y_branch)
    y_branch = Softmax()(y_branch)
    return y_branch

1-2-3、GooletNet整体架构

清楚了上面两小节说的内容,我们再来看总体的网络架构就很简单了,先看个完整架构图

在这里插入图片描述

待会我们就根据这个网络架构图和下面的参数列表(原论文给出、如下)来搭建GoogLeNet整体结构

在这里插入图片描述

提示两点

  • ‘# 3 x 3 reduce’ 表示 ‘# 3 x 3’ 前面的 ‘# 1 x 1’(理解不了请再看一遍1-2-1小节内容)
  • ‘# 5 x 5 reduce’ 表示 ‘# 5 x 5’ 前面的 ‘# 1 x 1’

根据以上所有内容,我们使用Keras函数式API搭建模型的方法搭建出来的GooletNet卷积神经网络如下:

from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, BatchNormalization, Concatenate, AveragePooling1D
from tensorflow.keras.layers import Dense, Flatten, Dropout, AveragePooling2D, Softmax
from tensorflow.keras.models import Model


def inception(x, filters):
    """
    inception模块
    :param x: 输入张量
    :param filters: 一个列表,元素表示卷积核的个数,int类型
    :return: 输出张量
    """
    # 对应结构图从左边计算的第一条分支
    branch1 = Conv2D(filters[0], (1, 1), 1, 'same', activation='relu')(x)

    # 对应结构图从左边计算的第二条分支
    branch2 = Conv2D(filters[1], (1, 1), 1, 'same', activation='relu')(x)
    branch2 = Conv2D(filters[2], (3, 3), 1, 'same', activation='relu')(branch2)

    # 对应结构图从左边计算的第三条分支
    branch3 = Conv2D(filters[3], (1, 1), 1, 'same', activation='relu')(x)
    branch3 = Conv2D(filters[4], (5, 5), 1, 
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值