【深度学习经典模型】CVPR2017的最佳论文DenseNet好在哪里??!Densely Connected Convolutional Networks!

【深度学习经典模型】CVPR2017的最佳论文DenseNet好在哪里??!Densely Connected Convolutional Networks!

【深度学习经典模型】CVPR2017的最佳论文DenseNet好在哪里??!Densely Connected Convolutional Networks!



欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!
祝所有的硕博生都能遇到好的导师!好的审稿人!好的同门!顺利毕业!
论文链接:https://arxiv.org/pdf/1608.06993
代码链接:https://github.com/liuzhuang13/DenseNet

大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文:
可访问艾思科蓝官网,浏览2024年即将召开的学术会议列表。会议入口:https://ais.cn/u/mmmiUz

1. DenseNet 的起源

DenseNet(Densely Connected Convolutional Networks)是由 Gao Huang 等人于 2017 年提出的,最早发表于论文《Densely Connected Convolutional Networks》【CVPR 2017】。

DenseNet 提出时主要针对深层神经网络中的梯度消失、信息流失和参数冗余问题并通过改进网络的连接方式,显著减少参数量和提升网络的表示能力

2. DenseNet 的原理

DenseNet 的核心思想是 密集连接(Dense Connection),即每一层的输出都直接连接到后续所有层。传统的卷积神经网络(CNN)层与层之间是顺序连接的,而在 DenseNet 中,第 l l l 层的输入不仅仅来自于第 l − 1 l-1 l1 层,还来自于所有之前层的输出。数学上表示为:

x l = H l ( [ x 0 , x 1 , . . . x l − 1 ] ) x_l=H_l([x_0,x_1,...x_{l-1}]) xl=Hl([x0,x1,...xl1])

其中, [ x 0 , x 1 , . . . x l − 1 ] [x_0,x_1,...x_{l-1}] [x0,x1,...xl1]表示将之前各层的输出拼接起来作为输入, H l H_l Hl代表第 l l l层的非线性转换(例如卷积、ReLU 等)。

DenseNet 可以被看作是 ResNet(残差网络)的进一步改进。在 ResNet 中,通过引入残差连接,部分绕过了深层网络中的梯度消失问题,而 DenseNet 则通过密集连接,进一步加强了特征重用,从而提升了模型的表现。

3. DenseNet 的创新点

DenseNet 的主要创新点可以总结为以下几点:

  • 特征重用:通过密集连接,各层之间的特征共享,避免了信息的重复学习,同时减小了过拟合的风险。
  • 梯度流动性更好:由于每一层的梯度都可以通过多个路径进行反向传播,这有助于解决梯度消失问题,并提升模型训练的效率。
  • 参数效率更高:尽管连接更密集,但 DenseNet 的参数量较少,因为每一层只输出较少的特征图。相比 ResNet,DenseNet
    的层更薄,参数量更少,性能却更好。
  • 无信息冗余:因为每一层的输入都包含了所有之前层的输出,因此减少了冗余计算,提高了效率。

4. DenseNet 的发展

DenseNet 提出后迅速受到关注,并在多个任务上取得了卓越的表现,包括图像分类、目标检测、语义分割等。在 ImageNet 数据集上,DenseNet 的表现优于其他深度网络如 ResNet 和 Inception。

DenseNet 也催生了多个变种版本和改进,例如:

  • DenseNet-BC:增加了对 Bottleneck 结构和 Compression 机制的支持,以进一步减少模型参数和计算复杂度。
  • DenseNet for Segmentation:DenseNet 在图像分割任务中表现优越,尤其在医学图像分割中,因其良好的梯度流动性和特征重用性,大大提升了分割的精度。
  • DenseNet 与其他网络结合:DenseNet 还被应用于与其他网络架构相结合,如与 LSTM、Transformer 等结合进行时序分析等任务。

5. DenseNet 的应用

DenseNet 广泛应用于以下领域:

  • 图像分类:DenseNet 的特征重用性和高效的梯度传递特性,使其在 CIFAR、ImageNet 等数据集上表现优秀。
  • 医学影像分析:由于 DenseNet 在信息提取方面的优越性能,在医学影像分析(如病变检测、医学分割)中,DenseNet 作为基础架构有着广泛应用。
  • 目标检测:DenseNet 在目标检测任务中,也可以用作主干网络(backbone),例如在 Faster R-CNN 中替代 ResNet。
  • 语义分割:DenseNet 由于层间连接密集,在语义分割任务中能够更好地捕捉细节信息,被广泛用于 UNet、DeepLab 等模型的改进版。

6. DenseNet 的 Python 实现

接下来,我们将通过 PyTorch 实现 DenseNet,并使用其进行 CIFAR-10 数据集上的分类任务。代码包含逐行解释。

DenseNet 实现

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# 定义DenseNet的基本块 - Dense Layer
class DenseLayer(nn.Module):
    def __init__(self, in_channels, growth_rate):
        super(DenseLayer, self).__init__()
        # Batch Normalization -> ReLU -> 3x3 卷积
        self.bn = nn.BatchNorm2d(in_channels)
        self.relu = nn.ReLU(inplace=True)
        self.conv = nn.Conv2d(in_channels, growth_rate, kernel_size=3, padding=1, bias=False)

    def forward(self, x):
        # 输入 x 是之前所有层的输出
        out = self.conv(self.relu(self.bn(x)))
        # 将新产生的特征与输入拼接
        return torch.cat([x, out], 1)

# 定义DenseBlock
class DenseBlock(nn.Module):
    def __init__(self, num_layers, in_channels, growth_rate):
        super(DenseBlock, self).__init__()
        layers = []
        # 在 Dense Block 中,多个 DenseLayer 堆叠
        for i in range(num_layers):
            layers.append(DenseLayer(in_channels + i * growth_rate, growth_rate))
        self.block = nn.Sequential(*layers)

    def forward(self, x):
        return self.block(x)

# 定义 Transition Layer 用于减少特征图大小和通道数
class TransitionLayer(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(TransitionLayer, self).__init__()
        self.bn = nn.BatchNorm2d(in_channels)
        self.relu = nn.ReLU(inplace=True)
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False)
        self.pool = nn.AvgPool2d(2, stride=2)

    def forward(self, x):
        out = self.conv(self.relu(self.bn(x)))
        out = self.pool(out)
        return out

# 定义DenseNet
class DenseNet(nn.Module):
    def __init__(self, num_blocks, num_layers_per_block, growth_rate, num_classes=10):
        super(DenseNet, self).__init__()
        # 初始卷积层
        self.conv1 = nn.Conv2d(3, 2 * growth_rate, kernel_size=3, padding=1, bias=False)
        # 构建Dense Blocks
        channels = 2 * growth_rate
        self.dense_blocks = nn.ModuleList()
        self.transition_layers = nn.ModuleList()

        for i in range(num_blocks):
            self.dense_blocks.append(DenseBlock(num_layers_per_block, channels, growth_rate))
            channels += num_layers_per_block * growth_rate
            if i != num_blocks - 1:
                # 增加Transition层
                self.transition_layers.append(TransitionLayer(channels, channels // 2))
                channels = channels // 2

        # 全局平均池化层和全连接层
        self.bn = nn.BatchNorm2d(channels)
        self.relu = nn.ReLU(inplace=True)
        self.fc = nn.Linear(channels, num_classes)

    def forward(self, x):
        # 前向传播
        out = self.conv1(x)
        for i, block in enumerate(self.dense_blocks):
            out = block(out)
            if i != len(self.dense_blocks) - 1:
                out = self.transition_layers[i](out)
        out = self.relu(self.bn(out))
        out = F.adaptive_avg_pool2d(out, (1, 1))
        out = torch.flatten(out, 1)
        out = self.fc(out)
        return out

# 超参数设置
growth_rate = 12
num_blocks = 3
num_layers_per_block = 4

# 模型实例化
model = DenseNet(num_blocks, num_layers_per_block, growth_rate)

# 设定训练数据集和测试数据集
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练模型
def train(model, device, train_loader, optimizer, criterion, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()

# 测试模型
def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += criterion(output, target).item()
            pred = output.argmax(dim=1, keepdim=True)
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)
    accuracy = 100. * correct / len(test_loader.dataset)
    print(f'Test set: Average loss: {test_loss:.4f}, Accuracy: {correct}/{len(test_loader.dataset)} ({accuracy:.0f}%)')

# 将模型放到GPU上训练
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)

# 进行若干轮的训练与测试
for epoch in range(1, 11):
    train(model, device, train_loader, optimizer, criterion, epoch)
    test(model, device, test_loader)

代码解释:

  • DenseLayer:DenseNet 的核心组件,每一层输出都会与输入拼接。
  • DenseBlock:由多个 DenseLayer 组成,用于进行特征的级联输出。
  • TransitionLayer:用于减少特征图的大小和通道数,通过 1x1 卷积层和池化操作。
  • DenseNet:通过多个 DenseBlock 和 TransitionLayer 组合,实现深层网络。
  • 训练和测试代码:模型的训练函数 train() 和测试函数 test(),用于 CIFAR-10 数据集上的训练和评估。

这个实现展示了 DenseNet 的基本架构,适用于图像分类任务。

欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!
祝所有的硕博生都能遇到好的导师!好的审稿人!好的同门!顺利毕业!

大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文:
可访问艾思科蓝官网,浏览2024年即将召开的学术会议列表。会议入口:https://ais.cn/u/mmmiUz

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值