动手实现深度学习(12): 卷积层的实现与优化(img2col)

卷积的计算过程网上的资料已经做够好了,没必要自己再写一遍。只把资料搬运到这里:

这里总结一下有padding\stride的卷积操作:

假设,输入大小为(H,W,C),fileter大小为(FH,FW,C)*N ; padding=P, stride=S,卷积后的形状为(OH,OW,OC)

卷积的backward是对卷积的求导。

代码实现如下:

再讲卷积的实现之前,首先抛出一个问题:如果按照上述的卷积方式计算,是否会影响性能?

答案是肯定会受影响的。

因此,我们需要向优化一下conv的计算方式.

按照”以空间换时间”的思想,我们可以做一些优化,使得在conv和pool的时候运算速度加快。

首先,我们知道Numpy对大型矩阵的运算是有做优化的,这个特点我们应该好好利用;

其次,我们知道Numpy在做多个嵌套的for循环的时候,O(n)会很大;应该避免做多个for循环;

因此,要是将4D的卷积运算转换成2D的矩阵乘法就会好很多;filter也可以变成2D的数组;

Im2col便是将4D数据转换成2D矩阵的函数。

该函数大致的思路是:filter按照行列展开成一个2D矩阵即可,input_data按照计算的单元重新组合。因此需要写一个函数将图像转换成2D矩阵,该函数可以将图像展开成适合与滤波去做乘法的矩阵。

展开和计算的流程如下:

对filter计算有影响的因素有input_data,filter_h,filter_w,stride, padding;im2col会应该根据以上的因因素展开input_data,展开后的input_data一定是比之前要大的;

我们可以尝试计算一下input_data展开后的数据形状:

假设,输入数据为443大小的tensor; filter有两个为2(22*3),filter_h=2,filter_w=2,stride=1, padding=0;这里可以计算出展开以后的大小:

Filter为有两个,分别为f1和f2; shape=(223), 按照行展开成2D的矩阵以后如下图所示:

Input_data为443的tensor,如下图所示:

Input_data首先会找出filter对应的计算单元,这些还是需要padding\stride\filter_w\filter_h相关,找出计算的单元以后,按照行展开。最后得到的数据便是im2col的结果:

Input_data和filter这样展开以后,卷积计算就可以按照矩阵乘法的方式计算,避免了重复的for循环。如下图所示,黑色和灰色区域是计算的结果。不必担心矩阵过大是否会影响计算速度,Numpy对大规模矩阵乘法内部有优化加速,这样展开以后恰恰也能充分的利用numpy的特性。

Im2col的实现:

测试代码:

========输出:可以发现和上面的绘图的结果是一致的 =====

(1, 3, 4, 4)

[[3. 0. 6. 5. 1. 2. 3. 0. 4. 2. 1. 2.]

[0. 4. 5. 4. 2. 0. 0. 2. 2. 0. 2. 0.]

[4. 2. 4. 3. 0. 1. 2. 4. 0. 1. 0. 4.]

[6. 5. 3. 0. 3. 0. 1. 0. 1. 2. 3. 0.]

[5. 4. 0. 2. 0. 2. 0. 3. 2. 0. 0. 4.]

[4. 3. 2. 3. 2. 4. 3. 2. 0. 4. 4. 2.]

[3. 0. 1. 0. 1. 0. 4. 3. 3. 0. 6. 2.]

[0. 2. 0. 3. 0. 3. 3. 0. 0. 4. 2. 4.]

[2. 3. 3. 1. 3. 2. 0. 1. 4. 2. 4. 5.]]

卷积操作也需要实现forward和backward函数。

Forward函数中用到了9.1\9.2的im2col

输入:input_data\filters

输出:output

测试代码:

Conv的输出结果,与上图的结果一致。

Original: https://www.cnblogs.com/greentomlee/p/16686862.html
Author: 修雨轩陈
Title: 动手实现深度学习(12): 卷积层的实现与优化(img2col)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/804854/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球