卷积 - 感受野(Receptive Field)

卷积 - 感受野(Receptive Field)

flyfish

感受野(Receptive Field)是指卷积神经网络中某一层的一个特定神经元能够“看到”并响应的输入图像区域。简单来说,它是指卷积核在输入图像上滑动过程中每次覆盖的区域。感受野的大小随着卷积层的增加而增大,即网络越深,感受野越大。

感受野的直观理解

假设我们有一个简单的卷积神经网络,只有一层卷积层,卷积核大小为 3 × 3 3 \times 3 3×3,步长为 1,没有填充。

例子

输入图像(大小为 5 × 5 5 \times 5 5×5):
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ] \begin{bmatrix} 1 & 2 & 3 & 4 & 5 \\ 6 & 7 & 8 & 9 & 10 \\ 11 & 12 & 13 & 14 & 15 \\ 16 & 17 & 18 & 19 & 20 \\ 21 & 22 & 23 & 24 & 25 \\ \end{bmatrix} 16111621271217223813182349141924510152025
卷积核(大小为 3 × 3 3 \times 3 3×3):
[ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix} 1 & 0 & -1 \\ 1 & 0 & -1 \\ 1 & 0 & -1 \\ \end{bmatrix} 111000111
卷积操作的步骤:

  1. 卷积核首先覆盖输入图像的左上角 3 × 3 3 \times 3 3×3 区域: [ 1 2 3 6 7 8 11 12 13 ] \begin{bmatrix} 1 & 2 & 3 \\ 6 & 7 & 8 \\ 11 & 12 & 13 \\ \end{bmatrix} 161127123813 这个区域就是第一个神经元的感受野。
  2. 卷积核向右滑动一个步长,覆盖下一个 3 × 3 3 \times 3 3×3 区域: [ 2 3 4 7 8 9 12 13 14 ] \begin{bmatrix} 2 & 3 & 4 \\ 7 & 8 & 9 \\ 12 & 13 & 14 \\ \end{bmatrix} 271238134914 这个区域就是第二个神经元的感受野。
    以此类推,卷积核会覆盖输入图像上的每一个可能的 3 × 3 3 \times 3 3×3 区域,每个区域都对应一个神经元的感受野。

更深层的感受野

假设我们有一个两层卷积神经网络:

  • 第一层卷积层的卷积核大小为 3 × 3 3 \times 3 3×3,步长为 1,没有填充。
  • 第二层卷积层的卷积核大小为 3 × 3 3 \times 3 3×3,步长为 1,没有填充。
    在第一层,感受野的大小为 3 × 3 3 \times 3 3×3。在第二层,每个神经元的感受野由它在第一层的感受野决定,并且考虑到卷积核的大小,它实际上看到了第一层的 3 × 3 3 \times 3 3×3 区域的 3 × 3 3 \times 3 3×3 感受野。

第二层神经元的实际感受野大小可以通过计算来确定:

  1. 第一层的感受野大小: 3 × 3 3 \times 3 3×3
  2. 第二层的卷积核大小: 3 × 3 3 \times 3 3×3
  3. 第二层的每个神经元的感受野包括第一层中 3 × 3 3 \times 3 3×3 区域的感受野。
    所以,第二层的感受野大小是 5 × 5 5 \times 5 5×5,因为第二层的卷积核会覆盖第一层卷积的多个感受野,具体如下:
  • 如果考虑第一层的每个感受野( 3 × 3 3 \times 3 3×3)作为一个单位块,那么第二层的感受野大小就是这些单位块的覆盖范围。
  • 例如,第二层的一个神经元可能会结合第一层的9个不同感受野的输出
import torch
import torch.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0)
        self.conv2 = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0)
        
    def forward(self, x):
        x = self.conv1(x)
        print(f"After conv1: {x.shape}")
        x = self.conv2(x)
        print(f"After conv2: {x.shape}")
        return x

def calculate_receptive_field(layers):
    receptive_field = 1
    for layer in layers:
        kernel_size = layer.kernel_size[0]
        stride = layer.stride[0]
        padding = layer.padding[0]
        
        receptive_field = ((receptive_field - 1) * stride) + kernel_size - 2 * padding
        print(f"Layer {layer}: receptive field size = {receptive_field}")

# 输入图像
input_image = torch.tensor([
    [1, 2, 3, 4, 5],
    [6, 7, 8, 9, 10],
    [11, 12, 13, 14, 15],
    [16, 17, 18, 19, 20],
    [21, 22, 23, 24, 25]
], dtype=torch.float32).unsqueeze(0).unsqueeze(0)  # 添加批次和通道维度

# 创建模型
model = SimpleCNN()

# 进行前向传播
output = model(input_image)

# 打印输出结果
print("输出结果:")
print(output.squeeze().detach().numpy())

# 计算并输出感受野大小
calculate_receptive_field([model.conv1, model.conv2])
After conv1: torch.Size([1, 1, 3, 3])
After conv2: torch.Size([1, 1, 1, 1])
输出结果:
4.2884874
Layer Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1)): receptive field size = 3
Layer Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1)): receptive field size = 5

运行这段代码将会输出每一层卷积之后的特征图形状,以及每一层的感受野大小。输出结果将会显示每一层卷积操作后的感受野如何变化。

感受野大小的计算步骤

第一层卷积 c o n v 1 conv1 conv1
  • 输入图像大小: 5 × 5 5 \times 5 5×5
  • 卷积核大小: 3 × 3 3 \times 3 3×3
  • 步长: 1 1 1
  • 填充: 0 0 0
    计算第一层感受野大小:
    R 1 = 3 R_1 = 3 R1=3
第二层卷积 c o n v 2 conv2 conv2
  • 第一层输出特征图大小: 3 × 3 3 \times 3 3×3
  • 卷积核大小: 3 × 3 3 \times 3 3×3
  • 步长: 1 1 1
  • 填充: 0 0 0
    计算第二层感受野大小:
    R 2 = ( ( R 1 − 1 ) × stride ) + kernel size − 2 × padding R_2 = ((R_1 - 1) \times \text{stride}) + \text{kernel size} - 2 \times \text{padding} R2=((R11)×stride)+kernel size2×padding
    R 2 = ( ( 3 − 1 ) × 1 ) + 3 − 2 × 0 R_2 = ((3 - 1) \times 1) + 3 - 2 \times 0 R2=((31)×1)+32×0
    R 2 = 5 R_2 = 5 R2=5

通过这种方式,我们可以跟踪每一层卷积操作后感受野大小的变化。代码中的 calculate_receptive_field 函数通过遍历每一层卷积层来计算和输出感受野大小。

核心概念

卷积神经网络(CNN)之所以在处理图像等数据时非常有效,是因为它们利用了三大核心概念:局部连接(Local Connectivity)、权值共享(Weight Sharing)、平移不变性(Translation Invariance)。让我们详细探讨这些概念。

1. 局部连接(Local Connectivity)

在传统的全连接神经网络中,每个神经元与上一层的每个神经元相连接,形成一个全连接的网络结构。而在卷积神经网络中,卷积层的每个神经元只与上一层的局部区域(称为感受野)相连接。

解释:
  • 局部连接是指每个卷积核仅覆盖输入图像的一个小区域(如 3 × 3 3 \times 3 3×3 5 × 5 5 \times 5 5×5)。
  • 这种局部连接的方式使得卷积层能够捕捉局部特征,如边缘、角点等。
例子:

假设我们有一个 5 × 5 5 \times 5 5×5 的输入图像和一个 3 × 3 3 \times 3 3×3 的卷积核。卷积核每次只关注输入图像的一个 3 × 3 3 \times 3 3×3 的区域,逐步滑动覆盖整个图像。这种方式使得网络能够有效地学习局部特征。

2. 权值共享(Weight Sharing)

在卷积神经网络中,卷积核的参数(权重)在整个输入图像上是共享的。这意味着卷积核在不同位置上应用相同的一组参数进行卷积操作。

解释:
  • 权值共享是指在整个输入图像上使用相同的卷积核,减少了需要训练的参数数量。
  • 这种方式确保了在不同位置检测到的相同特征具有相同的权重。
例子:

如果我们使用一个 3 × 3 3 \times 3 3×3 的卷积核在 5 × 5 5 \times 5 5×5 的输入图像上滑动,该卷积核会在每个位置上应用相同的权重。这样,不管特征出现在图像的哪个部分,该卷积核都能有效地检测到它。

3. 平移不变性(Translation Invariance)

平移不变性是指卷积神经网络能够识别出图像中的特征,无论这些特征出现在图像的哪个位置。卷积操作通过滑动窗口机制,确保网络对图像中不同位置的特征具有相同的响应。

解释:
  • 平移不变性使得网络能够在图像的任何位置检测到相同的特征。
  • 这种特性使得卷积神经网络在处理图像分类等任务时非常有效,因为特征的位置不再重要,网络关注的是特征本身。
例子:

假设我们有一张包含数字“7”的图片。不管“7”出现在图像的左上角还是右下角,卷积神经网络都能够识别出这个特征。这是因为卷积核在整个图像上滑动,确保能够检测到特征的位置。

你可能感兴趣的:(卷积神经网络,深度学习,神经网络,人工智能,卷积)