卷积神经网络的复杂度分析

https://zhuanlan.zhihu.com/p/31575074

https://zhuanlan.zhihu.com/p/31575074

https://blog.csdn.net/dcrmg/article/details/79652521

https://blog.csdn.net/laolu1573/article/details/79196160

时间复杂度

时间复杂度即模型的浮点数运算次数, 可用 FLOPs (FLoating-point OPerations) 来衡量.

单个卷积层的时间复杂度

  • $M$ : 每个卷积核输出的特征图谱的边长
  • $K$ : 每个卷积核的边长
  • $C_{in}$ : 每个卷积核的输入通道数
  • $C_{out}$ : 本卷积层具有的卷积核个数, 也即输出通道数

注一: 为了简化表达式, 这里假设输入和输出的特征图谱都是正方形
注二: 同样为了简化表达式, 这里省略了偏置项.

网络整体的时间复杂度

  • $D$ : 神经网络具有的卷积层层数, 也就是网络的深度
  • $l$ : 神经网络的第l层卷积层
  • $C_l$ : 神经网络第l层卷积层的输出通道数, 也就是该层的卷积核个数

示例: 用Numpy实现简单二维卷积:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def conv2d(img, kernel):
height, width, in_channels = img.shape
kernel_height, kernel_width, in_channels, out_channels = kernel.shape
out_height = height - kernel_height + 1
out_width = width - kernel_width + 1
feature_maps = np.zeros(shape=(out_height, out_width, out_channels))
for oc in range(out_channels): # Iterate out_channels (# of kernels)
for h in range(out_height): # Iterate out_height
for w in range(out_width): # Iterate out_width
for ic in range(in_channels): # Iterate in_channels
patch = img[h: h + kernel_height, w: w + kernel_width, ic]
feature_maps[h, w, oc] += np.sum(patch * kernel[:, :, ic, oc])

return feature_maps

空间复杂度

空间复杂度 (访存量) 包含两部分: 总参数量 + 各层的输出特征图谱

  • 参数复杂度: 模型所有带参数的层的参数总量: $O(K^2C_{l-1}C_{l})$
  • 特征图谱复杂度: 实时运行过程的每层计算出的图谱大小: $O(M^2C_l)$

注意, 上面的参数复杂度没有带偏置项, 因为这只是计算复杂度, 而不是精确的参数个数.

复杂度对模型的影响

复杂度的优化

1×1 卷积降维同时优化时间复杂度和空间复杂度

用两个 3×3 卷积 (18个参数) 替代 5×5卷积 (25个参数)

使用 N×1 和 1×N 卷积级联替代 $N×N$ 卷积.