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)
代码错误的地方
- InceptionA中第一个branch5x5支路,卷积应该是1x1
- 卷积中经常的做法是用两个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模块拿来用用…
以后有机会再搞吧