常规卷积

常规卷积:卷积核与输入的每个通道都进行卷积操作; 假设输入层为一个大小为64×64像素、三通道彩色图片,经过一个包含4个Filter的卷积层,最终输出4个Feature Map,且尺寸与输入层相同。 卷积层共4个Filter,每个Filter包含了3个Kernel,每个Kernel的大小为3×3。 卷积层的参数数量可以用如下公式来计算(即:卷积核W x 卷积核H x 输入通道数 x 输出通道数): 4 × 3 × 3 × 3 = 108

深度可分离卷积

深度可分离卷积(Depthwise Separable Convolution,DSC)用于减少网络参数,提升计算效率;它的核心思想是将一个完整的卷积运算分解为两步进行,分别为Depthwise Convolution和Pointwise Convolution,详细结构如图所示:

Depthwise Convolution 逐通道卷积

常规卷积卷积核需要与输入的每个通道都进行卷积操作,而Depthwise对输入feature map的每个通道分别使用一个卷积核,然后将所有卷积核的输出再进行拼接得到它的最终输出,如图: 还用上面那个例子,这里的Filter的数量与上一层的Depth相同。所以一个三通道的图像经过运算后生成了3个Feature map,参数量为: 3x3x3=27

Pointwise Convolution 逐点卷积

Pointwise Convolution实际为1×1卷积,与常规卷积运算相同,在DSC中它起两方面的作用: 第一个作用是让DSC能够自由改变输出通道的数量; 第二个作用是对Depthwise Convolution输出的feature map进行通道融合;

用1*1的卷积组合不同深度卷积的输出,得到一组新的输出。卷积核的尺寸为 1×1×M,M为上一层的depth。这里的卷积运算会将上一步的map在深度方向上进行加权组合,生成新的Feature map。有几个Filter就有几个Feature map,参数量为: 1x1x3x4=12;

因此,深度可分离卷积的参数个数为27+12=39。

pytorch 实现可分离卷积

可以使用 torch.nn.Conv2d() 中的卷积组参数 groups,来实现深度可分离卷积。groups 参数是用于控制输入和输出的连接的,表示要分的组数(in_channels 和 out_channels 都必须能被 groups 参数整除)。例如:

当 groups =1 (默认值)时,就是同普通的卷积;当 groups=n 时,相当于把原来的卷积分成 n 组,每组 in_channels/n 的输入与 out_channels/n 个 kernel_size x kernel_size x in_channels/n的卷积核卷积,生成 out_channels/n 的输出 ,然后将各组输出连接起来,形成完整的 out_channels 的输出;当 groups = in_channels 时,每个输入通道都只跟 out_channels/in_channels 个卷积核卷积; out_channels = in_channels 时就是 Depthwise 卷积。

import torch

from torchsummary import summary

class myGroupConv(torch.nn.Module):

def __init__(self):

super(myGroupConv, self).__init__()

self.conv2d = torch.nn.Conv2d(in_channels=4,

out_channels=8,

kernel_size=3,

stride=1,

padding=1,

groups=1,

bias=False)

self.relu = torch.nn.ReLU()

def forward(self, x):

x = self.conv2d(x)

x = self.relu(x)

return x

class depthwise_separable_conv(torch.nn.Module):

def __init__(self, ch_in, ch_out):

super(depthwise_separable_conv, self).__init__()

self.ch_in = ch_in

self.ch_out = ch_out

self.depth_conv = torch.nn.Conv2d(ch_in, ch_in, kernel_size=3, padding=1, groups=ch_in, bias=False)

self.point_conv = torch.nn.Conv2d(ch_in, ch_out, kernel_size=1, bias=False)

def forward(self, x):

x = self.depth_conv(x)

x = self.point_conv(x)

return x

class mydspConv(torch.nn.Module):

def __init__(self):

super(mydspConv, self).__init__()

self.conv2d = depthwise_separable_conv(4, 8)

self.relu = torch.nn.ReLU()

def forward(self, x):

x = self.conv2d(x)

x = self.relu(x)

return x

device = torch.device("cuda" )

model_1 = myGroupConv().to(device)

summary(model_1, (4, 3, 3))

model_2 = mydspConv().to(device)

summary(model_2, (4, 3, 3))

结果: 说明: 输入尺寸:3x3x4 输出尺寸:3x3x8

常规卷积,group=1,参数量:3x3x4x8=288;测试代码中偏置设为False,所以不加上偏置的参数量,若设为true,则参数量还需要加上等于输出通道个数的偏执量的个数,等于296;深度可分离卷积:

逐通道卷积:groups=输入通道数,输出通道数=输入通道数,kernel_size=3,每一个卷积核只在一个通道上进行卷积,其参数量=3×3×4=36逐点卷积:kernel_size=1, 其参数量=1×1×4×8=32; 总参数量=36 + 32 = 68

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: