AI学习日记——卷积神经网络(CNN):卷积层与池化层的实现
目录
一、实现基础
1. 四维数组的数据结构
2. im2col函数
二、卷积层的具体实现
1. 卷积层的初始化
2. 卷积层的前向传播
三、池化层的具体实现
1. 池化层的初始化
2. Max池化层的前向传播
3. 通道独立处理机制
总结
一、实现基础
1. 四维数组的数据结构
CNN处理的是4维数据,其形状为(batch_num, channel, height, width):
数据访问方式:
-
x[0]
:第1个样本 → (1, 28, 28) -
x[0, 0]
:第1个样本的第1个通道 → (28, 28)
2. im2col函数
im2col(image to column图像到矩阵)是会考虑滤波器大小、步幅、填充,将输入数据(四维数组)展开以适应滤波器计算的(二维数组)技巧:
上图只是示意图,步幅很大;实际情况大部分会重叠,展开后元素可能多于原数据,造成内存消耗增加。
传统实现的困境:
-
需要多层嵌套for循环
im2col的解决方案:
-
将滤波器的应用区域展开为矩阵的列
-
将卷积运算转换为矩阵乘法
-
利用高度优化的线性代数库
二、卷积层的具体实现
1. 卷积层的初始化
class Convolution:
def __init__(self, W, b, stride=1, pad=0):
self.W = W # 滤波器权重 (FN, C, FH, FW)
self.b = b # 偏置 (FN, 1, 1)
self.stride = stride
self.pad = pad
参数说明:
-
FN
:滤波器数量(Filter Number) -
C
:通道数(Channel) -
FH, FW
:滤波器高宽(Filter Height/Width)
2. 卷积层的前向传播
def forward(self, x):
FN, C, FH, FW = self.W.shape
N, C, H, W = x.shape
# 计算输出尺寸
out_h = int(1 + (H + 2*self.pad - FH) / self.stride)
out_w = int(1 + (W + 2*self.pad - FW) / self.stride)
# 1.使用im2col展开输入
col = im2col(x, FH, FW, self.stride, self.pad)
# 2.展开滤波器权重
col_W = self.W.reshape(FN, -1).T
# 3.矩阵乘法计算输出
out = np.dot(col, col_W) + self.b
# 4.形状转换
out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)
return out
reshape函数中-1的作用:
- 自动计算该维度的大小,保持总元素数量不变
-
例如:
self.W.reshape(FN, -1)
将形状(FN, C, FH, FW)变为(FN, C×FH×FW)
为什么要transpose函数:
-
经过矩阵乘法后,数据的自然排列顺序是:(样本, 输出高, 输出宽, 通道)
-
但CNN标准格式要求:(样本, 通道, 高, 宽)
三、池化层的具体实现
1. 池化层的初始化
class Pooling:
def __init__(self, pool_h, pool_w, stride=1, pad=0):
self.pool_h = pool_h
self.pool_w = pool_w
self.stride = stride
self.pad = pad
池化层无需记录权重参数
2. Max池化层的前向传播
def forward(self, x):
N, C, H, W = x.shape
out_h = int(1 + (H - self.pool_h) / self.stride)
out_w = int(1 + (W - self.pool_w) / self.stride)
# 1. 使用im2col展开输入
col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
col = col.reshape(-1, self.pool_h * self.pool_w)
# 2. 求各行最大值
out = np.max(col, axis=1)
# 3. 转换为合适形状
out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)
return out
3. 通道独立处理机制
与卷积相比,池化在每个通道上独立进行:
-
输入形状:(N, C, H, W)
-
输出形状:(N, C, out_h, out_w)
-
通道数保持不变
总结
本文介绍了CNN中卷积层和池化层的实现方法。卷积层通过im2col函数将四维输入数据转换为二维矩阵,利用矩阵乘法优化计算效率,并处理滤波器权重、步幅和填充等参数。池化层同样采用im2col转换,通过取区域最大值实现Max池化,且保持通道独立性。两种层都涉及数据形状转换以满足CNN的标准格式要求(N,C,H,W)。该方法有效解决了传统实现中多层循环嵌套的性能问题。