keras实现Inception模块

1.Conv_bn的实现

也就是说,这里默认是卷积后(默认relu) + 一个BN层
另外,这里的形式参数的默认值,取的太巧妙了
反正是’same’模式,高和宽不会改变
当然,你想改的时候,只要改成valid就行了 。 像步长也是可以改的,但是卷积层步长变化的比较少

padding = (f-1)/s 

通通只要在这个函数完成就行了

函数的封装性真的强大

from keras.models import Model
from keras.layers import Dense,add,Input,Flatten,Conv2D,MaxPooling2D,Dropout,BatchNormalization
from keras.layers.merge import concatenate

def Conv2d_BN(x, filters,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(filters,kernel_size,padding=padding,strides=strides,activation='relu',name=conv_name)(x)
    x = BatchNormalization(axis=3,name=bn_name)(x)
    return x

1.1 不改H和W示例

x = Input(shape=(256,256,3))
y = Conv2d_BN(x,16,(3,3))
model = Model(inputs=x, outputs=y)
model.summary()

输入 + 卷积 + BN层
在这里插入图片描述

1.2 改H 和 W

x = Input(shape=(256,256,3))
y = Conv2d_BN(x,16,(5,5),'Valid')

model = Model(inputs=x, outputs=y)

model.summary()

因为设置了Valid模式,所以就缩减了H和W
在这里插入图片描述

2.Inception模块简单示例

代码的结构图
在这里插入图片描述

b1_1x1 = Conv2d_BN(x,16,(1,1))
b1_3x3 = Conv2d_BN(b1_1x1,32,(3,3))

b2_1x1 = Conv2d_BN(x,16,(1,1))model = Model(inputs=x, outputs=out)

b2_5x5 = Conv2d_BN(b2_1x1,32,(5,5))

b3_maxpool = MaxPooling2D((3,3),strides=(1,1),padding='same')(x)
b3_1x1 = Conv2d_BN(b3_maxpool,32,(1,1))

out = [b1_3x3,b2_5x5,b3_1x1]
out = concatenate(out,axis=-1)
model.summary()

如图,最后实现的拼接效果
在这里插入图片描述

3.GoogleNet简介

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

3.1 InceptionA

实际上采用什么样的Inception Block最好,需要根据你的输出需要来定。比如要输出35*35尺寸的特征图,你不用费心调了,下面这个Inception Block最好:
在这里插入图片描述
注意了,InceptionA模块,不改变H和W,只改变C,所以所有的卷积s=1,pad=‘same’
所有的池化,s=1, 这个比较少见

然后,由于Conv2d_BN是封装了的,x写在了里面
而,MaxPooling2D是写在外面的(x)

代码错误的地方

  1. InceptionA中第一个branch5x5支路,卷积应该是1x1
  2. 卷积中经常的做法是用两个3x3的卷积,代替一个5x5的卷积,这两种情况具有共同的感受野,但是前者参数更少。这个是VGG16里的常用做法 (GoogleNet好像就是5x5 ,但是不同Version的,所以这算不上错误)
from keras.models import Model
from keras.layers import Dense,add,Input,Flatten,Conv2D,MaxPooling2D,Dropout,BatchNormalization
from keras.layers.merge import concatenate


def Conv2d_BN(x, filters,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(filters,kernel_size,padding=padding,strides=strides,activation='relu',name=conv_name)(x)
    x = BatchNormalization(axis=3,name=bn_name)(x)
    return x

def InceptionA(x,filters):
    branch1x1 = Conv2d_BN(x,filters,(1,1),name='branch_1x1')
 
    branch3x3 = Conv2d_BN(x,filters,(1,1),name='branch_3x3_1')
    branch3x3 = Conv2d_BN(branch3x3,filters,(3,3),name='branch_3x3_2')
 
    branch5x5 = Conv2d_BN(x,filters,(5,5),name='branch_5x5_1')
    branch5x5 = Conv2d_BN(branch5x5,filters,(5,5),name='branch_5x5_2')
 
    branchpool = MaxPooling2D(pool_size=(3,3),strides=(1,1),padding='same',name='branchpool_1')(x)
    branchpool = Conv2d_BN(branchpool,filters,(1,1),name='branchpool_2')
 
    out = [branch1x1,branch3x3,branch5x5,branchpool]
    out = concatenate(out,axis=-1)
    return out

x = Input(shapxe=(64,64,3))
y = InceptionA(x,32)
model = Model(inputs=x, outputs=y)
model.summary()

如图中可以看出,每个层级的输出都是32个,但是这个是可以改的
在这里插入图片描述

修改

另外,filters可以不用写死…
也不一定要写数组
因为,可以用数字代替

def Inception(x):


	return out

修改后的

def InceptionA(x,filters):
    branch1x1 = Conv2d_BN(x,filters,(1,1),name='branch_1x1')
 
    branch3x3 = Conv2d_BN(x,filters,(1,1),name='branch_3x3_1')
    branch3x3 = Conv2d_BN(branch3x3,filters,(3,3),name='branch_3x3_2')
    
    # 用两个3x3 代替5x5
    branch5x5 = Conv2d_BN(x,filters,(1,1),name='branch_5x5_1')
    branch5x5 = Conv2d_BN(branch5x5,filters,(3,3),name='branch_5x5_2')
    branch5x5 = Conv2d_BN(branch5x5,filters,(3,3),name='branch_5x5_3')
 
    branchpool = MaxPooling2D(pool_size=(3,3),strides=(1,1),padding='same',name='branchpool_1')(x)
    branchpool = Conv2d_BN(branchpool,filters,(1,1),name='branchpool_2')
 
    out = [branch1x1,branch3x3,branch5x5,branchpool]
    out = concatenate(out,axis=-1)
    return out

3.1.1 如果更改不同的输出

加一个filters=[ ] 数组就好了,控制不同层级的滤波器的个数

3.2 InceptionB

如果要输出17*17尺寸的特征图?没关系,这个Inception Block最好:
在这里插入图片描述

4.GoogleNet结构

输入:(224,224,3)
在这里插入图片描述
网络大小变化,详细的描述

5 总结

最近忙着毕业,确实没时间深入GoogleNet
只是想着把Inception模块拿来用用…
以后有机会再搞吧

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值