居家男人手撸卷积神经网络一
本文由在当地较为英俊的男子金天大神原创,版权所有,欢迎转载,本文首发地址 https://jinfagang.github.io 。但请保留这段版权信息,多谢合作,有任何疑问欢迎通过微信联系我交流:
jintianiloveu
前言
这个系列博客,自己动手实现卷积神经网络,以备遗忘,也给广大青少年同胞一个tips。在学习深度学习的道路上,我们往往遗失了一些基础的东西,比如卷积,这个从05年发展到现在,却容易被一个硕士生轻松“被掌握”,但是其实我们大多数并没有理解它背后的原理到底是什么?用编程到底如何去实现?今天,我们从原始部落开始。
ConvNet
卷积的计算方式相信大家应该比较熟悉,除了卷积之外,还有这么几个名词:
- 池化,Pooling
- 滤波核,Filter
- 步长,Stride
我们先解决掉这三个名词,首先Pooling是最简单的,粗犷的理解是一个44 的方格,被缩减成1。滤波核是我们卷积的核心,一般都是 k\k 这样的大小。然后卷积实现就相当于是,加入你有一个 5*6 大小的一个方格纸板,你用一个 2*2 的透明小纸板去挨个的取方格纸板中的元素,我们不考虑Padding,Stride就是1,然后你看一下每一行每一列可以得到多少个新的格子,这么一个操作之后,卷积就完成了。
w * h 的图片,经过 k * k 的卷积核操作之后,Padding是p, 步长是 s, 新的图片大小应该是 (w + 2*p - k ) / s + 1 高度:(h + 2*p - k ) / s + 1
上面这个公式非常重要,要理解他也非常简单,p由于有两边,所以加上两次,减掉最后一个卷积核大小,除以步长加1就是新的宽度,高度类似。
如何计算?
那么问题来了,我如何去用语言实现一个卷积的运算?我看过很多人写的代码,各种循环,其实不管你怎么循环,所有的卷机操作都可以归结为一个非常简单的操作,也就是 转化成两个矩阵的相乘。
这也是Caffe中卷积计算的基本原理。这里偷一张图:
假设有卷积核是k*k , 然后有M个卷积核,那么矩阵A就是M个卷积核,每一行是每一个卷积核扩展成一行。那么B是什么呢?
B我们从列来看,B的每一列都是一个卷积核在图片里面的像素的对应,也就是说B的行必须等于卷积核的面积(k*k), 然后从第一列开始,一直计算下去,知道最后一个卷积核。这么一通才做之后,我们会发现最后B矩阵的宽度,恰恰就是最终图片的面积(这里指的是宽乘以高).
举个例子:
这个矩阵是输入图片:
我们假设卷积核是两个2*2的矩阵,多少不管,那么B就应该是:
注意看,第一列,3 1 1 0,恰好是第一个卷积核元素一列排开,第二列一次计算….知道最后一个卷积核。
最后,我们实现了一个伟大的转换,复杂的卷积运算,转换成了两个矩阵的简单相乘!!!!
下次,我们用C++来对图片进行卷积操作!!