【论文阅读及复现】(2017)Densely Connected Convolutional Networks + Pytorch代码实现

简介: - 最近的工作表明,如果卷积网络在靠近输入的层和靠近输出的层之间包含较短的连接,则它们可以更深、更准确和更有效地训练。- 在本文中,我们接受了这一观察并介绍了密集卷积网络(DenseNet),它以前馈方式将每一层连接到其他每一层。具有 L 层的传统卷积网络有 L 个连接——每层与其后续层之间有一个连接——我们的网络有 L*(L+1) /2 个直接连接。 F 或每一层,所有前面的层的特征图被用作输入,它自己的特征图被用作所有后续层的输入。 - DenseNets 有几个引人注目的优势:它们缓解了梯度消失问题,加强了特征传播,鼓励特征重用,并大大减少了参数的数量。- 我们在四个竞争激烈的对象

@[toc]


论文来源:(2017)Densely Connected Convolutional Networks
作者:Gao Huang 等人

一、摘要

  • 最近的工作表明,如果卷积网络在靠近输入的层和靠近输出的层之间包含较短的连接,则它们可以更深、更准确和更有效地训练。
  • 在本文中,我们接受了这一观察并介绍了密集卷积网络(DenseNet),它以前馈方式将每一层连接到其他每一层。具有 L 层的传统卷积网络有 L 个连接——每层与其后续层之间有一个连接——我们的网络有 L*(L+1) /2 个直接连接。 F 或每一层,所有前面的层的特征图被用作输入,它自己的特征图被用作所有后续层的输入。
  • DenseNets 有几个引人注目的优势:它们缓解了梯度消失问题,加强了特征传播,鼓励特征重用,并大大减少了参数的数量。
  • 我们在四个竞争激烈的对象识别基准任务(CIF AR-10、CIF AR-100、SVHN 和 ImageNet)上评估我们提出的架构。
  • DenseNets 在大多数情况下都比最先进的技术获得了显着改进,同时需要更少的计算来实现高性能。

二、Dense Net 网络结构

在这里插入图片描述
在这里插入图片描述

三、Dense Block

在Dense Block中,每一层都与后面的层有跳连接

为了更好的保存低层网络的特征,DenseNet 使用的是将不同层的输出拼接在一起,而在残差网络中使用的是单位加操作。以上便是DenseNet算法的动机
在这里插入图片描述
在Dsense Block中的每一层,都有1×1和3×3两个卷积核

论文中指出:”虽然每一层只产生 k 个输出特征图,但它通常有更多的输入。可以在每个 3×3 卷积之前引入一个 1×1 卷积作为瓶颈层,以减少输入特征图的数量,从而提高计算效率。我们发现这种设计对 DenseNet 特别有效,我们将我们的网络称为具有这样一个瓶颈层的网络,即 H' 的 BN-ReLU-Conv(1×1)-BN-ReLU-Conv(3×3) 版本“

四、PyTorch-GPU代码实现

MNIST手写数据集的图片大小为28×28,如果采用论文里的结构,在第四层pooling时会出现0×0尺寸的情况,为了避免这个情况,我在第四层前的1×1的conv层设置了padding=(1,1),故下面的代码结构不和论文里完全一致

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


def conv_block(in_channels, out_channels):
    block = nn.Sequential(nn.BatchNorm2d(in_channels),
                        nn.ReLU(),
                        nn.Conv2d(in_channels, out_channels, kernel_size=(3, 3), padding=(1, 1)))
    return block


class DenseBlock(nn.Module):
    def __init__(self, in_channels, out_channels, cnt):
        super(DenseBlock, self).__init__()
        net = []
        for i in range(cnt):
            in_c = in_channels + i * out_channels
            net.append(conv_block(in_c, out_channels))
        self.net = nn.ModuleList(net)
        self.out_channels = in_channels + cnt * out_channels  # 计算输出通道数

    def forward(self, x):
        for blk in self.net:
            y = blk(x)
            x = torch.cat((x, y), dim=1)  # 在通道维上将输入和输出拼接
        return x


class DenselyNet(torch.nn.Module):
    def __init__(self):
        super(DenselyNet, self).__init__()
        self.conv7x7 = nn.Conv2d(1, 16, kernel_size=(7, 7), padding=(3, 3), stride=(2, 2))
        self.conv1x1_1 = nn.Conv2d(112, 16, kernel_size=(1, 1))
        self.conv1x1_2 = nn.Conv2d(208, 16, kernel_size=(1, 1))
        self.conv1x1_3 = nn.Conv2d(400, 16, kernel_size=(1, 1),padding=(1,1))
        self.max_pooling3x3 = nn.MaxPool2d(kernel_size=(3, 3), stride=(2, 2))
        self.avg_pooling2x2 = nn.AvgPool2d(kernel_size=(2, 2), stride=(2, 2))

        self.dense_block1 = DenseBlock(16, 16, 6)
        self.dense_block2 = DenseBlock(16, 16, 12)
        self.dense_block3 = DenseBlock(16, 16, 24)
        self.dense_block4 = DenseBlock(16, 16, 16)

        self.fc = nn.Linear(272, 10)

    def forward(self, x):
        in_size = x.size(0)

        x = torch.relu(self.conv7x7(x))
        x = torch.relu(self.max_pooling3x3(x))
        x = self.dense_block1(x)

        x = torch.relu(self.conv1x1_1(x))
        x = torch.relu(self.avg_pooling2x2(x))
        x = self.dense_block2(x)

        x = torch.relu(self.conv1x1_2(x))
        x = torch.relu(self.avg_pooling2x2(x))
        x = self.dense_block3(x)

        x = torch.relu(self.conv1x1_3(x))
        x = torch.relu(self.avg_pooling2x2(x))
        x = self.dense_block4(x)

        x = torch.relu(F.adaptive_avg_pool2d(x, output_size=(1, 1)))

        x = x.view(in_size, -1)
        x = self.fc(x)
        return x


# 单次训练函数
def train(epoch, criterion):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        inputs, target = data
        # 将inputs, target转移到Gpu或者Cpu上
        inputs, target = inputs.to(device), target.to(device)
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, target)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
        if batch_idx % 300 == 299:
            print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0.0


# 单次测试函数
def ttt():
    correct = 0.0
    total = 0.0
    with torch.no_grad():
        for data in test_loader:
            images, labels = data
            # 将images, labels转移到Gpu或者Cpu上
            images, labels = images.to(device), labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print('Accuracy on test set: %d %% [%d/%d]' % (100 * correct / total, correct, total))


if __name__ == '__main__':
    batch_size = 64
    transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
    train_dataset = datasets.MNIST(root='../dataset/', train=True, download=True, transform=transform)

    train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)

    test_dataset = datasets.MNIST(root='../dataset/', train=False, download=True, transform=transform)
    test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)

    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    # 声明模型
    model = DenselyNet()
    # 将模型转移道Gpu或者Cpu上
    model.to(device)
    # 定义损失函数
    criterion = torch.nn.CrossEntropyLoss()
    # 定义优化器
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

    for epoch in range(10):
        train(epoch, criterion)
        ttt()

输出:

[1,   300] loss: 1.274
[1,   600] loss: 0.321
[1,   900] loss: 0.179
Accuracy on test set: 96 % [9699/10000]
[2,   300] loss: 0.114
[2,   600] loss: 0.115
[2,   900] loss: 0.099
Accuracy on test set: 98 % [9813/10000]
[3,   300] loss: 0.080
[3,   600] loss: 0.068
[3,   900] loss: 0.069
Accuracy on test set: 98 % [9864/10000]
[4,   300] loss: 0.053
[4,   600] loss: 0.056
[4,   900] loss: 0.056
Accuracy on test set: 98 % [9873/10000]
[5,   300] loss: 0.041
[5,   600] loss: 0.044
[5,   900] loss: 0.041
Accuracy on test set: 98 % [9882/10000]
[6,   300] loss: 0.033
[6,   600] loss: 0.035
[6,   900] loss: 0.034
Accuracy on test set: 98 % [9864/10000]
[7,   300] loss: 0.033
[7,   600] loss: 0.028
[7,   900] loss: 0.033
Accuracy on test set: 99 % [9903/10000]
[8,   300] loss: 0.024
[8,   600] loss: 0.027
[8,   900] loss: 0.031
Accuracy on test set: 98 % [9883/10000]
[9,   300] loss: 0.020
[9,   600] loss: 0.022
[9,   900] loss: 0.027
Accuracy on test set: 99 % [9901/10000]
[10,   300] loss: 0.019
[10,   600] loss: 0.022
[10,   900] loss: 0.021
Accuracy on test set: 98 % [9883/10000]
相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
4月前
|
存储 物联网 PyTorch
基于PyTorch的大语言模型微调指南:Torchtune完整教程与代码示例
**Torchtune**是由PyTorch团队开发的一个专门用于LLM微调的库。它旨在简化LLM的微调流程,提供了一系列高级API和预置的最佳实践
335 59
基于PyTorch的大语言模型微调指南:Torchtune完整教程与代码示例
|
27天前
|
机器学习/深度学习 存储 算法
近端策略优化(PPO)算法的理论基础与PyTorch代码详解
近端策略优化(PPO)是深度强化学习中高效的策略优化方法,广泛应用于大语言模型的RLHF训练。PPO通过引入策略更新约束机制,平衡了更新幅度,提升了训练稳定性。其核心思想是在优势演员-评论家方法的基础上,采用裁剪和非裁剪项组成的替代目标函数,限制策略比率在[1-ϵ, 1+ϵ]区间内,防止过大的策略更新。本文详细探讨了PPO的基本原理、损失函数设计及PyTorch实现流程,提供了完整的代码示例。
229 10
近端策略优化(PPO)算法的理论基础与PyTorch代码详解
|
6月前
|
机器学习/深度学习 PyTorch 算法框架/工具
CNN中的注意力机制综合指南:从理论到Pytorch代码实现
注意力机制已成为深度学习模型的关键组件,尤其在卷积神经网络(CNN)中发挥了重要作用。通过使模型关注输入数据中最相关的部分,注意力机制显著提升了CNN在图像分类、目标检测和语义分割等任务中的表现。本文将详细介绍CNN中的注意力机制,包括其基本概念、不同类型(如通道注意力、空间注意力和混合注意力)以及实际实现方法。此外,还将探讨注意力机制在多个计算机视觉任务中的应用效果及其面临的挑战。无论是图像分类还是医学图像分析,注意力机制都能显著提升模型性能,并在不断发展的深度学习领域中扮演重要角色。
224 10
|
9月前
|
机器学习/深度学习 PyTorch 算法框架/工具
【从零开始学习深度学习】28.卷积神经网络之NiN模型介绍及其Pytorch实现【含完整代码】
【从零开始学习深度学习】28.卷积神经网络之NiN模型介绍及其Pytorch实现【含完整代码】
|
5月前
|
机器学习/深度学习 PyTorch 算法框架/工具
聊一聊计算机视觉中常用的注意力机制以及Pytorch代码实现
本文介绍了几种常用的计算机视觉注意力机制及其PyTorch实现,包括SENet、CBAM、BAM、ECA-Net、SA-Net、Polarized Self-Attention、Spatial Group-wise Enhance和Coordinate Attention等,每种方法都附有详细的网络结构说明和实验结果分析。通过这些注意力机制的应用,可以有效提升模型在目标检测任务上的性能。此外,作者还提供了实验数据集的基本情况及baseline模型的选择与实验结果,方便读者理解和复现。
314 0
聊一聊计算机视觉中常用的注意力机制以及Pytorch代码实现
|
7月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch代码实现神经网络
这段代码示例展示了如何在PyTorch中构建一个基础的卷积神经网络(CNN)。该网络包括两个卷积层,分别用于提取图像特征,每个卷积层后跟一个池化层以降低空间维度;之后是三个全连接层,用于分类输出。此结构适用于图像识别任务,并可根据具体应用调整参数与层数。
115 9
|
9月前
|
机器学习/深度学习 PyTorch 算法框架/工具
【从零开始学习深度学习】29.卷积神经网络之GoogLeNet模型介绍及用Pytorch实现GoogLeNet模型【含完整代码】
【从零开始学习深度学习】29.卷积神经网络之GoogLeNet模型介绍及用Pytorch实现GoogLeNet模型【含完整代码】
|
2月前
|
机器学习/深度学习 搜索推荐 PyTorch
基于昇腾用PyTorch实现传统CTR模型WideDeep网络
本文介绍了如何在昇腾平台上使用PyTorch实现经典的WideDeep网络模型,以处理推荐系统中的点击率(CTR)预测问题。
220 66
|
15天前
|
机器学习/深度学习 算法 安全
用PyTorch从零构建 DeepSeek R1:模型架构和分步训练详解
本文详细介绍了DeepSeek R1模型的构建过程,涵盖从基础模型选型到多阶段训练流程,再到关键技术如强化学习、拒绝采样和知识蒸馏的应用。
142 3
用PyTorch从零构建 DeepSeek R1:模型架构和分步训练详解
|
5月前
|
算法 PyTorch 算法框架/工具
Pytorch学习笔记(九):Pytorch模型的FLOPs、模型参数量等信息输出(torchstat、thop、ptflops、torchsummary)
本文介绍了如何使用torchstat、thop、ptflops和torchsummary等工具来计算Pytorch模型的FLOPs、模型参数量等信息。
708 2