深度学习笔记之卷积神经网络——卷积示例与池化操作
引言
上一节介绍了卷积的另一特点——筛选数据特征。并通过神经网络的反向传播过程,我们能够对卷积核内的参数进行更新,得到从数据中提取到更优质特征的卷积核。
本节对卷积操作进行示例,并继续介绍池化操作。
卷积神经网络:卷积层
在之前的卷积神经网络反向传播示例中,我们仅仅使用单通道的灰度图片作为输入,并使用 1 1 1个卷积核执行卷积运算。
但在 3 3 3通道的彩色图片中,每个通道均使用对应的卷积核执行卷积操作。也就是说:对于彩色图片,如果依然使用 3 × 3 3 \times 3 3×3大小的卷积核执行卷积运算,对于该图片的卷积核格式 ( Shape ) (\text{Shape}) (Shape)是: 3 × 3 × 3 3 \times 3 \times 3 3×3×3。
需要注意的是,虽然对每个通道分别进行卷积操作,但是
3 × 3 × 3 3 \times 3 \times 3 3×3×3卷积核矩阵是‘一个卷积核’。并且各分量之间仅起到一个‘并行’作用。仅仅是用矩阵合在一起。
在卷积神经网络的卷积层中,针对一个图像数据,不一定仅使用 1 1 1个卷积核来执行卷积操作,而是通过构建若干个卷积核针对同一个数据进行卷积操作。这意味着:针对同一数据,可以得到不同卷积结果,其结果数量与卷积核数量相同。
这里使用 PyTorch \text{PyTorch} PyTorch中的二维卷积 Conv2d \text{Conv2d} Conv2d的执行过程示例。
为了简化运算,使用元素值均为 1 1 1的矩阵作为数据。其数据格式表示如下:
import torch
from torch import nn as nn
SampleInput = torch.ones(1,3,3,3)
这明显是一个 4 4 4维张量。各维度的物理意义表示为:
- 1 ⇒ 1 \Rightarrow 1⇒ 数据数量—— 1 1 1张图片数据。
- 3 ⇒ 3 \Rightarrow 3⇒ 图片数据通道数——彩色图片。
- 3 ⇒ 3 \Rightarrow 3⇒ 图片数据的宽 ( Width ) (\text{Width}) (Width)。
- 3 ⇒ 3 \Rightarrow 3⇒ 图片数据的高 ( Height ) (\text{Height}) (Height)。
其卷积层设置如下:
Conv1 = nn.Conv2d(
in_channels=3,
out_channels=1,
kernel_size=(2,2)
)
其中:
in_channels=3
表示该卷积层对于样本数据的输入通道数为 3 3 3;out_channels=1
表示输出通道数,也就是针对每个输入数据,使用的卷积核数量;kernel_size=(2,2)
表示针对每个通道的卷积核的大小。- 关于
Stride,Padding
等参数均使用默认值。
我们观察卷积核的权重信息以及它的返回结果格式:
print(Conv1.state_dict()["weight"].shape)
print(Conv1(SampleInput).shape)
返回结果如下:
torch.Size([1, 3, 2, 2])
torch.Size([1, 1, 2, 2])
其中权重 ( Weight ) (\text{Weight}) (Weight)的格式可看作是: 1 1 1个 3 × 2 × 2 3 \times 2 \times 2 3×2×2大小的卷积核。而对应的输出结果格式表示为:针对 1 1 1个数据, 1 1 1个卷积核产生的大小为 2 × 2 2 \times 2 2×2的卷积结果。
同理,如果将卷积层中的out_channels
参数进行修改,可得到不同格式的权重和输出结果:
Conv1 = nn.Conv2d(
in_channels=3,
out_channels=10,
kernel_size=(2,2)
)
torch.Size([10, 3, 2, 2])
torch.Size([1, 10, 2, 2])
卷积层的计算过程
观察它的计算过程:
print(SampleInput)
print("------" * 10)
print(Conv1.state_dict()["weight"].shape)
print(Conv1.state_dict()["weight"])
print(Conv1.state_dict()["bias"])
print(Conv1(SampleInput).shape)
print(Conv1(SampleInput))
返回结果如下:
tensor([[[[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]],
[[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]],
[[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]]])
------------------------------------------------------------
torch.Size([1, 3, 2, 2])
tensor([[[[-0.2332, 0.0908],
[ 0.0909, 0.1832]],
[[ 0.2570, 0.1007],
[-0.1385, -0.2769]],
[[-0.1610, -0.2174],
[ 0.1630, 0.2141]]]])
tensor([0.0693])
torch.Size([1, 1, 2, 2])
tensor([[[[0.1420, 0.1420],
[0.1420, 0.1420]]]], grad_fn=<ThnnConv2DBackward0>)
- 将各通道的卷积核对相应通道执行卷积运算:
{ Convolution [ ( 1 , 1 , 1 1 , 1 , 1 1 , 1 , 1 ) , ( − 0.2332 , 0.0908 0.0909 , 0.1832 ) ] = ( 0.1317 , 0.1317 0.1317 , 0.1317 ) Convolution [ ( 1 , 1 , 1 1 , 1 , 1 1 , 1 , 1 ) , ( 0.2570 , 0.1007 − 0.1385 , − 0.2769 ) ] = ( − 0.0577 , − 0.0577 − 0.0577 , − 0.0577 ) Convolution [ ( 1 , 1 , 1 1 , 1 , 1 1 , 1 , 1 ) , ( − 0.1610 , − 0.2174 0.1630 , 0.2141 ) ] = ( − 0.0013 , − 0.0013 − 0.0013 , − 0.0013 ) \begin{cases} \text{Convolution} \left[\begin{pmatrix} 1,1,1 \\ 1,1,1 \\ 1,1,1 \end{pmatrix},\begin{pmatrix} -0.2332,0.0908 \\ 0.0909,0.1832 \end{pmatrix}\right] = \begin{pmatrix} 0.1317,0.1317 \\ 0.1317,0.1317 \end{pmatrix} \\ \text{Convolution} \left[\begin{pmatrix} 1,1,1 \\ 1,1,1 \\ 1,1,1 \end{pmatrix},\begin{pmatrix} 0.2570,0.1007 \\ -0.1385,-0.2769 \end{pmatrix} \right] = \begin{pmatrix} -0.0577,-0.0577 \\ -0.0577,-0.0577 \end{pmatrix} \\ \text{Convolution} \left[\begin{pmatrix} 1,1,1 \\ 1,1,1 \\ 1,1,1 \end{pmatrix},\begin{pmatrix} -0.1610, -0.2174 \\ 0.1630, 0.2141 \end{pmatrix}\right] = \begin{pmat