AIHIA梦工厂

标题: 空洞卷积的概念及其代码实现 [打印本页]

作者: 迪迦奥特曼    时间: 2023-9-21 10:28 AM
标题: 空洞卷积的概念及其代码实现
本帖最后由 迪迦奥特曼 于 2023-9-21 10:31 AM 编辑

当我们谈论卷积操作时,通常是一个卷积核(也可以叫做滤波器)在输入图像上滑动并计算一些特定区域的值,然后将这些值合并以生成输出图像。通常情况下,卷积核中的每个元素都与输入图像中的相应元素相乘,然后将它们相加以得到一个输出值。

现在,来谈谈"空洞卷积"。在空洞卷积中,我们引入了一个概念叫做"""空洞"。这些""实际上是卷积核中的一些位置不与输入的每个像素点一一对应,而是跳过一些像素点,以便扩大感受野(也就是卷积核所能看到的输入图像的区域)。

以一个直观的例子来解释:假设你有一块巧克力,正常情况下你可以将它分成4x4块来吃。但是如果你想一口吃掉它,你可以在巧克力上钻几个洞,这样你的嘴巴就可以同时触及到更多的巧克力,但巧克力还是一块。

在卷积中,通过引入洞,卷积核可以"看到"更多距离自己更远的像素,而不需要增加卷积核的大小。这对于捕捉图像中的长距离特征非常有用,比如在语义分割任务中,可以同时捕捉到物体的局部和全局信息。

所以,空洞卷积就是通过在卷积核中引入一些跳过像素的"洞"来扩大感受野,以便更好地理解图像中的特征。这就好像巧克力上的洞让你更容易一口吃掉一整块一样,但卷积核并没有变大。

所以用专业角度解释空洞卷积就是:
空洞卷积(也称为膨胀卷积或孔卷积)是卷积神经网络中的一种特殊卷积操作,它允许在保持参数数量较少的情况下增大感受野( receptive field)。空洞卷积通过在卷积核之间引入空洞(或孔),以增加感受野的大小,而不需要增加参数数量。这对于处理具有大范围上下文信息的图像数据非常有用,例如图像分割或语义分割任务。

以下是一些关于空洞卷积的重要概念:
膨胀率(Dilation Rate):膨胀率定义了卷积核中间的空洞之间的距离。通常,一个膨胀率为1的卷积核与普通卷积相同。增加膨胀率会使卷积核在输入上跳过更多的像素,从而增大感受野。

感受野(Receptive Field):感受野是指卷积神经网络中每个神经元的输入区域。较大的感受野可以捕获更广泛的上下文信息。

空洞卷积前后特征图尺寸计算
设输入特征图的尺寸为H_in × W_in,卷积核的大小为K,空洞率为d,则输出特征图的尺寸计算公式如下:
H_out = (H_in + 2 * padding - dilation * (K - 1) - 1) / stride + 1
W_out = (W_in + 2 * padding - dilation * (K - 1) - 1) / stride + 1
其中,padding是填充大小,stride是步长。
例如:输入特征图尺寸为:64x64,填充大小padding=0,步长stride=1,卷积核大小K=3x3,空洞率d=2,则:
H_out = (H_in + 2 * padding - dilation * (K - 1) - 1) / stride + 1
  =(64+2*0-2(3-1)-1)/1+1=60
W_out = (H_in + 2 * padding - dilation * (K - 1) - 1) / stride + 1
  =(64+2*0-2(3-1)-1)/1+1=60
即输出的特征图尺寸为60*60

需要注意的是,空洞卷积相较于普通卷积,可以在不增加模型参数和计算量的情况下,增大感受野,捕捉更多的上下文信息。但同时,它可能会导致特征图的尺寸减小,因此可能需要进一步处理特征图的尺寸变化,如通过填充或池化操作来保持尺寸一致性。

以下是一个简单的Python代码示例,使用PyTorch来实现一个带有空洞卷积的网络层:

import torch

import torch.nn as nn

# 定义一个包含空洞卷积的神经网络层

class DilatedConvolutionalLayer(nn.Module):

    def __init__(self, in_channels, out_channels, kernel_size, dilation):

        super(DilatedConvolutionalLayer, self).__init__()

        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, dilation=dilation)

    def forward(self, x):

        return self.conv(x)

# 创建一个输入张量

input_tensor = torch.randn(1, 3, 64, 64)  # 1个样本,3个通道,64x64的输入图像

# 创建一个具有空洞卷积的神经网络层

dilated_layer = DilatedConvolutionalLayer(in_channels=3, out_channels=64, kernel_size=3, dilation=2)

# 将输入传递给空洞卷积层

output_tensor = dilated_layer(input_tensor)

# 输出张量的形状

print("输入张量形状:", input_tensor.shape)

print("输出张量形状:", output_tensor.shape)



输出结果:
输入张量形状: torch.Size([1, 3, 64, 64])
输出张量形状: torch.Size([1, 64, 60, 60])
跟我们上面的计算是一样的!







欢迎光临 AIHIA梦工厂 (https://aihiamgc.com/) Powered by Discuz! X3.5