目录1.卷积运算2.步幅stride3.边界效应 (Padding)4.多个输入通道5.多个输出通道6.卷积层1.卷积运算卷积层由卷积运算和激活函数组成。卷积运算基于一个局部的线性模型这个线性模型会重复地应用在图像的各个不同的位置上。卷积运算的结果仍然是一种类似图像的数据只不过每个位置上的数值代表的是一种局部特征。卷积运算的公式若输入图像的尺寸为 (H, W) 则输出数据的尺寸为。下边的例子演示了一个3x3的kernel卷积的过程卷积核为可见卷积层实现的就是滤波操作。与全连接层相比卷积运算具有局部性计算结果只受到卷积核覆盖范围内局部数据的影响。卷积层具有参数共享的特性因此参数量小更有利于特征的学习。卷积层的输出的结果仍然具有空间结构方便进一步提取更高层级的图像特征。2.步幅stride卷积核每次移动的位移叫做步幅(stride)在上边的例子里纵向和横向的步幅均为1即表示为。步幅的大小也可以超过1此时相当于对图像数据进行了降采样。在考虑步幅大小时输出数据的尺寸为。3.边界效应 (Padding)在上边卷积运算的例子中与卷积核相乘的数据都在图像范围内因此输出的“图像”相较原图像是缩小的图像边缘的特征被忽略了。 Padding是将原图像进行扩展并将扩展的部分补0使得卷积运算的结果尺寸与原图像相同。如果纵向和横向的填充尺寸分别为和(两边各分一半)那么输出数据的尺寸为:4.多个输入通道到目前为止处理的图像还只是灰度图即只有一个特征通道。如果处理的是彩色图具有 (R, G, B) 三通道特征输入图像数据的尺寸是。此时卷积核也需要升一个维度尺寸变为。在进行卷积运算时同样沿着高、宽的维度平移。每次运算输入窗口中的数据大小也为与卷积核先将对应位置的元素相乘再相加。输出数据的尺寸与单输入通道的情况相同。from PIL import Image import numpy as np # 进行滤波 卷积运算的函数 def filter(input : np.ndarray, kernel : np.ndarray) - np.ndarray: # input : (channel, H, W) # kernel : (channel, h, w) # kernel size h kernel.shape[1] w kernel.shape[2] # input image size H input.shape[1] W input.shape[2] # output image size output np.zeros((H-h1, W-w1)) # 开始滤波卷积 for i in range(H-h1): for j in range(W-w1): #input[:, i:ih,j:jw].shape : (3, h, w) output[i,j] (input[:, i:ih,j:jw] * kernel).sum() return output def data2img(output1): output1 ((output1 - output1.min()) / (output1.max() - output1.min()) * 255) output1 np.clip(output1-128, 0, 255).astype(np.uint8) return output1 def expand_kernel(kernel): kernel2 [] kernel2.append(kernel) kernel2.append(kernel) kernel2.append(kernel) return np.array(kernel2) if __name__ __main__: # 读入图像数据 # img Image.open(cross.png).convert(RGB) img Image.open(./data/mihao.jpeg).convert(RGB) data np.array(img) data data.transpose(2, 0, 1) # sobel base_kernel [[1, 0, -1], [2, 0, -2], [1, 0, -1]] sobel_x expand_kernel(base_kernel) sobel_x2 -sobel_x sobel_y sobel_x.transpose(0, 2, 1) # 交换维度 sobel_y2 -sobel_y output1 filter(data, sobel_x) output2 filter(data, sobel_x2) output3 filter(data, sobel_y) output4 filter(data, sobel_y2) output data2img(output1) data2img(output2) data2img(output3) data2img(output4) out_img Image.fromarray(output) out_img.show()5.多个输出通道在之前的例子中只使用了一个卷积核。实际上为了提高模型提取特征的能力一般会使用多个卷积核每个卷积核对应一种输出的特征即特征通道。如下图所示每个卷积核独立地进行特征提取。输出数据会增加一个表示通道的维度。此时输出数据的尺寸为。其中。PyTorch定义了进行卷积运算的层即 nn.Conv2d 和 nn.Conv1d 他们都是 nn.Module 的子类。nn.Conv2dhttps://docs.pytorch.org/docs/2.11/generated/torch.nn.Conv2d.html#torch.nn.Conv2dhttps://docs.pytorch.org/docs/2.11/generated/torch.nn.Conv2d.html#torch.nn.Conv2dnn.Conv1dhttps://docs.pytorch.org/docs/2.11/generated/torch.nn.Conv1d.html#torch.nn.Conv1dhttps://docs.pytorch.org/docs/2.11/generated/torch.nn.Conv1d.html#torch.nn.Conv1d接下来我们利用 nn.Conv2d 复现一下 sobel 滤波。6.卷积层卷积运算非线性激活函数就构成了卷积层非线性函数一般采用ReLU 。我们可以把nn.Conv2d和nn.ReLU组成一个块 (也是nn.Module的子类)方便后续搭建更复杂的网络结构。在利用sobel算子提取边缘特征时我们对两个方向的滤波数据先取绝对值再进行组合。接下来我们利用卷积层来复现这一过程。卷积层可以叠加多层所提取的局部特征其语义抽象层次逐步提高。随着卷积次数的增加每个位 置上的特征所关联的区域也逐渐增大因此一般也会逐步降低采样率通过池化层。