目录

winograd算法简介

知识直通车

winograd代码实例解析


winograd算法简介

现今的Winograd主要来源于1980年,由Shmuel Winograd提出减少FIR滤波器计算量的方法

Shmuel Winograd指出,对于输出个数为m,有r个参数的FIR滤波器,不需要m*r次乘法计算,而仅仅需要:

次乘法计算即可。

下面是一个F(2,3)的例子,即输出m=2个结果,参数r=3个:

可以看到,只需要4次乘法计算结果,发生在m1/m2/m3/m4的计算过程中,外加8次加法。注意,跟g相关的加减乘除可以在初始化时一口气算好,不占计算量。

扩展到二维:

上式中,g为参数,d为数据,G/B/A都是转换矩阵,Y是输出

具体的公式推荐大家直接看论文

对于不同的卷积核和输出大小,winograd的转换矩阵各自不同。本文专注于conv3x3_s1的介绍。

知识直通车

知乎文章:https://zhuanlan.zhihu.com/p/72149270

winograd论文:https://arxiv.org/abs/1509.09308

github实例代码(python):https://github.com/Sejudyblues/cs194-winograd/blob/master/winograd.py

winograd代码实例解析

#include <stdio.h>
#include <assert.h>
#include <chrono>
using namespace std::chrono;const float x[8][8] = {       // input X{ 1.0,     0.0,    0.5,   0.0,   5.0,   0.4,   0.4,   0.8},    // X矩阵{-2.0,    -2.0,   -2.0,  -2.0,  -2.0,  -2.0,  -2.0,  -2.0},{-2.0,     2.0,    2.1,   3.5,   6.0,   2.0,   4.4,   2.0},{ 1.0,     1.0,    1.0,   1.0,   1.0,   6.5,   1.4,   1.0},{ 1.0,    -1.0,   -1.2,  -1.5,  -7.6,  -1.0,  -1.2,  -1.2},{ 1.0,     1.0,    1.0,   1.7,   1.6,   4.4,   1.6,   1.5},{ 1.0,    -1.0,   -3.5,  -6.0,  -1.3,  -1.0,  -1.6,  -7.0},{ 0.0,     0.0,    0.0,   0.6,   0.2,   9.0,   0.4,   0.3}
};const float weight[9] = {         // Weight w1.2, 0.63, 0.4,0.2,  0.5, 0.56,1.5,  0.3, 0.74
};//U=GgG^T
const float ktm[8][3] = {       // Acutually Matrix G{   1.0f,        0.0f,        0.0f},    // G矩阵{-2.0f/9,     -2.0f/9,     -2.0f/9},{-2.0f/9,      2.0f/9,     -2.0f/9},{1.0f/90,     1.0f/45,     2.0f/45},{1.0f/90,    -1.0f/45,     2.0f/45},{1.0f/45,     1.0f/90,    1.0f/180},{1.0f/45,    -1.0f/90,    1.0f/180},{   0.0f,        0.0f,        1.0f}
};int main()
{//w^Tconst float* k0 = weight;const float* k1 = weight+3;const float* k2 = weight+6;//U^T = G.g^T.G^Tfloat tmp[8][3];    // tmp = G.g^Tfor(int i=0; i<8; i++){tmp[i][0] = k0[0] * ktm[i][0] + k0[1] * ktm[i][1] + k0[2] * ktm[i][2];tmp[i][1] = k1[0] * ktm[i][0] + k1[1] * ktm[i][1] + k1[2] * ktm[i][2];tmp[i][2] = k2[0] * ktm[i][0] + k2[1] * ktm[i][1] + k2[2] * ktm[i][2];}//U^T = tmp.G^Tfloat U[64];for (int j=0; j<8; j++){float* tmpp = &tmp[j][0];for (int i=0; i<8; i++){U[j*8 + i] = tmpp[0] * ktm[i][0] + tmpp[1] * ktm[i][1] + tmpp[2] * ktm[i][2];}}
//         const float itm[8][8] = {
//             {1.0f,  0.0f, -5.25f,  0.00f,  5.25f,  0.00f, -1.0f, 0.0f},
//
//             {0.0f,  1.0f,  1.00f, -4.25f, -4.25f,  1.00f,  1.0f, 0.0f},
//             {0.0f, -1.0f,  1.00f,  4.25f, -4.25f, -1.00f,  1.0f, 0.0f},
//
//             {0.0f,  0.5f,  0.25f, -2.50f, -1.25f,  2.00f,  1.0f, 0.0f},
//             {0.0f, -0.5f,  0.25f,  2.50f, -1.25f, -2.00f,  1.0f, 0.0f},
//
//             {0.0f,  2.0f,  4.00f, -2.50f, -5.00f,  0.50f,  1.0f, 0.0f},
//             {0.0f, -2.0f,  4.00f,  2.50f, -5.00f, -0.50f,  1.0f, 0.0f},
//
//             {0.0f, -1.0f,  0.00f,  5.25f,  0.00f, -5.25f,  0.0f, 1.0f}
//         };// 0 = r00 - r06 + (r04 - r02) * 5.25// 7 = r07 - r01 + (r03 - r05) * 5.25// 1 = (r02 + r06 - r04 * 4.25) + (r01 - r03 * 4.25 + r05)// 2 = (r02 + r06 - r04 * 4.25) - (r01 - r03 * 4.25 + r05)// 3 = (r06 + r02 * 0.25 - r04 * 1.25) + (r01 * 0.5 - r03 * 2.5 + r05 * 2)// 4 = (r06 + r02 * 0.25 - r04 * 1.25) - (r01 * 0.5 - r03 * 2.5 + r05 * 2)// reuse r04 * 1.25// reuse r03 * 2.5// 5 = (r06 + (r02 - r04 * 1.25) * 4) + (r01 * 2 - r03 * 2.5 + r05 * 0.5)// 6 = (r06 + (r02 - r04 * 1.25) * 4) - (r01 * 2 - r03 * 2.5 + r05 * 0.5)//V^T = B^T.d^T.Bfloat tempv[8][8];for (int m=0; m<8; m++){const float *r0 = &x[m][0];tempv[0][m] = r0[0] - r0[6] + (r0[4] - r0[2]) * 5.25f;tempv[7][m] = r0[7] - r0[1] + (r0[3] - r0[5]) * 5.25f;float tmp12a = (r0[2] + r0[6] - r0[4] * 4.25f);float tmp12b = (r0[1] + r0[5] - r0[3] * 4.25f);tempv[1][m] = tmp12a + tmp12b;tempv[2][m] = tmp12a - tmp12b;float tmp34a = (r0[6] + r0[2] * 0.25f - r0[4] * 1.25f);float tmp34b = (r0[1] * 0.5f - r0[3] * 2.5f + r0[5] * 2.f);tempv[3][m] = tmp34a + tmp34b;tempv[4][m] = tmp34a - tmp34b;float tmp56a = (r0[6] + (r0[2] - r0[4] * 1.25f) * 4.f);float tmp56b = (r0[1] * 2.f - r0[3] * 2.5f + r0[5] * 0.5f);tempv[5][m] = tmp56a + tmp56b;tempv[6][m] = tmp56a - tmp56b;}float V[64];for (int m=0; m<8; m++){const float* tmp0 = tempv[m];V[m*8] = tmp0[0] - tmp0[6] + (tmp0[4] - tmp0[2]) * 5.25f;V[m*8+7] = tmp0[7] - tmp0[1] + (tmp0[3] - tmp0[5]) * 5.25f;float tmp12a = (tmp0[2] + tmp0[6] - tmp0[4] * 4.25f);float tmp12b = (tmp0[1] - tmp0[3] * 4.25f + tmp0[5]);V[m*8+1] = tmp12a + tmp12b;V[m*8+2] = tmp12a - tmp12b;float tmp34a = (tmp0[6] + tmp0[2] * 0.25f - tmp0[4] * 1.25f);float tmp34b = (tmp0[1] * 0.5f - tmp0[3] * 2.5f + tmp0[5] * 2.f);V[m*8+3] = tmp34a + tmp34b;V[m*8+4] = tmp34a - tmp34b;float tmp56a = (tmp0[6] + (tmp0[2] - tmp0[4] * 1.25f) * 4.f);float tmp56b = (tmp0[1] * 2.f - tmp0[3] * 2.5f + tmp0[5] * 0.5f);V[m*8+5] = tmp56a + tmp56b;V[m*8+6] = tmp56a - tmp56b;}//Matrix M^T=U^T.V^Tfloat tempResult[64];for(int n=0;n<64;n++){tempResult[n] = V[n]*U[n]; }//         const float otm[6][8] = {
//             {1.0f,  1.0f,   1.0f,   1.0f,   1.0f,  32.0f, 32.0f, 0.0f},
//             {0.0f,  1.0f,  -1.0f,   2.0f,  -2.0f,  16.0f,-16.0f, 0.0f},
//             {0.0f,  1.0f,   1.0f,   4.0f,   4.0f,   8.0f,  8.0f, 0.0f},
//             {0.0f,  1.0f,  -1.0f,   8.0f,  -8.0f,   4.0f, -4.0f, 0.0f},
//             {0.0f,  1.0f,   1.0f,  16.0f,  16.0f,   2.0f,  2.0f, 0.0f},
//             {0.0f,  1.0f,  -1.0f,  32.0f, -32.0f,   1.0f, -1.0f, 1.0f}
//         };// 0 = r0 + (r1 + r2) + (r3 + r4)     + (r5 + r6) * 32// 1 =      (r1 - r2) + (r3 - r4) * 2 + (r5 - r6) * 16// 2 =      (r1 + r2) + (r3 + r4) * 4 + (r5 + r6) * 8// 3 =      (r1 - r2) + (r3 - r4) * 8 + (r5 - r6) * 4// 4 =      (r1 + r2) + (r3 + r4) * 16+ (r5 + r6) * 2// 5 = r7 + (r1 - r2) + (r3 - r4) * 32+ (r5 - r6)//R = A^T.M.Afloat* pTempR = tempResult;float r[6][8];for (int m=0; m<8; m++){float tmp024a = pTempR[1] + pTempR[2];float tmp135a = pTempR[1] - pTempR[2];float tmp024b = pTempR[3] + pTempR[4];float tmp135b = pTempR[3] - pTempR[4];float tmp024c = pTempR[5] + pTempR[6];float tmp135c = pTempR[5] - pTempR[6];r[0][m] = pTempR[0] + tmp024a + tmp024b + tmp024c * 32;r[2][m] = tmp024a + tmp024b * 4 + tmp024c * 8;r[4][m] = tmp024a + tmp024b * 16 + tmp024c + tmp024c;r[1][m] = tmp135a + tmp135b + tmp135b + tmp135c * 16;r[3][m] = tmp135a + tmp135b * 8 + tmp135c * 4;r[5][m] = pTempR[7] + tmp135a + tmp135b * 32 + tmp135c;pTempR+=8;}float result[64]; float* pr = result;for (int m=0; m<6; m++){const float* tmp0 = r[m];float tmp024a = tmp0[1] + tmp0[2];float tmp135a = tmp0[1] - tmp0[2];float tmp024b = tmp0[3] + tmp0[4];float tmp135b = tmp0[3] - tmp0[4];float tmp024c = tmp0[5] + tmp0[6];float tmp135c = tmp0[5] - tmp0[6];pr[0+6*m] = tmp0[0] + tmp024a + tmp024b + tmp024c * 32;pr[2+6*m] = tmp024a + tmp024b * 4 + tmp024c * 8;pr[4+6*m] = tmp024a + tmp024b * 16 + tmp024c + tmp024c;pr[1+6*m] = tmp135a + tmp135b + tmp135b + tmp135c * 16;pr[3+6*m] = tmp135a + tmp135b * 8 + tmp135c * 4;pr[5+6*m] = tmp0[7] + tmp135a + tmp135b * 32 + tmp135c;}float output[36];int stride_h = 1;int stride_w = 1;for(int h=0;h<6;h++){int src_h = stride_h*h;for(int w=0;w<6;w++){float sum = 0;int src_w = stride_w*w;for(int k_h=0;k_h<3;k_h++){for(int k_w=0;k_w<3;k_w++){sum+=x[k_h+src_h][k_w+src_w]*weight[3*k_h+k_w];}}output[h*6+w] = sum;}}for(int i=0;i<36;i++)printf("%f==%f \n",output[i],result[i]);return 0;
}

浮点卷积winograd算法相关推荐

  1. CV之CNN:基于tensorflow框架采用CNN(改进的AlexNet,训练/评估/推理)卷积神经网络算法实现猫狗图像分类识别

    CV之CNN:基于tensorflow框架采用CNN(改进的AlexNet,训练/评估/推理)卷积神经网络算法实现猫狗图像分类识别 目录 基于tensorflow框架采用CNN(改进的AlexNet, ...

  2. DL之CNN:卷积神经网络算法简介之原理简介——CNN网络的3D可视化(LeNet-5为例可视化)

    DL之CNN:卷积神经网络算法简介之原理简介--CNN网络的3D可视化(LeNet-5为例可视化) CNN网络的3D可视化 3D可视化地址:http://scs.ryerson.ca/~aharley ...

  3. DL之CNN:利用卷积神经网络算法(2→2,基于Keras的API-Functional)利用MNIST(手写数字图片识别)数据集实现多分类预测

    DL之CNN:利用卷积神经网络算法(2→2,基于Keras的API-Functional)利用MNIST(手写数字图片识别)数据集实现多分类预测 目录 输出结果 设计思路 核心代码 输出结果 下边两张 ...

  4. DL之CNN:利用卷积神经网络算法(2→2,基于Keras的API-Sequential)利用MNIST(手写数字图片识别)数据集实现多分类预测

    DL之CNN:利用卷积神经网络算法(2→2,基于Keras的API-Sequential)利用MNIST(手写数字图片识别)数据集实现多分类预测 目录 输出结果 设计思路 核心代码 输出结果 1.10 ...

  5. DL之CNN:卷积神经网络算法应用之卷积神经网络实践技巧(DA/DP/WI/BN/H/O/R)、优化技术经验之详细攻略

    DL之CNN:卷积神经网络算法应用之卷积神经网络实践技巧(DA/DP/WI/BN/Hyperparameter/Overfitting/Regularization).优化技术经验之详细攻略 目录 卷 ...

  6. DL之CNN:卷积神经网络算法简介之卷积矩阵、转置卷积(反卷积Transpose)、膨胀卷积(扩张卷积Dilated/带孔卷积atrous)之详细攻略

    DL之CNN:卷积神经网络算法简介之卷积矩阵.转置卷积(反卷积Transpose).膨胀卷积(扩张卷积Dilated/带孔卷积atrous)之详细攻略 目录 卷积矩阵的简介 卷积.转置卷积--Tran ...

  7. DL之CNN:卷积神经网络算法简介之原理简介(步幅/填充/特征图)、七大层级结构(动态图详解卷积/池化+方块法理解卷积运算)、CNN各层作用及其可视化等之详细攻略

    DL之CNN:卷积神经网络算法简介之原理简介(步幅/填充/特征图).七大层级结构(动态图详解卷积/池化+方块法理解卷积运算).CNN各层作用及其可视化等之详细攻略 目录 CNN 的层级结构及相关概念 ...

  8. DL之CNN:计算机视觉之卷积神经网络算法的简介(经典架构/论文)、CNN优化技术、调参学习实践、CNN经典结构及其演化、案例应用之详细攻略

    DL之CNN:计算机视觉之卷积神经网络算法的简介(经典架构/论文).CNN优化技术.调参学习实践.CNN经典结构.案例应用之详细攻略 目录 卷积神经网络算法的简介 0.Biologically Ins ...

  9. 卷积神经网络图像识别_[源码和文档分享]基于CUDA的卷积神经网络算法实现

    摘 要 卷积神经网络是近年来人工智能领域取得重大突破的一种重要手段,给出了图像识别.语音识别和自然语言处理领域中关键问题的优化解决方案,尤其适合处理图像方面的任务,如人脸识别和手写体识别.手写数字识别 ...

最新文章

  1. spring web参数传递
  2. 十大编程算法助程序员走上高手之路
  3. Bean的解析与注册
  4. matlab kmeans c 代码,K-means之matlab实现
  5. spark学习-JavaRDD注册成表然后用SparkSQL查询
  6. PLC与C语言的本质区别,一文告诉你PLC与计算机的本质区别在哪里!
  7. net.conn read 判断数据读取完毕_单方验方|如何应对千万级工商数据抓取(一)
  8. spring session的生命周期
  9. php中0, ,null和false的区别
  10. Maven pom.xml 文件格式详解一
  11. SAP FICO财务模块FI财务CO成本视频教学教程(基础+进阶+高级篇)
  12. cad迷你画图2020中文版
  13. python自动补全快捷键_Python快捷键的干货来啦!快来看看你掌握了几个~
  14. 主板风扇转不开机是什么问题_cpu风扇转主板不启动怎么办
  15. python xlwt 设置表格的行高方法
  16. 【开发一个简单的音乐播放器+服务端】【一】
  17. Linux常用命令及解析
  18. c语言指针知识点总结
  19. 如何设置鼠标”的速度、滚动方向等配置?
  20. 微波光子信道化:瞬时频谱分析与宽带信号接收(一)

热门文章

  1. boost log 能不能循环覆盖_记一次for循环中let是声明还是赋值
  2. (002)每日SQL学习:删除名称重复的数据
  3. 移动端下网页border:1px显示
  4. 统计rgb与yuv文件中各分量的熵
  5. C# 系统应用之获取Windows最近使用记录
  6. 312. Burst Balloons 戳气球
  7. 174. Dungeon Game 地下城游戏
  8. 13.2.9 中间件
  9. LDC1000学习资料
  10. 【STM32】光敏传感器示例