Convolution and Max Pooling of CNN (卷积和池化的实现)

原创 2018年04月15日 14:31:38

Convolution and Max Pooling of CNN (卷积和池化的实现)

  1. 卷积和池化的具体解释(比较清晰直观):
    http://www.hackcv.com/index.php/archives/104/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

  2. 图像卷积的实现

    • 图像卷积的原理图解
      这里写图片描述
    • 具体实现——卷积模板(Filter)
    double filter0[3][3]={{0,0,0},{0,1,0},{0,0,0}};
    double filter1[3][3]={{1/16.0,1/16.0,1/16.0},{1/16.0,8/16.0,1/16.0},{1/16.0,1/16.0,1/16.0}};
    
    double filter2[3][3]={{-1,0,0},{0,1,0},{0,0,0}};
    double filter3[3][3]={{0,-1,0},{0,1,0},{0,0,0}};
    double filter4[3][3]={{0,0,0},{-1,0,1},{0,0,0}};
    double filter5[3][3]={{1.0/9,1.0/9,1.0/9},{1.0/9,1.0/9,1.0/9},{1.0/9,1.0/9,1.0/9}};
    double filter6[3][3]={{0,0,0},{-1,2,-1},{0,0,0}};
    double filter7[3][3]={{0,1,0},{1,-4,1},{0,1,0}};
    
    double filter8[3][3]={{0,0,-1},{0,1,0},{0,0,0}};
    double filter9[3][3]={{0,0,0},{-1,1,0},{0,0,0}};
    double filter10[3][3]={{0,-1,0},{0,0,0},{0,1,0}};
    double filter11[3][3]={{1/16.0,2/16.0,1/16.0},{2/16.0,4/16.0,2/16.0},{1/16.0,2/16.0,1/16.0}};
    double filter12[3][3]={{0,-1,0},{0,2,0},{0,-1,0}};
    double filter13[3][3]={{1,1,1},{1,-7,1},{1,1,1}};
    
    double filter14[3][3]={{0,0,0},{0,1,-1},{0,0,0}};
    double filter15[3][3]={{0,0,0},{0,1,0},{-1,0,0}};
    double filter16[3][3]={{-1,0,0},{0,0,0},{0,0,1}};
    double filter17[3][3]={{1/16.0,1/16.0,1/16.0},{2/16.0,6/16.0,2/16.0},{1/16.0,1/16.0,1/16.0}};
    double filter18[3][3]={{-1,0,0},{0,2,0},{0,0,-1}};
    double filter19[3][3]={{-1,-1,-1},{-1,8,-1},{-1,-1,-1}};
    
    double filter20[3][3]={{0,0,0},{0,1,0},{0,-1,0}};
    double filter21[3][3]={{0,0,0},{0,1,0},{0,0,-1}};
    double filter22[3][3]={{0,0,-1},{0,0,0},{1,0,0}};
    double filter23[3][3]={{1/16.0,2/16.0,1/16.0},{1/16.0,6/16.0,1/16.0},{1/16.0,2/16.0,1/16.0}};
    double filter24[3][3]={{0,0,-1},{0,2,0},{-1,0,0}};
    double filter25[3][3]={{0,-1,0},{-1,5,-1},{0,-1,0}};
    • 具体实现——输入输出数据格式
    typedef struct{
    int W;//图像的宽
    int H;//图像的高
    int num;//图像个数
    byte ***data;//具体数据
    }Data;
    • 具体实现——卷积的实现
    /*
    功能:卷积
    输入:
    Data input:要进行卷积的图像数据的总和
    out_num:指定卷积之后图像的个数
    start_filter:指定从哪一个filter开始进行卷积
    border:true代表保留原图像的边界,图像大小不变;false忽略边界,图像大小发生变化
    输出:
    Data &output:卷积之后的图像的总和
    */
    bool convolution(Data input,Data &output,int out_num,int start_filter,bool border)
    {
    if(!init_output(output,input,out_num,MAX_FILTERS,border))
        return false;
    for(int i=0;i<input.num;i++)
    {
        for(int j=0;j<out_num;j++)
        {
            int filter=(j+start_filter)%MAX_FILTERS;
            if(border)
                convolution_once_border(input.data[i],output.data[j],
                                       input.W,input.H,filter);
            else
                convolution_once_noborder(input.data[i],output.data[j],
                                     input.W,input.H,filter);
        }
    }
    return true;
    }
    /*
    功能:初始化output
    */
    bool init_output(Data &output,Data input,int out_num,int use_filter,bool border)
    {
    cout <<"Conv: ";
    if(input.num*use_filter<out_num)
    {
        cout <<"Inputs :"<<input.num<<" | ";
        cout <<"Filters:"<<use_filter<<" | ";
        cout <<"Max outputs:"<<input.num*use_filter<<endl;
        cout <<"Require outputs:"<<out_num<<endl;
        return false;
    }
    
    if(!border)
    {
        if(input.W<5||input.H<5)
        {
            cout <<"Use border mode, Output Image too small:"<<
                 input.W-2<<" "<<input.H-2<<endl;
            return false;
        }
        output.W=input.W-2;
        output.H=input.H-2;
    }
    else
    {
        output.W=input.W;
        output.H=input.H;
    }
    output.num=out_num;
    printf("Input Image:%d*%d*%d  |  Output Image:%d*%d*%d\n",
              input.num,input.W,input.H,output.num,output.W,output.H);
    malloc_data(output);
    return true;
    }
    /*
    功能:为output的data字段分配实际的空间
    */
    void malloc_data(Data &output)
    {
    output.data=(byte ***)malloc(sizeof(byte **)*output.num);
    for(int i=0;i<output.num;i++)
    {
        output.data[i]=(byte **)malloc(sizeof(byte *)*output.H);
        for(int j=0;j<output.H;j++)
            output.data[i][j]=(byte*)malloc(sizeof(byte)*output.W);
    }
    }
    /*
    功能:考虑边界的单张图像的卷积操作
    输入:
    byte **input:单张图像的数据
    int W,int H:图像的长宽
    int filter:卷积要使用的filter
    输出:
    byte **output
    */
    void convolution_once_border(byte **input,byte **output,int W,int H,int filter)
    {
    double m[3][3]={0};
    for(int r=0;r<H;r++)
    {
        for(int c=0;c<W;c++)
        {
                 //拷贝出3*3大小的矩阵数据用于卷积
            copy_metrix(input,r-1,c-1,W,H,m);
                 //卷积:矩阵乘法
            byte t=(byte)mult_metrix(m,Filters[filter]);
            output[r][c]=t;
        }
    }
    for(int r=0;r<H;r++)
    {
        output[r][0]=output[r][1];
        output[r][W-1]=output[r][W-2];
    }
    for(int c=0;c<W;c++)
    {
        output[0][c]=output[1][c];
        output[H-1][c]=output[H-2][c];
    }
    }
    
    /*
    功能:不考虑边界的单张图像的卷积操作
    输入:
    byte **input:单张图像的数据
    int W,int H:图像的长宽
    int filter:卷积要使用的filter
    输出:
    byte **output
    */
    oid convolution_once_noborder(byte **input,byte **output,int W,int H,int filter)
    {
    double m[3][3];
    for(int r=1;r<H-1;r++)
    {
        for(int c=1;c<W-1;c++)
        {
            copy_metrix(input,r-1,c-1,W,H,m);
            output[r-1][c-1]=(byte)mult_metrix(m,Filters[filter]);
        }
    }
    }
    /*
    功能:拷贝用于卷积运算的3*3矩阵
    输入:
    byte **input:单张图像的数据
    int r,int c:3*3矩阵的(0,0)点的实际位置
    int W,int H:图像的长宽
    输出:
    double m[3][3]
    */
    void copy_metrix(byte **input,int r,int c,int W,int H,double m[3][3])
    {
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            int t1=r+i;
            int t2=c+j;
            if(t1<0)t1=0;
            if(t2<0)t2=0;
            if(t1>=H)t1=H-1;
            if(t2>=W)t2=W-1;
            m[i][j]=input[t1][t2];
        }
    }
    }
  3. 最大池化的实现

    • 最大池化的原理
      这里写图片描述

    • 具体实现

    /*
    功能:最大池化
    输入:
    Data input:要进行池化的图像数据的总和
    int step:池化的步长,上图中的窗口大小
    输出:
    Data &output:池化之后的图像的总和
    */
    bool max_pooling(Data input,Data &output,int step)
    {
    if(!init_output(input,output,step))
        return false;
    for(int i=0;i<input.num;i++)
    {
        max_pooling_once(input.data[i],output.data[i],
                            input.W,input.H,output.W,output.H,step);
    }
    return true;
    }
    /*
    功能:初始化output
    */
    bool init_output(Data input,Data &output,int step)
    {
    cout <<"Pooling:";
    if(input.W/step+1<3||input.H/step+1<3)
    {
        cout <<"The Output Image too small:"<<input.W/step+1<<" "<<input.H/step+1<<endl;
        return false;
    }
    output.num=input.num;
    output.H=input.H/step+1;
    output.W=input.W/step+1;
    printf("Input Image:%d*%d*%d  |  Output Image:%d*%d*%d\n",input.num,input.W,input.H,output.num,output.W,output.H);
    malloc_data(output);
    return true;
    }
    /*
    功能:单张图像的最大池化操作
    输入:
    byte **input:单张图像的数据
    int W,int H:图像的长宽
    int dW,int dH:目的图像的长宽
    int step:池化步长
    输出:
    byte **output
    */
    void max_pooling_once(byte **input,byte **output,int W,int H,int dW,int dH,int step)
    {
    byte *m=(byte *)malloc(sizeof(byte)*step*step);
    for(int r=0;r<dH;r++)
    {
        for(int c=0;c<dW;c++)
        {
            copy_array(input,r*step,c*step,W,H,step,m);
            output[r][c]=find_max(m,step);
        }
    }
    }
    
    //  功能:拷贝池化窗口内的数据到数组内
    void copy_array(byte **input,int r,int c,int W,int H,int step,byte *m)
    {
    for(int i=0;i<step;i++)
    {
        for(int j=0;j<step;j++)
        {
            int t1=r+i;
            int t2=c+j;
            if(t1>=H)t1=H-1;
            if(t2>=W)t2=W-1;
            m[i*step+j]=input[t1][t2];
        }
    }
    }
    /*
    功能:寻找数组中的最大值
    */
    byte find_max(byte *m,int step)
    {
    int l=step*step;
    int max=0;
    for(int i=0;i<l;i++)
        if(m[i]>max)
            max=m[i];
    return max;
    }
  4. 示例结果

    输出数据
    Raw Image Size (516*415) convert to (500*400)
    Conv: Input Image:1*500*400  |  Output Image:18*500*400
    Pooling:Input Image:18*500*400  |  Output Image:18*126*101
    Conv: Input Image:18*126*101  |  Output Image:36*126*101
    Pooling:Input Image:36*126*101  |  Output Image:36*32*26
    Conv: Input Image:36*32*26  |  Output Image:161*32*26
    Pooling:Input Image:161*32*26  |  Output Image:161*17*14
    Conv: Input Image:161*17*14  |  Output Image:528*17*14
    Pooling:Input Image:528*17*14  |  Output Image:528*9*8

    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

github:https://github.com/Shuiliusheng/2018/tree/master/C-_for_NN/Feature-Convolution_and_Pool

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shuiliusheng/article/details/79949113

Deep Learning 学习随记(七)Convolution and Pooling --卷积和池化

图像大小与参数个数: 前面几章都是针对小图像块处理的,这一章则是针对大图像进行处理的。两者在这的区别还是很明显的,小图像(如8*8,MINIST的28*28)可以采用全连接的方式(即输入层和隐含...
  • zhoubl668
  • zhoubl668
  • 2014年04月30日 16:39
  • 21321

UFLDL——Exercise: Convolution and Pooling 卷积和池化

实验要求可以参考deep learning的tutorial,Exercise:Convolution and Poling 卷积和池化。 本实验通过卷积神经网络对RGB彩色图像进行分类,先通过C...
  • Daniel_djf
  • Daniel_djf
  • 2015年01月01日 22:37
  • 2561

deep learning convolution and pooling(卷积和池化)

深度学习,卷积和池化
  • hlx371240
  • hlx371240
  • 2014年11月17日 14:05
  • 4385

反卷积(Deconvolution)上采样(Upsampling)上池化(Unpooling)的区别——附翻译

http://blog.csdn.net/u012949263/article/details/54379996 提供了英文版 Question: Deconvolution netw...
  • xiaoli_nu
  • xiaoli_nu
  • 2018年01月10日 21:27
  • 1026

池化方法总结(Pooling) 和卷积 。 第三部分讲的很好

池化方法总结(Pooling) 2016-01-12 22:55 5033人阅读 评论(2) 收藏 举报  分类: deep learning(18)  ...
  • kebu12345678
  • kebu12345678
  • 2017年02月08日 09:41
  • 8054

深度学习, cnn,本质不是深而是卷积pooling,验证。

2017-3-6 写过cnn本质是卷积和pooling,而不是因为深。一直想着办法验证这个理论。到目前为止,昨天终于有了惊喜的结果。     深度学习之cnn于图像识别,从不同的分辨率进行卷积和po...
  • zsyddl2
  • zsyddl2
  • 2017年05月16日 12:51
  • 444

CNN中pooling层的作用

1.引入了位移不变性,更关注是否存在某些特征而不是特征具体的位置。比如最常见的max pooling,因为取一片区域的最大值,所以这个最大值在该区域内无论在哪,max-pooling之后都是它,相...
  • byplane
  • byplane
  • 2016年09月03日 14:23
  • 2272

CNN网络中的 1 x 1 卷积是什么?

http://iamaaditya.github.io/2016/03/one-by-one-convolution/ http://cs231n.github.io/convolutional-n...
  • zhangjunhit
  • zhangjunhit
  • 2017年02月15日 14:06
  • 3993

卷积神经网络CNN理论到实践

系列博文目录(实时更新)卷积神经网络CNN理论到实践(1) 摘要: 首先介绍卷积的概念,然后我们解释在神经网络中使用卷积的原因:sparse interactions,parameter shar...
  • github_36326955
  • github_36326955
  • 2017年06月12日 11:32
  • 780

深度学习之卷积和池化

转载:http://www.cnblogs.com/zf-blog/p/6075286.html 卷积神经网络(CNN)由输入层、卷积层、激活函数、池化层、全连接层组成,即INPUT-CONV-...
  • zhangxiangweide
  • zhangxiangweide
  • 2017年07月20日 09:29
  • 670
收藏助手
不良信息举报
您举报文章:Convolution and Max Pooling of CNN (卷积和池化的实现)
举报原因:
原因补充:

(最多只允许输入30个字)