【keras】GoogleNet 网络结构及其实现_keras.model googlenet-程序员宅基地

技术标签: 强化学习与人工智能  

深度学习模型常常通过增加模型的深度或者宽度来获得更高的性能。本文将就深度学习常见的网络结构进行介绍。

GoogLeNet是2014年Christian Szegedy提出的一种全新的深度学习结构,在这之前的AlexNet、VGG等结构都是通过增大网络的深度来获得更好的训练效果,但层数的增加会带来很多负作用,比如overfit、梯度消失、梯度爆炸等。

在介绍GoogLeNet之前,先介绍一下两种卷积模型,即 Inception 模型和 Residual (残差)模型是卷积神经网络中对卷积升级的两个操作。下面主要讲一下Inception模型。

上面的 Inception 模型的Keras实现代码如下所示。 

from keras.layers import Conv2D, MaxPooling2D, Input

input_img = Input(shape=(256, 256, 3))

tower_1 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
tower_1 = Conv2D(64, (3, 3), padding='same', activation='relu')(tower_1)

tower_2 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
tower_2 = Conv2D(64, (5, 5), padding='same', activation='relu')(tower_2)

tower_3 = MaxPooling2D((3, 3), strides=(1, 1), padding='same')(input_img)
tower_3 = Conv2D(64, (1, 1), padding='same', activation='relu')(tower_3)

# concatenate是核心,其实就是连接在一起,比如两列向量和两列向量,连接成四列向量即可。
output = keras.layers.concatenate([tower_1, tower_2, tower_3], axis=1)

一般情况下,如果想降低特征图的大小,可以有如下两种方式:

先池化再作Inception卷积,或者先作Inception卷积再作池化。但是方法一:先作pooling(池化)会导致特征表示遇到瓶颈(特征缺失),方法二:正常缩小,但计算量很大。为了同时保持特征表示且降低计算量,将网络结构改为下图,使用两个并行化的模块来降低计算量(卷积、池化并行执行,再进行合并)。

GoogleNet 中的 Inception 模型如下所示:

深度:层数更深,文章采用了22层,为了避免上述提到的梯度消失问题,googlenet巧妙的在不同深度处增加了两个loss来保证梯度回传消失的现象。

宽度:增加了多种核 1x1,3x3,5x5,还有直接max pooling的,但是如果简单的将这些应用到feature map上的话,concat起来的feature map厚度将会很大,所以在googlenet中为了避免这一现象提出的inception具有如下结构,在3x3前,5x5前,max pooling后分别加上了1x1的卷积核起到了降低feature map厚度的作用。仅仅一层block就包含1*1卷积,3*3卷积,5*5卷积,3*3池化。这样,网络中每一层都能学习到“稀疏”或者“不稀疏”的特征。

实际上采用什么样的Inception Block最好,需要根据你的输出需要来定。比如要输出35*35尺寸的特征图,你不用费心调了,下面这个Inception Block最好:

 如果要输出17*17尺寸的特征图?没关系,这个Inception Block最好:

注意到每组卷积之前都有1*1卷积,之前我们说过,1*1的卷积是为了降低输入特征图个数,不至于到最后特征图泛滥。于是,像拼积木一样,把上述Blocks拼到Inception V4 中就可以了:

其中,Inception-A的block和Inception-B的block展开,正是上一张和上上一张图片的架构。可见,Inception V4的Block更像是模块化的拼接。

下面给出 GoogLeNet 的网络结构:

 网络的参数如下表所示。

 利用Keras实现代码如下所示。

#coding=utf-8
from keras.models import Model
from keras.layers import Input,Dense,Dropout,BatchNormalization,Conv2D,MaxPooling2D,AveragePooling2D,concatenate
from keras.layers.convolutional import Conv2D,MaxPooling2D,AveragePooling2D
import numpy as np
seed = 7
np.random.seed(seed)

# 卷积层和标准层组成的block
def Conv2d_BN(x, nb_filter,kernel_size, padding='same',strides=(1,1),name=None):
    if name is not None:
        bn_name = name + '_bn'
        conv_name = name + '_conv'
    else:
        bn_name = None
        conv_name = None
 
    x = Conv2D(nb_filter,kernel_size,padding=padding,strides=strides,activation='relu',name=conv_name)(x)
    x = BatchNormalization(axis=3,name=bn_name)(x)
    return x

# Inception Block
def Inception(x,nb_filter):
    branch1x1 = Conv2d_BN(x,nb_filter,(1,1), padding='same',strides=(1,1),name=None)
 
    branch3x3 = Conv2d_BN(x,nb_filter,(1,1), padding='same',strides=(1,1),name=None)
    branch3x3 = Conv2d_BN(branch3x3,nb_filter,(3,3), padding='same',strides=(1,1),name=None)
 
    branch5x5 = Conv2d_BN(x,nb_filter,(1,1), padding='same',strides=(1,1),name=None)
    branch5x5 = Conv2d_BN(branch5x5,nb_filter,(1,1), padding='same',strides=(1,1),name=None)
 
    branchpool = MaxPooling2D(pool_size=(3,3),strides=(1,1),padding='same')(x)
    branchpool = Conv2d_BN(branchpool,nb_filter,(1,1),padding='same',strides=(1,1),name=None)
 
    x = concatenate([branch1x1,branch3x3,branch5x5,branchpool],axis=3)
 
    return x
 
inpt = Input(shape=(224,224,3))
#padding = 'same',填充为(步长-1)/2,还可以用ZeroPadding2D((3,3))
x = Conv2d_BN(inpt,64,(7,7),strides=(2,2),padding='same')
x = MaxPooling2D(pool_size=(3,3),strides=(2,2),padding='same')(x)
x = Conv2d_BN(x,192,(3,3),strides=(1,1),padding='same')
x = MaxPooling2D(pool_size=(3,3),strides=(2,2),padding='same')(x)
x = Inception(x,64)#256
x = Inception(x,120)#480
x = MaxPooling2D(pool_size=(3,3),strides=(2,2),padding='same')(x)
x = Inception(x,128)#512
x = Inception(x,128)
x = Inception(x,128)
x = Inception(x,132)#528
x = Inception(x,208)#832
x = MaxPooling2D(pool_size=(3,3),strides=(2,2),padding='same')(x)
x = Inception(x,208)
x = Inception(x,256)#1024
x = AveragePooling2D(pool_size=(7,7),strides=(7,7),padding='same')(x)
x = Dropout(0.4)(x)
x = Dense(1000,activation='relu')(x)
x = Dense(1000,activation='softmax')(x)
model = Model(inpt,x,name='inception')
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
model.summary()

本文参考自:不怕过拟合keras搬砖系列-细读GoogleNet大话CNN经典模型:GoogLeNet(从Inception v1到v4的演进)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zyxhangiian123456789/article/details/88023084

智能推荐

k8s编排nacos standalone模式踩坑实录_pod.alpha.kubernetes.io/initialized: "true-程序员宅基地

文章浏览阅读3.4k次,点赞3次,收藏4次。本人最近用k8s编排nacos,网上大多是用cluster模式启动nacos,而用cluster启动nacos一定要用mysql持久化,而如果用k8s编排nacos时,连数据库比较麻烦,所以本人就想用standalone不带数据库连的方式,用k8s编排nacos。可用的基于standaline的编排文件如下。apiVersion: apps/v1kind: StatefulSetmetadata: name: nacosspec: serviceName: nacos repli_pod.alpha.kubernetes.io/initialized: "true

grep 查询指定时间段内的日志_grep 取时间段-程序员宅基地

文章浏览阅读2.6w次,点赞3次,收藏15次。查询指定时间段内的日志grep 查询的内容 sed -n '/开始时间/,/结束时间/' 文件名eg:grep 成功 sed -n '/2018-09-06 16:00:00/,/2018-09-06 17:00:00/p' all.2018-09-06.log 之前用的一直sed -n 怎么不成功呢。查不到东西呢,显示的还是所有的日志呢,原来自己少了p,切记哦,不要忘了哦..._grep 取时间段

python如何将三维图变成动态_python图片转矩阵python中读取图片的方式,以及将图片以三维数组的形式输出...-程序员宅基地

文章浏览阅读231次。1、图像转换为矩阵matrix = numpy.asarray(image)2、矩阵转换为图像image = Image.fromarray(matrix)近期做个小项目需要用到python读取图片,自己整理了一下两种读取图片的方式,其中一种用到了TensorFlow,(TensorFlow是基于python3 的)。代码及运行结果如下所示:import numpy as npfrom PIL i..._img = image.fromarray(martix)

ArcGIS Editor for OSM插件大合集-程序员宅基地

文章浏览阅读4.8k次。概述开放街道地图是一个建构自由内容之网上地图协作计划,目标是创造一个内容自由且能让所有人编辑的世界地图,并且让一般的移动设备有方便的导航方案。之前有给大家介绍过OpenStreetMap的QGIS下载插件,详见《QGIS中的OpenStreetMap矢量下载插件QuickOSM(附插件下载)》一文,这里给大家介绍一下OpenStreetMap在ArcGIS中使用的插件ArcGIS Editor for OSM,希望能对大家有所帮助。这里整理了ArcGIS Editor for OSM从10.0到_arcgis editor for osm

MFC程序框架的剖析 .-程序员宅基地

文章浏览阅读415次。1,寻找WinMain人口:在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码。路径:MFC|SRC|APPMODUL.CPP:_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){ // call shared/exported Wi

Docker:Window上的Boot2Docker安装和入门-程序员宅基地

文章浏览阅读7.9k次。最近在研究Devops,目前最热门的Docker先研究下,由于公司虚拟机申请IP麻烦,先在工作机器上安装一个Windows版本的。 Docker虽然是Linux内核,但是官方还是支持了Windows和OS X。 Boot2Docker官方下载地址:https://github.com/boot2docker/windows-installer/releases Boot2Docker官_boot2docker

随便推点

ssm 课程资源库APP 计算机专业毕业设计源码23834-程序员宅基地

文章浏览阅读1k次,点赞23次,收藏11次。按照课程资源库APP的角色,我划分为了学生用户、教师用户和管理员这三大部分。学生用户管理模块:(1)用户注册登录:用户注册为用户并登录课程资源库APP;用户对个人信息的增删改查,比如个人资料,密码修改。(2)网站公告:当用户点击“网站公告”这一菜单按钮,会显示管理员在后台发布的所有的公告信息,可以查看详情;(3)课程资讯:用户进行资讯的阅览,查看管理者发布的课程资讯信息。(4)作业信息:当用户点击“作业信息”这一菜单按钮,会显示管理员在后台发布的所有的作业信息,支持通过关键词对作业信息进行搜索..

揭开“定点攻击”的神秘面纱_定点挖掘攻击-程序员宅基地

文章浏览阅读1.1k次。近来,专门利用热门软件漏洞来攻击单一特定对象的恶意软件攻击越来越普遍。在颇为知名的「Aurora」恶意软件攻击 Google 以及至少其他二十多家公司之前,锁定单一目标的恶意软件攻击就已经相当普遍,而且不断入侵政府机关、军事单位、民间企业、教育机构以及一般民间网络。虽然美国政府与相关网络遭到此类攻击已不是新闻,但越来越多其他国家的政府和民间机构也面临了同样的威胁。_定点挖掘攻击

宁波甬江职业学校计算机实,宁波中职学校有哪些 前20排名-程序员宅基地

文章浏览阅读108次。一、招生专业专业代码专业名称专业性质学制人数599精密模具智能制造技师六年80600精密模具智能制造高级工五年40601智能制造高级工五年406023d打印技术应用高级工五年40603电气自动化设备安装与维修技师六年120604工业机器人应用与维护技师六年40605电气自动化设备安装与维修高级工五年...技校中专招生开设的专业一、招生专业1.尖端数控(数控加工)六年制  培养具有本专业扎实理论基础..._甬江职业学校有哪些专业

Python生成图形验证码_python图形验证码生成模块-程序员宅基地

文章浏览阅读486次,点赞2次,收藏2次。1、安装Pillow:pip install Pillow(anaconda3自带)2、代码实现from pil import Image, ImageDraw, ImageFont# 引入随机函数模块import random# 定义变量,用于画面的背景色、宽、高bgcolor = (random.randrange(20, 100), random.randrange( ..._python图形验证码生成模块

Unity Shader之几何着色器(Geometry Shader)实现面片飞散的爆炸效果_shader 特效-程序员宅基地

文章浏览阅读2.6k次,点赞6次,收藏43次。前言上篇文章初学集合着色器实现了草地效果,这篇再次使用GS实现一个“爆炸效果”。为什么要加上引号呢,因为实现的其实不是一个传统的爆炸效果,更类似于面片向外扩散消失的一种科幻效果,其实通过修改面片大小,颜色和扩散方向,还可以模拟复仇者联盟三最后人化为灰烬的效果。为什么要实现这个效果呢,实际上我最早知道几何着色器是下载了一个K神实现的开源demo,然后看到了一个非常酷炫的传送特效。当时我第一感..._shader 特效

Redis 配置文件 redis.conf_redis.conf --loadmodule-程序员宅基地

文章浏览阅读293次。Redis各个版本的配置文件#Redis配置文件示例。##注意,为了读取配置文件,Redis必须是#以文件路径作为第一个参数开头:##./redis-server /path/to/redis.conf#关于单位的注释:需要内存大小时,可以指定#以通常的1k 5GB 4M格式,依此类推:##1k => 1000字节#1kb => 1024字节#1m => 1000000字节#1mb => 1024 * 1024字节#1g => 1000000000_redis.conf --loadmodule

推荐文章

热门文章

相关标签