码迷,mamicode.com
首页 > 其他好文 > 详细

im2col:将卷积运算转为矩阵相乘

时间:2019-08-20 00:44:32      阅读:106      评论:0      收藏:0      [点我收藏+]

标签:document   convert   现在   更新   blank   冗余   ace   提升   hub   

 

im2col:将卷积运算转为矩阵相乘

博客:blog.shinelee.me | 博客园 | CSDN

im2col实现

如何将卷积运算转为矩阵相乘?直接看下面这张图,以下图片来自论文High Performance Convolutional Neural Networks for Document Processing

技术图片im2col
上图为3D卷积的传统计算方式与矩阵乘法计算方式的对比,传统卷积运算是将卷积核以滑动窗口的方式在输入图上滑动,当前窗口内对应元素相乘然后求和得到结果,一个窗口一个结果。相乘然后求和恰好也是向量内积的计算方式,所以可以将每个窗口内的元素拉成向量,通过向量内积进行运算,多个窗口的向量放在一起就成了矩阵,每个卷积核也拉成向量,多个卷积核的向量排在一起也成了矩阵,于是,卷积运算转化成了矩阵运算

 

>>> : 现在是卷积 -> 矩阵乘法?能否尝试各种矩阵乘法,反推卷积形式?
deformable conv 对应的是什么矩阵乘法?

 

下图为转化后的矩阵尺寸,padding为0:

技术图片EmzaRO.png
代码上怎么实现呢?这里参看一下SeetaFaceEngine/FaceIdentification/src/conv_net.cpp 中的代码,与上面的图片对照着看比较直观。













































































src_num个输入,每个尺寸为 src_channels * src_h * src_w,卷积核尺寸为kernel_size = src_channels * kernel_h * kernel_w,将每个输入转化为二维矩阵,尺寸为(dst_h * dst_w) * (kernel_size),可以看到最内层循环在逐行拷贝当前窗口内的元素,窗口大小与卷积核大小相同,一次拷贝kernel_w个元素,一个窗口内要拷贝src_channels*kernel_h次,因此一个窗口共拷贝了kernel_size个元素,共拷贝dst_h * dst_w个窗口,因此输入对应的二维矩阵尺寸为(dst_h * dst_w) * (kernel_size)。对于卷积核,有dst_channels= weight->num();个卷积核,因为是行有先存储,卷积核对应的二维矩阵尺寸为dst_channels*(kernel_size)逻辑上虽然为矩阵乘法,实现时两个矩阵逐行内积即可

优缺点分析

将卷积运算转化为矩阵乘法,从乘法和加法的运算次数上看,两者没什么差别,但是转化成矩阵后,运算时需要的数据被存在连续的内存上,这样访问速度大大提升(cache),同时,矩阵乘法有很多库提供了高效的实现方法,像BLAS、MKL等,转化成矩阵运算后可以通过这些库进行加速。

缺点呢?这是一种空间换时间的方法,消耗了更多的内存——转化的过程中数据被冗余存储。

参考

 

im2col:将卷积运算转为矩阵相乘

标签:document   convert   现在   更新   blank   冗余   ace   提升   hub   

原文地址:https://www.cnblogs.com/cx2016/p/11380662.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!