GoogleNet网络详解与keras实现

  • GoogleNet网络详解与keras实现

    • GoogleNet系列网络的概览
    • Pascal_VOC数据集
      • 第一层目录
      • 第二层目录
      • 第三层目录
    • InceptionV1模块介绍
    • Inception的架构
    • GoogleNet的图片
    • Keras代码实现
      • 为了搭建Inception网络我们使用了以下策略
      • 整个代码的流程如下
    • 实验结果
    • 实验结果分析
    • 本博客相关引用

本博客旨在给经典的GoogleNet网络进行详解与代码实现,如有不足或者其他的见解,请在本博客下面留言。

GoogleNet系列网络的概览

  1. InceptionV1,通过把不同尺寸的卷积核如1x1,3x3,5x5进行堆叠增加了网络对不同尺度的适应性。并且通过在3x3的网络,5x5的网络后加入1x1使得网络的计算复杂度降低,而且提高网络的非线性的程度,基于更强的表征能力。
  2. InceptionV2,加入了BatchNormalization层,减少了Internal Variance Shift。使得每一程的输出的分布都满足指定的高斯分布,可以防止训练集与测试集之间分布的不匹配,还能加快网络收敛速度,防止过拟合。
  3. InceptionV3,在InceptionV3中google将分解的思想用到了极致,把二维卷积核(NxN)拆成两个方向上的一维卷积核(Nx1,1xN)。这样做不仅仅加快了网络的运算速度,而且由于增加网络的层数,使得网络的非线性增加,提高网络的表征能力
  4. InceptionV4,尝试着把Inception的结构与Resnet的结构进行结合,并设计了一个更深更加优秀的网络InceptionV4。

在本篇博客中,我们将实现一个类似于InceptionV2的结构,并用VOC2012的数据集进行网络的训练,验证,与测试。为了快速开发,本次我们把Keras作为代码的框架。

Pascal_VOC数据集

Pascal VOC为图像识别,检测与分割提供了一整套标准化的优秀的数据集,每一年都会举办一次图像识别竞赛。下面是VOC2012,训练集(包括验证集)的下载地址。

VOC2012里面有20类物体的图片,图片总共有1.7万张。我把数据集分成了3个部分,训练集,验证集,测试集,比例为8:1:1。
下面是部分截图:

第一层目录


第二层目录


第三层目录


接着我们使用keras代码来使用这个数据集,代码如下:

IM_WIDTH=224 #图片宽度
IM_HEIGHT=224 #图片高度
batch_size=32 #批的大小#train data
train_datagen = ImageDataGenerator(rotation_range=30, width_shift_range=0.2,height_shift_range=0.2,shear_range=0.2,zoom_range=0.2,horizontal_flip=True,featurewise_center=True
)train_generator = train_datagen.flow_from_directory(train_root,target_size=(IM_WIDTH, IM_HEIGHT),batch_size=batch_size,
)#vaild data
vaild_datagen = ImageDataGenerator(rotation_range=30,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.2,zoom_range=0.2,horizontal_flip=True,featurewise_center=True
)
vaild_generator = train_datagen.flow_from_directory(vaildation_root,target_size=(IM_WIDTH, IM_HEIGHT),batch_size=batch_size,
)#test data
test_datagen = ImageDataGenerator(rotation_range=30,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.2,zoom_range=0.2,horizontal_flip=True,featurewise_center=True
)
test_generator = train_datagen.flow_from_directory(test_root,target_size=(IM_WIDTH, IM_HEIGHT),batch_size=batch_size,
)

我使用了3个ImageDataGenerator,分别来使用训练集,验证集与测试集的数据。使用ImageDataGenerator需要导入相应的模块,==from keras.preprocessing.image import ImageDataGenerator==。ImageDataGenrator可以用来做数据增强,提高模型的鲁棒性.它里面提供了许多变换,包括图片旋转,对称,平移等等操作。里面的flow_from_directory方法可以从相应的目录里面批量获取图片,这样就可以不用一次性读取所有图片(防止内存不足)。

InceptionV1模块介绍

要想理解Googlenet的结构,第一步必须先知道Inception的结构,因为它是由多个Inception的结构组合而成的。如下图Fig.2所示,(a)表示朴素的版本的inception v1示意图,(b)表示降维版本的Inception v1示意图。

Inception的主要思想基于——一个卷积网络里面的局部稀疏最优结构往往可以由简单可复用的密集组合来近似或者替代。就像(a)里面,1x1,3x3,5x5的卷积层,与3x3的池化层的组合一个inception。这样做的几点说明:

  • 不同尺寸的卷积核可以提取不同尺度的信息。
  • 采用1x1,3x3,5x5可以方便对齐,padding分别为0,1,2就可以对齐。
  • 由于池化层在CNN网络里面的成功运用,也把池化层当做组合的一部分。
  • 由于Googlenet是好几个Inception模块的堆叠,而且往往越后面的Inception模块提取的是更加高级抽象的特征,而由于高级抽象的特征的时域联系会降低。(在这里加上一点个人理解,当提取的特征比较简单,比如边缘,轮廓的时候,往往只需要提取某个像素附近的几个像素就行了,这时卷积核比较小,没有问题。但是当提取的特征变得复杂的时候,比如提取的是人的鼻子,耳朵的时候,需要的可能就是某个像素旁边几十或者几百个像素了。当然我说的这些像素指的是特征图里面的像素。)因此为了获取这些高级信息,我们在后面的Inception模块里面需要增大3x3,5x5这些大卷积核的比例。

但是这么做,问题又来了,如果提高大卷积核的比例,那么这会意味着计算复杂度的飙升。为此,google的工程师们又提出(b)的这个Inception结构。

Inception的架构

下面的Table.1给出了Googlenet是怎么由Inception模块和一些传统的卷积层与池化层构成的。比较Inception(3a)和Inception(5b),我们可以看到大卷积核的滤波器的个数的比例已经提高了。最后需要注意两点,该网络的使用了avg pool来替代第一层全连接层,大大降低了参数的个数。后面在avg pool后面加入全连接层则是为了方便微调的操作。

GoogleNet的图片

根据上面的表格我们可以画出这样的一幅图。

Keras代码实现

#-*- coding: UTF-8 -*-from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D, ZeroPadding2D
from keras.layers import Flatten, Dense, Dropout,BatchNormalization
from keras.layers import Input, concatenate
from keras.models import Model,load_model
from keras.preprocessing.image import ImageDataGenerator
from keras.utils import plot_model,np_utils
from keras import regularizers
import keras.metrics as metric
import os# Global Constants
NB_CLASS=20
LEARNING_RATE=0.01
MOMENTUM=0.9
ALPHA=0.0001
BETA=0.75
GAMMA=0.1
DROPOUT=0.4
WEIGHT_DECAY=0.0005
LRN2D_NORM=True
DATA_FORMAT='channels_last' # Theano:'channels_first' Tensorflow:'channels_last'
USE_BN=True
IM_WIDTH=224
IM_HEIGHT=224
EPOCH=50train_root='/home/faith/keras/dataset/traindata/'
vaildation_root='/home/faith/keras/dataset/vaildationdata/'
test_root='/home/faith/keras/dataset/testdata/'IM_WIDTH=224
IM_HEIGHT=224
batch_size=32#train data
train_datagen = ImageDataGenerator(rotation_range=30,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.2,zoom_range=0.2,horizontal_flip=True,featurewise_center=True
)
train_generator = train_datagen.flow_from_directory(train_root,target_size=(IM_WIDTH, IM_HEIGHT),batch_size=batch_size,
)#vaild data
vaild_datagen = ImageDataGenerator(rotation_range=30,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.2,zoom_range=0.2,horizontal_flip=True,featurewise_center=True
)
vaild_generator = train_datagen.flow_from_directory(vaildation_root,target_size=(IM_WIDTH, IM_HEIGHT),batch_size=batch_size,
)#test data
test_datagen = ImageDataGenerator(rotation_range=30,width_shift_range=0.2,height_shift_range=0.2,shear_range=0.2,zoom_range=0.2,horizontal_flip=True,featurewise_center=True
)
test_generator = train_datagen.flow_from_directory(test_root,target_size=(IM_WIDTH, IM_HEIGHT),batch_size=batch_size,
)#normalization
def conv2D_lrn2d(x,filters,kernel_size,strides=(1,1),padding='same',data_format=DATA_FORMAT,dilation_rate=(1,1),activation='relu',use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,kernel_constraint=None,bias_constraint=None,lrn2d_norm=LRN2D_NORM,weight_decay=WEIGHT_DECAY):#l2 normalizationif weight_decay:kernel_regularizer=regularizers.l2(weight_decay)bias_regularizer=regularizers.l2(weight_decay)else:kernel_regularizer=Nonebias_regularizer=Nonex=Conv2D(filters=filters,kernel_size=kernel_size,strides=strides,padding=padding,data_format=data_format,dilation_rate=dilation_rate,activation=activation,use_bias=use_bias,kernel_initializer=kernel_initializer,bias_initializer=bias_initializer,kernel_regularizer=kernel_regularizer,bias_regularizer=bias_regularizer,activity_regularizer=activity_regularizer,kernel_constraint=kernel_constraint,bias_constraint=bias_constraint)(x)if lrn2d_norm:#batch normalizationx=BatchNormalization()(x)return xdef inception_module(x,params,concat_axis,padding='same',data_format=DATA_FORMAT,dilation_rate=(1,1),activation='relu',use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,kernel_constraint=None,bias_constraint=None,lrn2d_norm=LRN2D_NORM,weight_decay=None):(branch1,branch2,branch3,branch4)=paramsif weight_decay:kernel_regularizer=regularizers.l2(weight_decay)bias_regularizer=regularizers.l2(weight_decay)else:kernel_regularizer=Nonebias_regularizer=None#1x1pathway1=Conv2D(filters=branch1[0],kernel_size=(1,1),strides=1,padding=padding,data_format=data_format,dilation_rate=dilation_rate,activation=activation,use_bias=use_bias,kernel_initializer=kernel_initializer,bias_initializer=bias_initializer,kernel_regularizer=kernel_regularizer,bias_regularizer=bias_regularizer,activity_regularizer=activity_regularizer,kernel_constraint=kernel_constraint,bias_constraint=bias_constraint)(x)#1x1->3x3pathway2=Conv2D(filters=branch2[0],kernel_size=(1,1),strides=1,padding=padding,data_format=data_format,dilation_rate=dilation_rate,activation=activation,use_bias=use_bias,kernel_initializer=kernel_initializer,bias_initializer=bias_initializer,kernel_regularizer=kernel_regularizer,bias_regularizer=bias_regularizer,activity_regularizer=activity_regularizer,kernel_constraint=kernel_constraint,bias_constraint=bias_constraint)(x)pathway2=Conv2D(filters=branch2[1],kernel_size=(3,3),strides=1,padding=padding,data_format=data_format,dilation_rate=dilation_rate,activation=activation,use_bias=use_bias,kernel_initializer=kernel_initializer,bias_initializer=bias_initializer,kernel_regularizer=kernel_regularizer,bias_regularizer=bias_regularizer,activity_regularizer=activity_regularizer,kernel_constraint=kernel_constraint,bias_constraint=bias_constraint)(pathway2)#1x1->5x5pathway3=Conv2D(filters=branch3[0],kernel_size=(1,1),strides=1,padding=padding,data_format=data_format,dilation_rate=dilation_rate,activation=activation,use_bias=use_bias,kernel_initializer=kernel_initializer,bias_initializer=bias_initializer,kernel_regularizer=kernel_regularizer,bias_regularizer=bias_regularizer,activity_regularizer=activity_regularizer,kernel_constraint=kernel_constraint,bias_constraint=bias_constraint)(x)pathway3=Conv2D(filters=branch3[1],kernel_size=(5,5),strides=1,padding=padding,data_format=data_format,dilation_rate=dilation_rate,activation=activation,use_bias=use_bias,kernel_initializer=kernel_initializer,bias_initializer=bias_initializer,kernel_regularizer=kernel_regularizer,bias_regularizer=bias_regularizer,activity_regularizer=activity_regularizer,kernel_constraint=kernel_constraint,bias_constraint=bias_constraint)(pathway3)#3x3->1x1pathway4=MaxPooling2D(pool_size=(3,3),strides=1,padding=padding,data_format=DATA_FORMAT)(x)pathway4=Conv2D(filters=branch4[0],kernel_size=(1,1),strides=1,padding=padding,data_format=data_format,dilation_rate=dilation_rate,activation=activation,use_bias=use_bias,kernel_initializer=kernel_initializer,bias_initializer=bias_initializer,kernel_regularizer=kernel_regularizer,bias_regularizer=bias_regularizer,activity_regularizer=activity_regularizer,kernel_constraint=kernel_constraint,bias_constraint=bias_constraint)(pathway4)return concatenate([pathway1,pathway2,pathway3,pathway4],axis=concat_axis)def create_model():#Data format:tensorflow,channels_last;theano,channels_lastif DATA_FORMAT=='channels_first':INP_SHAPE=(3,224,224)img_input=Input(shape=INP_SHAPE)CONCAT_AXIS=1elif DATA_FORMAT=='channels_last':INP_SHAPE=(224,224,3)img_input=Input(shape=INP_SHAPE)CONCAT_AXIS=3else:raise Exception('Invalid Dim Ordering')x=conv2D_lrn2d(img_input,64,(7,7),2,padding='same',lrn2d_norm=False)x=MaxPooling2D(pool_size=(3,3),strides=2,padding='same',data_format=DATA_FORMAT)(x)x=BatchNormalization()(x)x=conv2D_lrn2d(x,64,(1,1),1,padding='same',lrn2d_norm=False)x=conv2D_lrn2d(x,192,(3,3),1,padding='same',lrn2d_norm=True)x=MaxPooling2D(pool_size=(3,3),strides=2,padding='same',data_format=DATA_FORMAT)(x)x=inception_module(x,params=[(64,),(96,128),(16,32),(32,)],concat_axis=CONCAT_AXIS) #3ax=inception_module(x,params=[(128,),(128,192),(32,96),(64,)],concat_axis=CONCAT_AXIS) #3bx=MaxPooling2D(pool_size=(3,3),strides=2,padding='same',data_format=DATA_FORMAT)(x)x=inception_module(x,params=[(192,),(96,208),(16,48),(64,)],concat_axis=CONCAT_AXIS) #4ax=inception_module(x,params=[(160,),(112,224),(24,64),(64,)],concat_axis=CONCAT_AXIS) #4bx=inception_module(x,params=[(128,),(128,256),(24,64),(64,)],concat_axis=CONCAT_AXIS) #4cx=inception_module(x,params=[(112,),(144,288),(32,64),(64,)],concat_axis=CONCAT_AXIS) #4dx=inception_module(x,params=[(256,),(160,320),(32,128),(128,)],concat_axis=CONCAT_AXIS) #4ex=MaxPooling2D(pool_size=(3,3),strides=2,padding='same',data_format=DATA_FORMAT)(x)x=inception_module(x,params=[(256,),(160,320),(32,128),(128,)],concat_axis=CONCAT_AXIS) #5ax=inception_module(x,params=[(384,),(192,384),(48,128),(128,)],concat_axis=CONCAT_AXIS) #5bx=AveragePooling2D(pool_size=(7,7),strides=1,padding='valid',data_format=DATA_FORMAT)(x)x=Flatten()(x)x=Dropout(DROPOUT)(x)x=Dense(output_dim=NB_CLASS,activation='linear')(x)x=Dense(output_dim=NB_CLASS,activation='softmax')(x)return x,img_input,CONCAT_AXIS,INP_SHAPE,DATA_FORMATdef check_print():# Create the Modelx,img_input,CONCAT_AXIS,INP_SHAPE,DATA_FORMAT=create_model()# Create a Keras Modelmodel=Model(input=img_input,output=[x])model.summary()# Save a PNG of the Model Buildplot_model(model,to_file='GoogLeNet.png')model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['acc',metric.top_k_categorical_accuracy])print 'Model Compiled'return modelif __name__=='__main__':if os.path.exists('inception_1.h5'):model=load_model('inception_1.h5')else:model=check_print()model.fit_generator(train_generator,validation_data=vaild_generator,epochs=EPOCH,steps_per_epoch=train_generator.n/batch_size,validation_steps=vaild_generator.n/batch_size)model.save('inception_1.h5')model.metrics=['acc',metric.top_k_categorical_accuracy]loss,acc,top_acc=model.evaluate_generator(test_generator,steps=test_generator.n/batch_size)print 'Test result:loss:%f,acc:%f,top_acc:%f'%(loss,acc,top_acc)

为了搭建Inception网络,我们使用了以下策略:

  • 使用了inception_module这个函数构造每个inception模块,里面有4路,分别对应着1x1,(1x1,3x3),(1x1,5x5),(3x3,1x1) 这四路。
  • 使用了3个正则化的手段,分别是L2正则化,BatchNormalization,dropout,来防止模型过拟合。
  • create_model这个函数里面的网络搭建可以参考Tabel.1,可以边看表里面的具体参数边搭网络。

整个代码的流程如下:

  • 导入相应库
  • 模型参数设置以及其它配置
  • 生成训练集,测试集,验证集的三个迭代器
  • Inception module函数的编写
  • create model函数编写,仿照Table.1
  • 模型编译,画出模型的图
  • 模型训练与验证
  • 模型保存
  • 模型在测试集上测试

实验结果

dataset loss acc top5-acc
Training set 1.85 39.9% 85.3%
Vaildation set 2.01 36.6% 82.0%
Testing set 2.08 35.7% 78.1%

实验结果分析

我们可以发现模型最后在测试集上的效果与训练集上的效果有一定程度上的差距,模型出现了一点过拟合。以下是个人对此问题的一些分析:由于采用了L2正则化,BatchNormalization,Dropout等等方法,但是还是出现了过拟合,可能是由于VOC数据比较少,20类物体才1.7万张,相当于每个物体850张左右,要想取得比较好的效果,每个类别物体的图片至少得几千张。所以可以通过降低网络层数,增加数据量,增加训练次数等手段来提高网络的性能。

本博客相关引用

以下是本博客的引用,再次本人对每个引用的作者表示感谢。读者如果对googlenet这个网络仍然存在一些疑虑,或者想要有更深的理解,可以参考以下的引用。

引用博客1

引用博客2

引用博客3

引用文献1:InceptionV1

引用文献2:InceptionV2

引用文献3:InceptionV3

引用文献4:InceptionV4!

GoogleNet网络详解与keras实现相关推荐

  1. ResNet网络详解与keras实现

    ResNet网络详解与keras实现 ResNet网络详解与keras实现 Resnet网络的概览 Pascal_VOC数据集 第一层目录 第二层目录 第三层目录 梯度退化 Residual Lear ...

  2. GoogLeNet网络详解并使用pytorch搭建模型

    1.GoogLeNet网络详解 网络中的创新点: (1)引入了Inception结构(融合不同尺度的特征信息) (2)使用1x1的卷积核进行降维以及映射处理 (虽然VGG网络中也有,但该论文介绍的更详 ...

  3. 【深度神经网络】五、GoogLeNet网络详解

    概要 本篇文章的重点就是主要介绍GoogLeNet的网络架构,这个网络架构于2014年由Google团队提出.GoogLeNet的论文为:Going deeper with convolutions. ...

  4. GoogLeNet网络详解与模型搭建

    文章目录 1 模型介绍 2 GoogLeNet详解 Inception模块 辅助分类器 3 GoogLeNet网络结构 4 Pytorch模型搭建代码 1 模型介绍 GoogLeNet是2014年Ch ...

  5. GoogLenet网络详解

    GoogLenet VGG在2014年由牛津大学著名研究组vGG (Visual Geometry Group)提出,斩获该年lmageNet竞赛中Localization Task (定位任务)第一 ...

  6. 第十六章 ConvNeXt网络详解

    系列文章目录 第一章 AlexNet网络详解 第二章 VGG网络详解 第三章 GoogLeNet网络详解 第四章 ResNet网络详解 第五章 ResNeXt网络详解 第六章 MobileNetv1网 ...

  7. Keras深度学习实战(22)——生成对抗网络详解与实现

    Keras深度学习实战(22)--生成对抗网络详解与实现 0. 前言 1. 生成对抗网络原理 2. 模型分析 3. 利用生成对抗网络生成手写数字图像 小结 系列链接 0. 前言 生成对抗网络 (Gen ...

  8. ResNet网络详解并使用pytorch搭建模型、并基于迁移学习训练

    1.ResNet网络详解 网络中的创新点: (1)超深的网络结构(突破1000层) (2)提出residual模块 (3)使用Batch Normalization加速训练(丢弃dropout) (1 ...

  9. MobileNetv1、v2网络详解、使用pytorch搭建模型MobileNetv2并基于迁移学习训练

    1.MobileNetv1网络详解 传统卷积神经网络专注于移动端或者嵌入式设备中的轻量级CNN网络,相比于传统卷积神经网络,在准确率小幅降低的前提下大大减少模型参数与运算量.(相比VGG16准确率减少 ...

最新文章

  1. python request.get()_使用Python request.get解析无法一次加载的html代码
  2. 【Qt】获取、比较Qt版本的宏和函数
  3. setsockopt
  4. Dockerfile 中 配置安装 php 扩展
  5. 托管非托管_如何利用Kubernetes的力量来优化您的托管成本
  6. 微信开发者配置服务器信息,【开发】微信验证开发者接口配置信息,服务器没有正确响应Token....
  7. Atitiit java通过Exchange协议同步note 记事本 目录 1.1.1. 使用EWS(Exchange Web Service)协议读取邮件、发送邮件 1 最新问题 1 热门问题 1
  8. android使用Charles抓包https请求
  9. delphi技巧--分离汉字和英文字母
  10. python调用有道翻译_python调用有道云翻译api
  11. Fibonacci费氏数列
  12. php开发中处理emoji表情和颜文字的兼容问题
  13. 【面试】数据分析助理面试
  14. bandzip屏蔽广告
  15. Win7 64位重装系统之后,IE11安装失败、升级失败之解决办法
  16. php mongodb的pecl,PECL方式安装php-mongodb扩展步骤详解
  17. 柯西飞行,瑞利飞行,莱维飞行,重尾分布、随机游走
  18. 整数分解 费马方法c语言,因数分解(费马的方法)
  19. KEIL MDK中的RO、RW和ZI
  20. python 运行时出现fixture xxx not found

热门文章

  1. UC浏览器APP如何卸载插件
  2. 大一计算机实验报告7,计算机一级实验报告7.doc
  3. 网络协议,各层功能,各层协议
  4. Linux编译soci库,Soci库linux下的编译方法
  5. linux openh264 编译,在Linux下为Android构建openh264
  6. ZooKeeper 的工作流程
  7. ubuntu系统下Jenkins和tomcat的安装与配置
  8. altium导出钻孔文件_[Altium Designer 学习]怎样输出Gerber文件和钻孔文件
  9. mysql 数据库访问层_MYSQL数据库访问层
  10. python 如何匹配列表中某个单词_Python中部分指定单词的最佳匹配项