单例说清楚卷积前向传播

Author: 张一极

date:20231021-16:45

很早就把卷积的单例C++做了实现,但是一直没来得及填这个坑,现在来回顾一下这个函数部分,顺便捋顺一下思路,方便后面进一步做更多算法的实现,完整的算法在最后面,仅供交流,请勿转载。

可以结合这几篇文章食用:

卷积前向的图解:http://likedge.top/test_summary/Edge/conv/conv_test_mode0.html

padding的C++实现:http://likedge.top/test_summary/C++/padding/padding.html

  1. 计算padding大小:

    输入图片矩阵大小:(mid1.wid, mid1.high)

    卷积核大小:kernel_size 步长:stride

    计算水平和垂直方向上的padding大小公式:

    意义就是计算 mid1的宽度减去第一步的kernel_size的大小后剩余值除掉stride步长的余量与stride的差值,即补充足够再完成最后一次窗口滑动的距离。

    padding_wid=stride(mid1.widkernel_size)/stride
    padding_high=stride(mid1.highkernel_size)%stride

    对每个RGB通道进行padding:

  1. 创建滤波器kernels:对每个RGB通道和每个输出通道创建全1滤波器:

    input_dim代表输入维度,output_channels代表输出维度,例如一个卷积层,输入维度3个通道,压缩为1个通道,就需要在外层维度为3,内层维度为1x3x3:

    image-20231021170632615

    4D矩阵画不出来,所以只画了后三个维度,可以理解为多三个这样的3D矩阵。

    实现如下:

  1. 进行卷积:对每个滤波器,在每个RGB通道上进行卷积,并求和得到特征图:

单个元素的卷积如下,其实最核心操作就是conv_element,这里的crop_pic(卷积核窗口切下来的区域)与kernel(卷积核)做mul_simple点乘:

mul_simple的实现如下:

conv_element实现如下

再用这个函数,实现对所有通道进行卷积:

上面的遍历是简化版,只保留了具体逻辑,实际上的实现如下,可以对照着看:

计算每个位置的卷积结果。

  1. 构造输出3D矩阵,每个深度通道存储一个特征

    这个就不用多说了,就是构造一个3D矩阵存储这些特征值:

 

 

 

 


完整的代码

代码仓库:https://github.com/AllenZYJ/Edge-Computing-Engine/blob/053ad935260f7fd120bb90561df5fec5b4f868ea/matrix/matrix_pro.h#L598

代码实现了一个输入3d矩阵,对这个3d矩阵进行卷积操作,并返回一个新的3d矩阵

代码如下: