深度可分离卷积网络层构建函数解析 - make_layers 函数详解
这段代码定义了一个名为 make_layers 的函数,用于构建卷积神经网络的层。
该函数接收两个参数:
block:一个字典,表示网络中每一层的配置信息,包括输入通道数、输出通道数、卷积核大小、步长、填充等。no_relu_layers:一个列表,表示不需要使用 ReLU 激活函数的层。
函数遍历 block 中每一层的配置信息,根据其类型分别构建最大池化层和深度可分离卷积层。深度可分离卷积层由一个深度卷积层和一个逐点卷积层组成,其中深度卷积层的输入输出通道数相同,逐点卷积层的输入通道数为深度卷积层的输出通道数,输出通道数为该层的输出通道数。
如果该层不在 no_relu_layers 中,则在深度可分离卷积层后添加一个 ReLU 激活函数。最终将所有层组合成一个有序字典,并用 nn.Sequential 封装成一个神经网络模型返回。
import torch
from collections import OrderedDict
import torch
import torch.nn as nn
def make_layers(block, no_relu_layers):
layers = []
for layer_name, v in block.items():
if 'pool' in layer_name:
layer = nn.MaxPool2d(kernel_size=v[0], stride=v[1], padding=v[2])
layers.append((layer_name, layer))
else:
depthwise_conv2d = nn.Conv2d(in_channels=v[0], out_channels=v[0], kernel_size=v[2], stride=v[3], padding=v[4], groups=v[0])
pointwise_conv2d = nn.Conv2d(in_channels=v[0], out_channels=v[1], kernel_size=1, stride=1, padding=0)
layers.append((layer_name, depthwise_conv2d))
layers.append(('pointwise_' + layer_name, pointwise_conv2d))
if layer_name not in no_relu_layers:
layers.append(('relu_' + layer_name, nn.ReLU(inplace=True)))
return nn.Sequential(OrderedDict(layers))
代码解析:
- 循环遍历
block字典: 循环遍历block字典,依次获取每一层的名称和配置信息。 - 判断层类型: 判断当前层是否为池化层,如果是,则构建
nn.MaxPool2d层并将其添加到layers列表中。 - 构建深度可分离卷积层: 如果当前层不是池化层,则构建深度可分离卷积层,包括深度卷积层
depthwise_conv2d和逐点卷积层pointwise_conv2d。 - 添加 ReLU 激活函数: 如果当前层的名称不在
no_relu_layers列表中,则在深度可分离卷积层后添加一个 ReLU 激活函数。 - 返回神经网络模型: 使用
nn.Sequential将所有层组合成一个有序字典,并返回一个神经网络模型。
深度可分离卷积层:
深度可分离卷积层是一种将标准卷积层分解成两个步骤的卷积方法,可以有效减少参数数量和计算量,提高模型效率。
- 深度卷积层: 对每个输入通道进行独立的卷积操作,输出通道数与输入通道数相同。
- 逐点卷积层: 使用 1x1 卷积核将深度卷积层的输出进行组合,得到最终的输出通道数。
ReLU 激活函数:
ReLU 激活函数是一种常用的激活函数,它可以将负值映射为 0,将正值映射为自身。ReLU 激活函数可以提高模型的非线性能力,加速模型的训练过程。
在 make_layers 函数中,如果该层不在 no_relu_layers 列表中,则在深度可分离卷积层后添加一个 ReLU 激活函数。这表明,对于某些层,可能不需要使用 ReLU 激活函数,例如池化层或最后一层。
总结:
make_layers 函数是一个用于构建卷积神经网络层的通用函数,它支持最大池化层和深度可分离卷积层的构建。函数中使用 no_relu_layers 列表来控制是否使用 ReLU 激活函数,可以根据具体任务和网络结构进行调整。
原文地址: https://www.cveoy.top/t/topic/fZv9 著作权归作者所有。请勿转载和采集!