深度理解卷积--使用im2col实现卷积

上一篇我们了解了卷积的概念,并且使用numpy实现了卷积。另一篇介绍了如何在tensorflow框架中调用API进行卷积操作。今天再介绍一个实现卷积操作的方案,使用im2col实现卷积,实际在OpenCV源码中也可以看到im2col的算法,顺便提一下opencv也可以直接部署深度学习模型,调用方法可以参考这里

im2col

im2col算法原理

im2col就是把图像转化为列向量,很多文章都有讲解,https://zhuanlan.zhihu.com/p/63974249 链接讲的比较详细。我按自己理解画了几个图,也方面大家理解
在这里插入图片描述
上图就是im2col的原理,把一个矩阵转化为一行。(实际应该是im2row)
如果看过numpy实现卷积的文章应该都知道卷积的过程,如果是二维图像,卷积核会在图像上滑动进行卷积,那在im2col实现卷积,怎么操作呢?
在这里插入图片描述
如果核大小是3*3,那每次卷积的图像就是依次为右边的四个矩阵了~
再把四个矩阵按图一的方式转化为一行,就是下图
在这里插入图片描述
同样,我们把卷积核也按im2col进行转化
在这里插入图片描述

总结下
一个63的图像,我们转换为了94的矩阵
一个33的卷积核,我们转换为了91的矩阵
两个矩阵相乘,是不是一个41的矩阵~
如果是正常卷积呢?回忆下卷积过程,或者跑下代码,应该也是得到一个4
1的结果~(以VALID方式)
对比下:
标准卷积的计算过程:4次33矩阵和33矩阵相乘累加
im2col实现卷积的计算过程:94矩阵和19矩阵相乘
根据矩阵相乘的定义,两个结果是一致的,但im2col肯定是优化版的卷积过程~

通过上面几个图,大家应该就就了解了什么叫im2col,以及它如何实现卷积了。
下面简单直接~上代码

im2col实现卷积代码实现

对于基础知识reshape和transpose的加深理解这里
下面我们直接写im2col的代码,注释已经比较详细

def im2col(inputs,filter,padding="SAME",stride=1):
    N, C, H ,W = inputs.shape
    filter_size = filter.shape[2]
    # default np.floor
    filter_center = int(filter_size / 2.0)
    filter_center_ceil = int(np.ceil(filter_size / 2.0))
    # SAME模式,输入和输出大小一致,所以要在外面填充0
    if padding == "SAME":
        padding_inputs = np.zeros([N,C,H + filter_center_ceil, W + filter_center_ceil], np.float32)
        padding_inputs[:,:,filter_center:-filter_center, filter_center:-filter_center] = inputs
        inputs = padding_inputs
    N ,C,H2, W2 = inputs.shape
    print("N ,C,H2, W2",N ,C,H2, W2,"inputs\n",inputs)
    out_h = H
    out_w = W
    col = np.empty((N * H * W, filter_size * filter_size * C))
    outsize = out_w * out_h
    #每个样本outsize行,每行就是fs*fs*C按行顺序reshape,如果是N个样本就是N行
    for y in range(out_h):
        y_min = y * stride
        y_max = y_min + filter_size
        y_start = y * out_w
        for x in range(out_w):
            x_min = x * stride
            x_max = x_min + filter_size
            #取出kernel大小的数据块reshape为一行,N个样本reshape为N行
            #这里::outsize就是间隔outsize放下一个样本的行
            col[y_start + x::outsize, :] = inputs[:,:,y_min:y_max, x_min:x_max].reshape(N, -1)
    return col

同样把filter进行im2col操作

def trans_weight(filter):
    # print("filter\n",filter)
    C_out, C_in, K, K = filter.shape
    weight = filter.reshape(C_out,-1)
    # print("weight\n",weight)
    return weight

然后进行卷积操作,为了和之前numpy实现的卷积以及Tensorflow进行卷积的结果对比,我们输入和之前一样:

inputs = np.zeros([1, 3, 9, 9])
    for n in range(1):
        for i in range(3):
            for j in range(9):
                for z in range(9):
                    inputs[n][i][j][z] = i + j + z

filter = np.zeros([2, 3, 3, 3])
    for i in range(2):
        for j in range(3):
            for x in range(3):
                for y in range(3):
                    filter[i][j][x][y] = i + j + x + y
conv_out = conv_im2col(inputs, filter)
#[1,9,9,2]---[1,2,9,9]
conv_out =np.transpose(conv_out,(0,3,1,2))
print(conv_out)

大家可以自己动手跑下,卷积结果和之前我们使用numpy实现卷积结果是一致的~

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值