卷积优化方法之Winograd

在卷积神经网络当中, 卷积运算是尤其是计算敏感的, 尤其是在端上设备中, 对于性能的要求更为苛刻。对于卷积优化的方法也有很多种,本文便针对近年来最常见的优化方法Winograd做一个简单总结。

相关资料

winograd算法最早是1980年由Terry Winograd提出的,当时并没有引起太大的轰动。在CVPR'16会议上,Lavin等人[1]提出了利用winogrd加速卷积运算,于是winograd加速卷积优化在算法圈里火了一把。网上较多的实现版本为andravin实现的py版本[2]。目前cudnn中计算卷积就使用了该方法。

[1] "Fast Algorithms for Convolutional Neural Networks" Lavin and Gray, CVPR 2016.
[2] https://github.com/andravin/wincnn

算法

在winograd算法下,对于一维卷积,当输出为m,卷积核长为r,要对应的乘法数量:
\[ u(F(m,r)) = m+r+1 \]
将一维卷积扩展到二维,如果输出维度为mxn,卷积核维度为rxs,则对应的乘法数量:
\[u(F(m * n,r * s)) = u(F(m,r)) * u(F(n,s)) = (m+r-1) * (n+s-1) \]

对一个矩阵大小为4 * 4的输入,卷积核大小为3 * 3,对应的输出为2 * 2,正常计算的情况下,滑动窗口或者im2col的计算方法的乘法次数为2*2*3*3 = 36次,而当使用winograd时,对应的乘法次数为$ u(F(2*2,3*3)) = (2+3-1) * (2+3-1)=16 $,乘法次数明显减少。

假设对应的一维输入为[d0,d1,d2,d3],对应的卷积为[g0,g1,g2],对应的输出为[m0,m1,m2],那么:
\[ F(2,3) = \begin{bmatrix}d0 & d1 & d2\\\\d1 & d2 &d3\end{bmatrix} \begin{bmatrix}g0\\\\g1\\\\g3\end{bmatrix} = \begin{bmatrix}m1+m2+m3\\\\m2-m3-m4\end{bmatrix}\]

其中:
\[ m1 = (d0-d1)g0 \]
\[m2 = 0.5(d1+d2)(g0+g1+g2)\]
\[m3 = 0.5(d2-d1)(g0-g1+g2)\]
\[m4 = (d1-d3)g2\]

这种计算方式需要2+3-1=4次乘法,4次加法。写成矩阵乘法的形式即为:
\[ Y = A^T \left[\left[Gg\right] \odot \left[B^Td\right]\right] \]

其中$ \odot $表示 element-wise multiplication. 对于F(2,3),以上矩阵分别为:

\[ B^{T}=\begin{bmatrix} 1 &0&-1 &0 \\ 0&1 &1 &0 \\ 0&-1 &1 &0 \\ 0& 1& 0& -1 \end{bmatrix} \]

\[ G=\begin{bmatrix} 1 & 0 & 0\\ 0.5& 0.5 &0.5 \\ 0.5& -0.5 &0.5 \\ 0& 0 &1 \end{bmatrix} \]

\[ A^{T}=\begin{bmatrix} 1 & 1 & 1 & 0\\ 0 & 1& -1 & -1 \end{bmatrix} \]

\[ g=\begin{bmatrix} g_{0} &g_{1} &g_{2} \end{bmatrix}^{T} \]

\[ d=\begin{bmatrix} d_{0} &d_{1} &d_{2}&d_{3} \end{bmatrix}^{T} \]

扩展为二维的形式即为:

\[ Y = A^T \left[\left[GgG^T\right] \odot \left[B^TdB\right]\right]A \]

注意

  1. 以上描述的 Winograd 算法只展示了在二维的图像 (更确切的说是 tile) 上的过程, 具体在 ConvNet 的多个 channel 的情况, 直接逐个 channel 按照上述方法计算完然后相加即可;
  2. 按照 1. 的思路, 在计算多个 channel 的时候, 仍然有可减少计算次数的地方.
  3. 按照 2. 的思路, Winograd 在目前使用越来越多的 depthwise conv 中其优势不明显了.
  4. 在 tile 较大的时候, Winograd 方法不适用, 因为, 在做 inverse transform 的时候的计算开销抵消了 Winograd 带来的计算节省.
    Winograd 会产生误差

[winograd]winograd算法在卷积中的应用的更多相关文章

  1. 任意半径局部直方图类算法在PC中快速实现的框架。

    在图像处理中,局部算法一般来说,在很大程度上会获得比全局算法更为好的效果,因为他考虑到了图像领域像素的信息,而很多局部算法可以借助于直方图获得加速.同时,一些常规的算法,比如中值滤波.最大值滤波.最小 ...

  2. 06 - 从Algorithm 算法派生类中删除ExecuteInformation() 和ExecuteData() VTK 6.0 迁移

    在先前的vtk中,如vtkPointSetAlgorithm 等算法派生类中定义了虚方法:ExecuteInformation() 和 ExecuteData().这些方法的定义是为了平稳的从VTK4 ...

  3. 1145: 零起点学算法52——数组中删数II

    1145: 零起点学算法52--数组中删数II Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 293 ...

  4. KMP算法 --- 在文本中寻找目标字符串

    KMP算法 --- 在文本中寻找目标字符串 很多时候,为了在大文本中寻找到自己需要的内容,往往需要搜索关键字.这其中就牵涉到字符串匹配的算法,通过接受文本和关键词参数来返回关键词在文本出现的位置.一般 ...

  5. 剑指Offer——算法复杂度中的O(logN)底数是多少

    剑指Offer--算法复杂度中的O(logN)底数是多少 前言 无论是计算机算法概论.还是数据结构书中,关于算法的时间复杂度很多都用包含O(logN)这样的描述,但是却没有明确说logN的底数究竟是多 ...

  6. AES加解密算法在Android中的应用及Android4.2以上版本调用问题

     from://http://blog.csdn.net/xinzheng_wang/article/details/9159969 AES加解密算法在Android中的应用及Android4.2以上 ...

  7. tarjan算法-解决有向图中求强连通分量的利器

    小引 看到这个名词-tarjan,大家首先想到的肯定是又是一个以外国人名字命名的算法.说实话真的是很佩服那些算法大牛们,佩服得简直是五体投地啊.今天就遇到一道与求解有向图中强连通分量的问题,我的思路就 ...

  8. 利用“海底捞算法”在MongoDB中优雅地存储一棵树

    目前常见的树形结构数据库存储方案有以下四种,但是在处理无限深度.海量数据的树结构时,都存在一些问题: 1)Adjacency List(邻接表):每个节点仅记录父节点主键.优点是简单,缺点是访问子树需 ...

  9. 图像处理之优化---任意半径局部直方图类算法在PC中快速实现的框架

    在图像处理中,局部算法一般来说,在很大程度上会获得比全局算法更为好的效果,因为他考虑到了图像领域像素的信息,而很多局部算法可以借助于直方图获得加速.同时,一些常规的算法,比如中值滤波.最大值滤波.最小 ...

随机推荐

  1. mysql函数调用过程

    1.conn = mysql_init(NULL);//初始化  MYSQL *conn; 2.mysql_real_connect(conn, "localhost", &quo ...

  2. Vue(小案例_vue+axios仿手机app)_Vuex优化购物车功能

    一.前言         1.用vuex实现加入购物车操作 2.购物车详情页面          3.点击删除按钮,删除购物详情页面里的对应商品 二.主要内容 1.用vuex加入购物车 (1)在src ...

  3. Java IO系列之一:IO

    1. 概述 Java IO一般包含两个部分: 1.java.io包中堵塞型IO: 2.java.nio包中的非堵塞型IO,通常称为New IO. java.io包下,分为四大块近80个类: 1.基于字 ...

  4. Python 条件、循环、异常处理

    一.条件语句 1.布尔值 条件语句中,判断条件的值一般是布尔值.即条件为真时,将执行什么,条件为假时,将执行什么. 下面的值在作为布尔表达式的时候,会被解释器看做假(false): False    ...

  5. [图解Java]ReentrantLock重入锁

    图解ReentrantLock 0. demo 我先给出一个demo, 这样大家就可以根据我给的这段代码, 边调试边看源码了. 还是那句话: 注意"My" , 我把Reentran ...

  6. kaldi通用底层矩阵运算库——CUDA

    cudamatrix/cublas-wrappers.h 该头文件对cuBLAS的接口进行了简单的封装(函数名的简化和部分kaldi函数的封装). 比如 cublasSgemm_v2封装为cublas ...

  7. pyQt5不让进度条卡住

    这里我们用一个更新程序做示例, 下载文件的过程中让进度条实时显示下载进度. 如果下载和更新进度条的工作都放在一个线程中,会出现进度条卡顿的情况. Qt中正确的做法是把界面刷新和工作任务交给不同的线程去 ...

  8. MariaDB Galera Cluster部署实践

    原理 官方地址:http://galeracluster.com/documentation-webpages/index.html Galera Cluster与传统的复制方式不同,不通过I/O_t ...

  9. RNN,写起来真的烦

    曾经,为了处理一些序列相关的数据,我稍微了解了一点递归网络 (RNN) 的东西.由于当时只会 tensorflow,就从官网上找了一些 tensorflow 相关的 demo,中间陆陆续续折腾了两个多 ...

  10. ubuntu常用命令及操作,包括安装CUDA

    chmod Document 这里Document是一个文件夹,文件夹中还有好多子文件,可以发现执行了这条指令以后,其子文件夹的权限并没有改变. 要想改变其子文件夹的权限,应该执行 Document/ ...