为什么在 Keras 中 CNN 的训练速度比完全连接的 MLP 慢?

Jor*_*Val 6 neural-network theano conv-neural-network keras

我查看了来自 Keras 的以下示例:

MNIST 中的 MLP:https : //github.com/fchollet/keras/blob/master/examples/mnist_mlp.py

MNIST 中的 CNN:https : //github.com/fchollet/keras/blob/master/examples/mnist_cnn.py

我在 CPU 上的 Theano 中运行两者。在 MLP 中,我每个 epoch的平均时间约为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
Run Code Online (Sandbox Code Playgroud)

在 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
Run Code Online (Sandbox Code Playgroud)

然而,这里的平均时间大约是每个 epoch 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
Run Code Online (Sandbox Code Playgroud)

即使有大约 6000 个参数,现在每个 epoch的时间是28 秒!!

为什么是这样?直观地说,优化应该只取决于变量的数量和梯度的计算(由于相同的批次大小应该是相似的)。

对此有所了解吗?谢谢

Den*_*ker 5

我假设所有卷积运算的内核大小为 (3x3),输入 2D 数组通道大小为 3。

因为conv2d_36你会有:

  • 3 * 32 = 所有通道的操作次数
  • 26 * 26 = 每个通道的卷积运算数
  • 3 * 3 = 每个卷积的乘法次数

因此,排除所有求和(偏差+内部转换),

  • 因为conv2d_36你会有3 * 32 * 26 * 26 * 3 * 3 =~ 585k乘法运算
  • 对于conv2d_37,类似的32 * 64 * 24 * 24 * 3 * 3 =~ 10.6M乘法运算
  • 因为dense_40没有卷积,所以相当于9216 * 10 = 92k乘法运算。

当我们将所有这些加起来时,~11.3MCNN 的第二个模型有单个乘法运算。

另一方面,如果我们将其展平并应用 MLP,

  • 对于dense_33layer来说,会有28 * 28 * 3 * 512 = 1.2M乘法运算
  • 对于dense_34layer来说,会有512 * 512 = 262k乘法运算
  • 对于dense_35layer来说,会有512 * 10 = 5k乘法运算

当我们总结所有这些时,~1.5M第一个 MLP 模型有单个乘法运算。

因此,仅 CNN 模型的乘法就比 MLP 模型多约 7.5 倍。考虑到层内的开销、求和和内存复制/访问操作等其他操作成本,CNN 模型像您提到的那样慢似乎是完全合理的。


ema*_*ele 1

卷积运算比密集层复杂得多。卷积是将图像的每个元素添加到其局部邻居的过程,并由内核加权。每个卷积本质上都是一个多重嵌套循环。这意味着密集层需要的时间只是卷积层的一小部分。 维基百科有一个关于卷积运算的启发性示例。