0.摘要
ICLR 2017
开源了但是是用caffe训练好的模型,不方便阅读
squeezenet是高效轻量网络开山之作,提出了三大原则和一个fire模块
1.三大原则
1.1策略一:用1x1 滤镜替换3x3滤镜
因为1x1滤波器的参数比3x3滤波器少9倍。
1.2减少3x3 卷积输入通道的数量
假设有一个卷积层, 它完全由3x3 卷积组成。此层中参数的总数量为:(输入通道数) * (过滤器数) * (3 * 3)
1.3 在网络中推迟下采样的时间, 以便卷积层具有较大的特征图
这样在后期的特征的h和w还是很大的,所以这样的操作虽然会提升网络的精度,但是它有一个非常严重的缺点,即会增加网络的计算量。
2.Fire
2.1Fire Model
一个Fire模块由Squeeze部分和Expand部分组成(在命名上和se网络有点冲突,se网络叫做squeeze和excite)
def fire_model(x, s_1x1, e_1x1, e_3x3, fire_name):
# squeeze part
squeeze_x = Conv2D(kernel_size=(1,1),filters=s_1x1,padding='same',activation='relu',name=fire_name+'_s1')(x)
# expand part
expand_x_1 = Conv2D(kernel_size=(1,1),filters=e_1x1,padding='same',activation='relu',name=fire_name+'_e1')(squeeze_x)
expand_x_3 = Conv2D(kernel_size=(3,3),filters=e_3x3,padding='same',activation='relu',name=fire_name+'_e3')(squeeze_x)
expand = merge([expand_x_1, expand_x_3], mode='concat', concat_axis=3)
return expand
2.2网络结构
开始于一个独立的卷积层(conv1),然后是8个fire模块(fire2-9),最后是一个最终的转换层(conv10)
几个小细节:
fire9之后接了一个rate为0.5的dropout
SqueezeNet中没有全连接层,这借鉴了Network in network的思想
def squeezeNet(x):
conv1 = Conv2D(input_shape = (224,224,3), strides = 2, filters=96, kernel_size=(7,7), padding='same', activation='relu')(x)
poo1 = MaxPool2D((2,2))(conv1)
fire2 = fire_model(poo1, 16, 64, 64,'fire2')
fire3 = fire_model(fire2, 16, 64, 64,'fire3')
fire4 = fire_model(fire3, 32, 128, 128,'fire4')
pool2 = MaxPool2D((2,2))(fire4)
fire5 = fire_model(pool2, 32, 128, 128,'fire5')
fire6 = fire_model(fire5, 48, 192, 192,'fire6')
fire7 = fire_model(fire6, 48, 192, 192,'fire7')
fire8 = fire_model(fire7, 64, 256, 256,'fire8')
pool3 = MaxPool2D((2,2))(fire8)
fire9 = fire_model(pool3, 64, 256, 256,'fire9')
dropout1 = Dropout(0.5)(fire9)
conv10 = Conv2D(kernel_size=(1,1), filters=1000, padding='same', activation='relu')(dropout1)
gap = GlobalAveragePooling2D()(conv10)
return gap
3.实验
做的是分类实验,用的依旧是fasion mnist数据集
对squeezenet做了修改只是用一个fire模块,因为数据集过小,网络太深容易过拟合,鲁棒性大大下降
SqueezeNet(
(features): Sequential(
(0): Conv2d(1, 96, kernel_size=(7, 7), stride=(2, 2))
(1): ReLU(inplace=True)
(2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=True)
(3): Fire(
(squeeze): Conv2d(96, 16, kernel_size=(1, 1), stride=(1, 1))
(squeeze_activation): ReLU(inplace=True)
(expand1x1): Conv2d(16, 64, kernel_size=(1, 1), stride=(1, 1))
(expand1x1_activation): ReLU(inplace=True)
(expand3x3): Conv2d(16, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(expand3x3_activation): ReLU(inplace=True)
)
(4): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=True)
)
(classifier): Sequential(
(0): Dropout(p=0.5, inplace=False)
(1): Conv2d(128, 10, kernel_size=(1, 1), stride=(1, 1))
(2): ReLU(inplace=True)
(3): AdaptiveAvgPool2d(output_size=(1, 1))
)
)
Number of parameter: 0.02M(input resize=none)
Lenet:
Number of parameter: 0.04M(input resize=none)
alexnet:
Number of parameter: 24.74M(input resize=112
)