卷积运算的优化 - Im2Col

前言

在卷积网络中,卷积运算的运算量是巨大的,如果使用Naive的for循环来完成卷积运算,真的是很Naive。而另一方面,无论是CPU还是GPU都对矩阵运算有着很好的支持和优化,那么,将卷积运算转化为矩阵运算就能很好的提升性能。

Im2Col - Image To Column

Im2Col将输入"图片"中卷积核扫过的区域转化为列向量输出。经过Im2Col函数处理后,卷积运算就可以转化为卷积核与这些列向量之间的点乘运算。


Im2Col运算过程[1]

Im2Col的算法实现

以单通道,步长为1为例,实现代码如下:

x_pad = np.pad(x, pad, 'constant')
i0 = np.repeat(np.arange(out_height), out_width).reshape(-1,1)
i1 = np.tile(np.arange(filter_height), filter_width)
i = i0 + i1
j0 = np.tile(np.arange(out_width), out_height).reshape(-1,1)
j1 = np.repeat(np.arange(filter_width),filter_height)
j = j0 + j1
cols = x_pad[i, j]

可以通过观察卷积核运动过程中横纵坐标的变化规律

i - 横坐标 <i = i0 + i1>
0 1 2 0 1 2 0 1 2 | < i1
0 1 2 0 1 2 0 1 2 - 第一行卷积扫过的横坐标
0 1 2 0 1 2 0 1 2 |
-------------------
1 2 3 1 2 3 1 2 3 |
1 2 3 1 2 3 1 2 3 - 第二行卷积扫过的横坐标
1 2 3 1 2 3 1 2 3 |
-------------------
2 3 4 2 3 4 2 3 4 |
2 3 4 2 3 4 2 3 4 - 第三行卷积扫过的横坐标
2 3 4 2 3 4 2 3 4 |
^
i0

j - 纵坐标 <j = j0 + j1>
0 0 0 1 1 1 2 2 2 | < j1
1 1 1 2 2 2 3 3 3 - 第一行卷积扫过的纵坐标
2 2 2 3 3 3 4 4 4 | 
-------------------
0 0 0 1 1 1 2 2 2 |
1 1 1 2 2 2 3 3 3 - 第二行卷积扫过的纵坐标
2 2 2 3 3 3 4 4 4 |
-------------------
0 0 0 1 1 1 2 2 2 |
1 1 1 2 2 2 3 3 3 - 第三行卷积扫过的纵坐标
2 2 2 3 3 3 4 4 4 | 
^
j0

对于步长大于1以及多通道的情况可以在此基础上进一步扩展。

后记

一开始也是尝试了用几层for循环实现卷积运算,效率低的令人发指,使用Im2Col之后,卷积运算速度提升巨大,果然是真香。

参考文献

[1]https://blog.csdn.net/u013498583/article/details/79414225

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容