SqueezeNet & SqueezeNext 简介
一、SqueezeNet 模型原理
- 采用 Global Average Pooling 代替 FC 层
- 采用不同于传统的卷积方式,提出
fire module
;fire module 包含两部分:squeeze
层 和expand
层- squeeze 层是一个
1*1
卷积核的卷积层,expand 层是一个1*1
和3*3
卷积核的卷积层,在 expand 层后,要把1*1
和3*3
卷积后得到的 feature map 进行concat
- fire module 有三个可调参数:s1,e1,e3,分别代表卷积核的个数,同时也表示对应输出 feature map 的维数,在论文中提出的 SqueezeNet 结构中,
e1=e3=4s1
- squeeze 层是一个
-
fire module block
的参数量(Params)以及理论计算量(FLOPs)分析?- Params:
- FLOPs:
- 相比较直接使用 的卷积核,参数量和理论计算量都降为原来的
二、SqueezeNet 模型结构及设计思路
- 相同
分辨率
的fire module block
数量前面要少一点,后面要多一点(这里为[2, 2, 4]
),通道数
通常以32
或64
的倍数增加([128, 256, 384-512]
) - 在通道数相同的层之间,添加旁路相加结构(
short-cut
)可以明显提升准确性(top-1 和 top-5 分别提升2.9%
和2.2%
) - 带有卷积的旁路结构可以在任意层之间添加(
1*1 卷积调控 depth
),准确性提升较小,模型增大
三、改进版本之 SqueezeNext
- Low Rank Filters:decompose the convolutions into two separable convolutions of size and
- SqueezeNext Block:减少 C_in ,即在 的卷积前,用两个 的卷积进一步把 input channels 减少
- Fully Connected Layers:在全连接层之前再用一个 bottleneck layer,把 C_in 变小
-
Short-Cut
-
SqueezeNext Block
的参数量(Params)以及理论计算量(FLOPs)分析?- Params:
- FLOPs:
- 相比较直接使用 的卷积核,参数量和理论计算量都降为原来的 ,通道数量相比 SqueezeNet 更小
四、SqueezeNet 模型代码
class SqueezeNet(object):
def __init__(self, inputs, nb_classes=1000, is_training=True):
# conv1
net = tf.layers.conv2d(inputs, 96, [7, 7], strides=[2, 2],
padding="SAME", activation=tf.nn.relu,
name="conv1")
# maxpool1
net = tf.layers.max_pooling2d(net, [3, 3], strides=[2, 2],
name="maxpool1")
# fire2
net = self._fire(net, 16, 64, "fire2")
# fire3
net = self._fire(net, 16, 64, "fire3")
# fire4
net = self._fire(net, 32, 128, "fire4")
# maxpool4
net = tf.layers.max_pooling2d(net, [3, 3], strides=[2, 2],
name="maxpool4")
# fire5
net = self._fire(net, 32, 128, "fire5")
# fire6
net = self._fire(net, 48, 192, "fire6")
# fire7
net = self._fire(net, 48, 192, "fire7")
# fire8
net = self._fire(net, 64, 256, "fire8")
# maxpool8
net = tf.layers.max_pooling2d(net, [3, 3], strides=[2, 2],
name="maxpool8")
# fire9
net = self._fire(net, 64, 256, "fire9")
# dropout
net = tf.layers.dropout(net, 0.5, training=is_training)
# conv10
net = tf.layers.conv2d(net, 1000, [1, 1], strides=[1, 1],
padding="SAME", activation=tf.nn.relu,
name="conv10")
# avgpool10
net = tf.layers.average_pooling2d(net, [13, 13], strides=[1, 1],
name="avgpool10")
# squeeze the axis
net = tf.squeeze(net, axis=[1, 2])
self.logits = net
self.prediction = tf.nn.softmax(net)
def _fire(self, inputs, squeeze_depth, expand_depth, scope):
with tf.variable_scope(scope):
squeeze = tf.layers.conv2d(inputs, squeeze_depth, [1, 1],
strides=[1, 1], padding="SAME",
activation=tf.nn.relu, name="squeeze")
# squeeze
expand_1x1 = tf.layers.conv2d(squeeze, expand_depth, [1, 1],
strides=[1, 1], padding="SAME",
activation=tf.nn.relu, name="expand_1x1")
expand_3x3 = tf.layers.conv2d(squeeze, expand_depth, [3, 3],
strides=[1, 1], padding="SAME",
activation=tf.nn.relu, name="expand_3x3")
return tf.concat([expand_1x1, expand_3x3], axis=3)
五、参考资料
1、纵览轻量化卷积神经网络:SqueezeNet、MobileNet、ShuffleNet、Xception
2、CVPR 2018 高效小网络探密(上)
3、如何评价轻量级深度神经网络 SqueezeNext?