参考
5.1 二维卷积层
卷积神经网络(convolutional neural network)是含有卷积层(convolutional layer)的神经网络。本章介绍的卷积神经网络均使用最常见的二维卷积层。它有高和宽两个空间维度,常用来处理图像数据。本节中,我们将介绍简单形式的二维卷积层的工作原理。
5.1.1 二维互相关运算
# 将上述过程实现在 corr2d 函数里.它接受输入数组 X 与核数组 K,并输出数组 Y
import torch
from torch import nndef corr2d(X, K): # 本函数已保存在d2lzh_pytorch包中方便以后使用h, w = K.shapeY = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i, j] = (X[i: i + h, j: j + w] * K).sum()return Y
X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
K = torch.tensor([[0, 1], [2, 3]])
corr2d(X, K)
5.1.2 二维卷积层
二维卷积层将输入和卷积核做互相运算,并加上一个标量偏差来得到输出。卷积层的模型参数包括了卷积核和标量偏差。在训练模型的时候,通常我们先对卷积核进行随机初始化,然后不断迭代卷积核和偏差。
下面基于corr2d
函数实现一个自定义的二维卷积层。在构造函数__init__
里,我们声明了weight
和bias
这两个模型参数。前向计算函数forward
则是直接调用corr2d
函数在加上偏差
class Conv2D(nn.Module):def __init__(self, kernel_size):super(Conv2D, self).__init__()self.weight = nn.Parameter(torch.randn(kernel_size))self.bias = nn.Parameter(torch.randn(1))def forward(self, x):return corr2d(x, self.weight) + self.bias
5.1.3 图像中物体边缘检测
下面我们来看一个卷积的简单应用: 检测图像物体的边缘,即找到像素变化的位置。首先我们构造一张 6 * 8 的图像。它中间4列为黑(0),其余为白(1)
X = torch.ones(6, 8)
X[:, 2:6] = 0.
X
然后我们构造一个高和宽分别为1和2的卷积核K。当它与输入做相关运行时,如果横向相邻元素相同,输出为0; 否则输出为非0.
K = torch.tensor([[1., -1.]])
K
下面将输入X和我们设计的卷积核K做相关运算。可以看出,我们将从白到黑和从黑到白的边缘分别检测成了1和-1。其余部分的输出全是0
Y = corr2d(X, K)
Y
5.1.4 通过数据学习核数组
最后我们来看一个例子,它使用物体边缘检测中的输入数据X
和输出数据Y
来学习我们构造的核数组K
。我们首先构造一个卷积层,其卷积核将被初始化成随机数组。接下来在每一次迭代中,我们使用平方误差来比较Y
和卷积层的输出,然后计算梯度来更新权重。
# 构造一个核数组
conv2d = Conv2D(kernel_size=(1, 2))step ,lr = 60 , 0.01for i in range(step):Y_hat = conv2d(X)l = ((Y_hat - Y) ** 2).sum()l.backward()# 梯度下降conv2d.weight.data -= lr * conv2d.weight.gradconv2d.bias.data -= lr * conv2d.bias.grad# 梯度清0conv2d.weight.grad.fill_(0)conv2d.bias.grad.fill_(0)if(i + 1) % 5 == 0:print("Step %d, loss %.5f "% (i+1, l.item()))
print(conv2d.weight)
print(conv2d.bias)