我查看了以下来自Keras的例子:
MNIST的MLP:https://github.com/fchollet/keras/blob/master/examples/mnist_mlp.py
MNN的CNN:https://github.com/fchollet/keras/blob/master/examples/mnist_cnn.py
我在Theano上运行CPU。在MLP中,我的平均时间大约<16>每个时期,共有669,706个参数:
Layer (type) Output Shape Param #
=================================================================
dense_33 (Dense) (None, 512) 401920
_________________________________________________________________
dropout_16 (Dropout) (None, 512) 0
_________________________________________________________________
dense_34 (Dense) (None, 512) 262656
_________________________________________________________________
dropout_17 (Dropout) (None, 512) 0
_________________________________________________________________
dense_35 (Dense) (None, 10) 5130
=================================================================
Total params: 669,706.0
Trainable params: 669,706.0
Non-trainable params: 0.0
在CNN中,我从原始代码中删除了最后一个隐藏图层。我还将优化器更改为rmsprop以使两个案例具有可比性,留下以下架构:
Layer (type) Output Shape Param #
=================================================================
conv2d_36 (Conv2D) (None, 26, 26, 32) 320
_________________________________________________________________
conv2d_37 (Conv2D) (None, 24, 24, 64) 18496
_________________________________________________________________
max_pooling2d_17 (MaxPooling (None, 12, 12, 64) 0
_________________________________________________________________
dropout_22 (Dropout) (None, 12, 12, 64) 0
_________________________________________________________________
flatten_17 (Flatten) (None, 9216) 0
_________________________________________________________________
dense_40 (Dense) (None, 10) 92170
=================================================================
Total params: 110,986.0
Trainable params: 110,986.0
Non-trainable params: 0.0
然而,这里的平均时间约为每个时期340秒!即使参数减少了六倍!
为了更详细地了解这一点,我将每层过滤器的数量减少到4,留下以下架构:
Layer (type) Output Shape Param #
=================================================================
conv2d_38 (Conv2D) (None, 26, 26, 4) 40
_________________________________________________________________
conv2d_39 (Conv2D) (None, 24, 24, 4) 148
_________________________________________________________________
max_pooling2d_18 (MaxPooling (None, 12, 12, 4) 0
_________________________________________________________________
dropout_23 (Dropout) (None, 12, 12, 4) 0
_________________________________________________________________
flatten_18 (Flatten) (None, 576) 0
_________________________________________________________________
dense_41 (Dense) (None, 10) 5770
=================================================================
Total params: 5,958.0
Trainable params: 5,958.0
Non-trainable params: 0.0
现在时间 28 s / epoch ,即使有大约6000个参数!!
这是为什么?直观地,优化应该仅取决于变量的数量和梯度的计算(由于相同的批量大小应该相似)。
对此有所了解? 谢谢
答案 0 :(得分:2)
我假设所有卷积运算的内核大小为(3x3),并且输入2D数组通道大小为3。
对于conv2d_36
,您将拥有:
因此,排除所有求和(bias + conv internal),
conv2d_36
,您将进行3 * 32 * 26 * 26 * 3 * 3 =~ 585k
个乘法运算conv2d_37
,类似的32 * 64 * 24 * 24 * 3 * 3 =~ 10.6M
乘法运算dense_40
,因为没有卷积,所以它等于9216 * 10 = 92k
乘法运算。 当我们将它们全部总结时,对于使用CNN的第二个模型,有~11.3M
个单乘法运算。
另一方面,如果我们将其展平并应用MLP,
dense_33
层,将进行28 * 28 * 3 * 512 = 1.2M
个乘法运算dense_34
层,将进行512 * 512 = 262k
个乘法运算dense_35
层,将进行512 * 10 = 5k
个乘法运算当我们总结所有这些时,对于带有MLP的第一个模型,有~1.5M
个单乘法运算。
因此,仅CNN模型的乘法是MLP模型的7.5倍左右。考虑到各层之间的开销,其他操作成本(例如求和和内存复制/访问操作)似乎完全合理,因为CNN模型要像您提到的那样慢。
答案 1 :(得分:0)
卷积操作比密集层复杂得多。 卷积是将图像的每个元素添加到其本地邻居的过程,由内核加权。 每个卷积本质上都是一个多重嵌套循环。这意味着密集层需要相对于卷积层的一小部分时间。 Wikipedia有一个启发卷积操作的启发性例子。