文章目录
- 简介
- 稠密连接:
简介
DenseNet的核心思想是改进网络中特征的传递方式,通过在每个层之间建立直接的连接(即稠密连接),来提高信息流动和梯度传播的效率,从而解决深度神经网络中的梯度消失和梯度爆炸问题。
稠密连接:
在DenseNet中,每一层都与前面的所有层相连。具体来说,层的输入包括前面所有层的输出。这意味着网络中的每个层都接收到来自前面所有层的特征图(feature maps)。由于稠密连接,后面的层可以重用前面层学到的特征,这有助于减少参数数量,同时提高特征的利用效率。
import torch
import torch.nn as nn
from torch.nn import functional as Fdef conv_block(input_channels, num_channels):'''这个函数创建了一个卷积块,包含批归一化层(BatchNorm2d)、ReLU激活函数和3x3卷积层。这个块用于每个稠密块(DenseBlock)中的卷积层。:param input_channels: 输入通道:param num_channels: 输出通道:return: 卷积块'''return nn.Sequential(nn.BatchNorm2d(input_channels), nn.ReLU(),nn.Conv2d(input_channels, num_channels, kernel_size=3, padding=1))def transition_block(input_channels, num_channels):'''这个函数创建了一个转换块,包含批归一化层、ReLU激活函数和1x1卷积层,以及平均池化层。转换块用于在稠密块之间减少通道数,同时降低特征图的空间维度。:param input_channels: 输入通道:param num_channels: 输出通道:return:转换块'''return nn.Sequential(nn.BatchNorm2d(input_channels), nn.ReLU(),nn.Conv2d(input_channels, num_channels, kernel_size=1),nn.AvgPool2d(kernel_size=2, stride=2))class DenseBlock(nn.Module):'''这个类定义了DenseNet中的稠密块。'''def __init__(self, num_convs, input_channels, num_channels):'''在构造函数中,循环创建指定数量的卷积块,并将它们添加到一个序列中。:param num_convs: 卷积块的数量:param input_channels: 当前的通道数:param num_channels: 每个卷积块增加通道数的倍数'''super(DenseBlock, self).__init__()layer = []for i in range(num_convs):layer.append(conv_block(num_channels * i + input_channels, num_channels))self.net = nn.Sequential(*layer)def forward(self, X):'''forward 方法定义了稠密块的前向传播过程,将每个卷积块的输出与输入在通道维度上连接起来。:param X:输入:return:'''for blk in self.net:Y = blk(X)# 连接通道维度上每个块的输入和输出X = torch.cat((X, Y), dim=1)return X'''
这是一个序列,包含网络的第一个卷积块,包括一个7x7的卷积层、批归一化层、ReLU激活函数和最大池化层。
这个序列用于网络的初始特征提取。
'''
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),nn.BatchNorm2d(64), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))'''
稠密块和转换层的构建
'''
num_channels, growth_rate = 64, 32 # num_channels为当前的通道数
num_convs_in_dense_blocks = [4, 4, 4, 4]
blks = []
'''
代码中使用了一个循环来构建一系列稠密块和转换层。
每个稠密块由DenseBlock类创建,转换层由transition_block函数创建。
'''
for i, num_convs in enumerate(num_convs_in_dense_blocks):# 建立num_convs个卷积网络,他的通道数数num_channels,增长的通道倍数growth_rateblks.append(DenseBlock(num_convs, num_channels, growth_rate))# 上一个稠密块的输出通道数num_channels += num_convs * growth_rate# 在稠密块之间添加一个转换层,使通道数量减半if i != len(num_convs_in_dense_blocks) - 1:blks.append(transition_block(num_channels, num_channels // 2))num_channels = num_channels // 2net = nn.Sequential(b1, *blks,nn.BatchNorm2d(num_channels), nn.ReLU(),nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(num_channels, 10))
print(net)
def forward(self, X):
里面写了每一层都与前面的所有层相连。