卷积神经网络——卷积层
卷积层
卷积神经网络中,最重要的就是卷积层,它负责从图片中提取特征信息。
先考虑一种最为简单的图片,一张二维的图片,那么卷积核也是二维的。
卷积运算
听上去挺高大上的,实际上就是乘积的求和。
举个例子:
假设图片是这样的
| 1 | 2 | 4 |
|---|---|---|
| 3 | 5 | 4 |
卷积核是
| 6 | 1 |
|---|---|
| 4 | 4 |
那么卷积运算的结果就是:
6×1+1×2+4×3+4×5=406×2+1×4+4×5+4×4=52
6\times 1+1\times 2 + 4\times 3 + 4\times 5 =40
\newline
6\times 2 + 1\times 4 + 4\times 5+4\times 4 =52
6×1+1×2+4×3+4×5=406×2+1×4+4×5+4×4=52
填充
通过上面简单的例子,不难发现,在经过卷积运算之后,矩阵的大小变化了。这样就会带来一个严重的问题,当不断进行卷积运算后,图片越来越小,以至于最后无法进行卷积运算。
为了解决这个问题,我们希望在进行卷积运算之后,图片的大小不发生改变,这个时候就需要往图片的边缘填充相应的值。
矩阵大小
往图片边缘填充多少,这与卷积核的大小密切相关。那么这个大小变化是否存在关系呢。答案是肯定的。
不妨设H,WH,WH,W表示原来矩阵的长和高,OH,OWOH,OWOH,OW表示经过卷积运算结果的长、高,FH,FWFH,FWFH,FW表示卷积核的长、高,PPP表示填充,SSS表示步幅。
OH=H+2⋅P−FHS+1OW=W+2⋅P−FWS+1
OH =\frac{H + 2\cdot P - FH}{S}+1
\newline
OW = \frac{W + 2\cdot P - FW}{S}+ 1
OH=SH+2⋅P−FH+1OW=SW+2⋅P−FW+1
代码实现
卷积运算的原理非常简单,而且代码实现也非常简单。
通过几个for循环就可以轻松解决,但是还有更高效的方法。
我们可以将图片中对应同一个卷积核的数字变为一行,将卷积核变为一列。然后运用矩阵乘法,就可以完美实现卷积运算,而且一次矩阵乘法就可以算出整张图片的结果。
具体如何变为一行,代码已经在下面给出。
def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
"""
Parameters
----------
input_data : 由(数据量, 通道, 高, 长)的4维数组构成的输入数据
filter_h : 滤波器的高
filter_w : 滤波器的长
stride : 步幅
pad : 填充
Returns
-------
col : 2维数组
"""
N, C, H, W = input_data.shape
out_h = (H + 2*pad - filter_h)//stride + 1
out_w = (W + 2*pad - filter_w)//stride + 1
img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))
for y in range(filter_h):
y_max = y + stride*out_h
for x in range(filter_w):
x_max = x + stride*out_w
col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]
col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
return col
def col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0):
"""
Parameters
----------
col :
input_shape : 输入数据的形状(例:(10, 1, 28, 28))
filter_h :
filter_w
stride
pad
Returns
-------
"""
N, C, H, W = input_shape
out_h = (H + 2*pad - filter_h)//stride + 1
out_w = (W + 2*pad - filter_w)//stride + 1
col = col.reshape(N, out_h, out_w, C, filter_h, filter_w).transpose(0, 3, 4, 5, 1, 2)
img = np.zeros((N, C, H + 2*pad + stride - 1, W + 2*pad + stride - 1))
for y in range(filter_h):
y_max = y + stride*out_h
for x in range(filter_w):
x_max = x + stride*out_w
img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :]
return img[:, :, pad:H + pad, pad:W + pad]
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)