【深度学习基础模型】深度残差网络(Deep Residual Networks, DRN)详细理解并附实现代码。

news2024/10/5 10:22:45

【深度学习基础模型】深度残差网络(Deep Residual Networks, DRN)详细理解并附实现代码。

【深度学习基础模型】深度残差网络(Deep Residual Networks, DRN)详细理解并附实现代码。


文章目录

  • 【深度学习基础模型】深度残差网络(Deep Residual Networks, DRN)详细理解并附实现代码。
  • 1. 算法提出
  • 2. 概述
  • 3. 发展
  • 4. 应用
  • 5. 优缺点
  • 6. Python代码实现


参考地址:https://www.asimovinstitute.org/neural-network-zoo/
论文地址:https://arxiv.org/pdf/1512.03385

欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!
在这里插入图片描述

1. 算法提出

深度残差网络(DRN)最初由何凯明等人于2015年在论文“Deep Residual Learning for Image Recognition”中提出。该算法的核心思想是通过残差块(Residual Block)来解决深层神经网络训练中的退化问题

传统神经网络在层数增加时,随着网络变深,训练误差反而会上升,这种现象被称为梯度消失/爆炸问题DRN通过引入跳跃连接(Skip Connection),将前几层的输入直接传递到后几层,从而有效缓解了这个问题

2. 概述

DRN的核心结构是残差块。一个典型的残差块包含一个跳跃连接,将输入直接加到输出上,如下所示:

y = F ( x ) + x y=F(x)+x y=F(x)+x

其中, x x x是残差块的输入, F ( x ) F(x) F(x)是经过几层非线性变换后的输出。通过将输入 x x x直接添加到输出 F ( x ) F(x) F(x),残差网络实际上是在学习一个残差函数。这种结构使得网络能够更容易训练,并且即使网络层数增加,网络也不会出现退化现象。

残差网络的优点在于:

  • 更深的网络结构:传统前馈神经网络(Feedforward Neural Networks, FFNN)的层数通常在几层到几十层,而DRN可以扩展到上百层甚至更深(如ResNet-152)。
  • 稳定的训练过程:通过引入跳跃连接,梯度可以更好地传播,从而缓解了梯度消失问题。

3. 发展

自2015年提出以来,残差网络成为了许多深度学习模型的基础架构。随着研究的深入,残差网络的变种也被提出,例如:

  • ResNet:最早的残差网络版本,适用于图像分类等任务。
  • ResNeXt:将残差块中的卷积运算拆分为多个并行的路径,提高了模型的可扩展性。
  • DenseNet:一种变体,进一步增加了层之间的密集连接。

4. 应用

DRN被广泛应用于各种深度学习任务中,特别是在计算机视觉领域表现出色。典型的应用包括:

  • 图像分类:ResNet在ImageNet分类任务中取得了极好的效果,常用于图像分类任务。
  • 目标检测:许多目标检测模型(如Faster R-CNN)都基于残差网络作为主干结构。
  • 语义分割:在语义分割任务中,残差网络作为特征提取器也广泛使用。

5. 优缺点

优点:

  • 有效的深度学习:DRN能够有效训练非常深的网络(可达150层甚至更多),而不会出现明显的性能退化。
  • 跳跃连接:通过跳跃连接,DRN能够更好地传播梯度,解决梯度消失问题,从而加快训练速度。
  • 强大的表达能力:可以通过残差学习获得更高的模型表达能力,适用于复杂的学习任务。

缺点:

  • 计算复杂性高:随着网络深度的增加,计算资源需求显著增加,训练时间可能较长。
  • 模型可解释性差:深度模型的复杂性可能导致难以解释其内部机制和决策过程。
  • 需要大量数据:有效训练深度残差网络通常需要大量标注数据,以防止过拟合。

6. Python代码实现

以下是一个使用深度残差网络进行图像分类的示例,基于PyTorch框架:

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

# 定义残差块
class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super(ResidualBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_channels)
        
        # 如果输入维度和输出维度不匹配,通过1x1卷积进行匹配
        self.shortcut = nn.Sequential()
        if stride != 1 or in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(out_channels)
            )
        
    def forward(self, x):
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)  # 跳跃连接
        out = self.relu(out)
        return out

# 定义ResNet模型
class ResNet(nn.Module):
    def __init__(self, block, num_blocks, num_classes=10):
        super(ResNet, self).__init__()
        self.in_channels = 64
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
        self.avg_pool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(512, num_classes)
    
    def _make_layer(self, block, out_channels, num_blocks, stride):
        layers = []
        layers.append(block(self.in_channels, out_channels, stride))
        self.in_channels = out_channels
        for _ in range(1, num_blocks):
            layers.append(block(self.in_channels, out_channels))
        return nn.Sequential(*layers)
    
    def forward(self, x):
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = self.avg_pool(out)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        return out

# 实例化ResNet18模型
def ResNet18():
    return ResNet(ResidualBlock, [2, 2, 2, 2])  # 定义ResNet18结构

# 数据预处理
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
])

# 加载CIFAR-10数据集
train_dataset = datasets.CIFAR10(root='./data', train=True, transform=transform, download=True)
test_dataset = datasets.CIFAR10(root='./data', train=False, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=100, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=100, shuffle=False)

# 定义设备、损失函数和优化器
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = ResNet18().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练模型
def train_model(num_epochs=5):
    for epoch in range(num_epochs):
        model.train()
        for images, labels in train_loader:
            images, labels = images.to(device), labels.to(device)
            outputs = model(images)
            loss = criterion(outputs, labels)
            
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# 评估模型
def test_model():
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print(f'测试集准确率: {100 * correct / total:.2f}%')

# 运行训练和测试
train_model(num_epochs=5)
test_model()

代码解释:

  • ResidualBlock:实现了残差块,其中包括卷积层、批量归一化(Batch Normalization)、ReLU激活函数和跳跃连接。通过跳跃连接,将输入直接加到输出中,以实现残差学习。
  • ResNet:定义了ResNet模型结构,包括多个残差块的堆叠。_make_layer方法用于构建每一层的残差块。
  • 数据预处理:使用transforms.Compose对CIFAR-10数据集进行转换,进行标准化处理。
  • 模型训练:在train_model函数中,模型通过多轮训练,不断优化损失函数。
  • 模型评估:在test_model函数中,模型评估在测试集上的性能,并输出准确率。

该代码实现了基于深度残差网络的图像分类任务,展示了DRN在实际应用中的有效性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2189718.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ | Leetcode C++题解之第457题环形数组是否存在循环

题目&#xff1a; 题解&#xff1a; class Solution { public:bool circularArrayLoop(vector<int>& nums) {int n nums.size();auto next [&](int cur) {return ((cur nums[cur]) % n n) % n; // 保证返回值在 [0,n) 中};for (int i 0; i < n; i) {if …

【人工智能深度学习应用】妙搜API最佳实践

功能概述 AI妙搜通过集成夸克通用搜索引擎&#xff0c;能够提供一个强大的搜索素材功能&#xff0c;大大提升内容创作者在寻找和使用网络资源时的效率和便捷性。用户只需输入相关的关键词或描述&#xff0c;系统将根据用户的搜索词在互联网上进行搜索&#xff0c;并展示与搜索…

【3D目标检测】激光雷达和相机联合标定(一)——ROS同步解包

ROS同步解包 引言1 鱼香ROS一键安装ros-docker脚本&#xff1a;2 指定目录映射3 数据解包3.1 解包脚本3.2 依赖安装3.3 运行脚本&#xff0c;解包 引言 总结步骤如下&#xff1a; 采集同步数据&#xff1a;ROS录制&#xff08;推荐&#xff09;&#xff0c;或者代码同步触发采…

C++入门基础知识99——【关于C++ 成员运算符】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C 成员运算符的相关内容&#xff01; 关…

昇思学习打卡营第32天|基于ResNet50的中药炮制饮片质量判断模型

背景介绍 中药炮制是根据中医药理论&#xff0c;依照临床用药需求&#xff0c;通过调剂和制剂要求&#xff0c;将中药材制备成中药饮片的过程。老百姓日常使用的中药饮片&#xff0c;是中药炮制技术的成果。中药炮制过程中&#xff0c;尤其是涉及到水火处理时&#xff0c;必须注…

CNN模型对CIFAR-10中的图像进行分类

代码功能 这段代码展示了如何使用 Keras 和 TensorFlow 构建一个卷积神经网络&#xff08;CNN&#xff09;模型&#xff0c;用于对 CIFAR-10 数据集中的图像进行分类。主要功能包括&#xff1a; 加载数据&#xff1a;从 CIFAR-10 数据集加载训练和测试图像。 数据预处理&#…

HTTP【网络】

文章目录 HTTPURL(Uniform Resource Lacator) HTTP协议格式HTTP的方法HTTP的状态码HTTP常见的Header HTTP 超文本传输协议&#xff0c;是一个简单的请求-响应协议&#xff0c;HTTP通常运行在TCP之上 URL(Uniform Resource Lacator) 一资源定位符&#xff0c;也就是通常所说的…

NIM简单实践-图像分割

项目背景 我正在学习一个图像分割的 Demo&#xff0c;使用 NVIDIA 提供的预训练大模型进行光学字符检测 (OCDNet) 和光学字符识别 (OCRNet)。这些模型专门为光学字符检测和识别设计&#xff0c;能够自动将图像中的字符进行分割和识别。 预训练模型介绍 OCDNet (Optical Char…

Windows NTLM中继攻击(PortBender二进制可执行文件)

Windows NTLM中继攻击&#xff08;PortBender二进制可执行文件) 前言 最近在完善自己的一套TTPs&#xff08;战术、技术和程序&#xff09;以应对未来的网络作战、项目和攻防演练需求&#xff0c;翻到了PortBender&#xff0c;我觉得不依赖C2和影响主机本身实现这一切非常有趣…

如何使用ssm实现民族大学创新学分管理系统分析与设计+vue

TOC ssm763民族大学创新学分管理系统分析与设计vue 第1章 绪论 1.1 课题背景 二十一世纪互联网的出现&#xff0c;改变了几千年以来人们的生活&#xff0c;不仅仅是生活物资的丰富&#xff0c;还有精神层次的丰富。在互联网诞生之前&#xff0c;地域位置往往是人们思想上不…

Linux 生产者消费者模型

前言 生产者消费者模型&#xff08;CP模型&#xff09;是一种十分经典的设计&#xff0c;常常用于多执行流的并发问题中&#xff01;很多书上都说他很高效&#xff0c;但高效体现在哪里并没有说明&#xff01;本博客将详解&#xff01; 目录 前言 一、生产者消费者模型 1.…

绝美的登录界面!滑动切换效果

绝美登录界面&#xff01;添加了管理员账号和测试账号 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><scri…

RC正弦波振荡电路

0、判断电路能否产生正弦波震荡的条件 如上图所示&#xff0c; Xo:输出量&#xff1b; A:放大器的增益&#xff1b; F:反馈系数。 上式分别为RC正弦波震荡器的幅值条件和相位条件&#xff0c;为了使输出量在合闸后能够有一个从小到大直至平衡在一定幅值的过程&#xff0c;电…

《Linux服务与安全管理》| 配置YUM源并验证

《Linux服务与安全管理》配置YUM源并验证 目录 《Linux服务与安全管理》配置YUM源并验证 任务一&#xff1a;配置本地YUM源 任务二&#xff1a;配置网络YUM源 学生姓名 **** 学号 **** 专业 **** 任务名称 配置YUM源并验证 完成日期 **** 任务目标 知识 了解配…

docker安装kafka-manager

kafkamanager docker安装_mob64ca12d80f3a的技术博客_51CTO博客 # 1、拉取镜像及创建容器 docker pull hlebalbau/kafka-manager docker run -d --name kafka-manager -p 9000:9000 --networkhost hlebalbau/kafka-manager# 2、增设端口 腾讯云# 3、修改防火墙 sudo firewall-…

Salesforce AI 推全新大语言模型评估家族SFR-Judge 基于Llama3构建

在自然语言处理领域&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的发展迅速&#xff0c;已经在多个领域取得了显著的进展。不过&#xff0c;随着模型的复杂性增加&#xff0c;如何准确评估它们的输出就变得至关重要。传统上&#xff0c;我们依赖人类来进行评估&#…

【目标检测】yolo的三种数据集格式

目标检测中数据集格式之间的相互转换--coco、voc、yolohttps://zhuanlan.zhihu.com/p/461488682?utm_mediumsocial&utm_psn1825483604463071232&utm_sourcewechat_session【目标检测】yolo的三种数据集格式https://zhuanlan.zhihu.com/p/525950939?utm_mediumsocial&…

Python小示例——质地不均匀的硬币概率统计

在概率论和统计学中&#xff0c;随机事件的行为可以通过大量实验来研究。在日常生活中&#xff0c;我们经常用硬币进行抽样&#xff0c;比如抛硬币来决定某个结果。然而&#xff0c;当我们处理的是“质地不均匀”的硬币时&#xff0c;事情就变得复杂了。质地不均匀的硬币意味着…

【宽搜】4. leetcode 103 二叉树的锯齿形层序遍历

1 题目描述 题目链接&#xff1a;二叉树的锯齿形层序遍历 2 题目解析 根据题目描述&#xff0c;第一行是从左往右遍历&#xff0c;第二行是从右往左遍历。和层序遍历的区别就是&#xff1a; 在偶数行需要从右往左遍历。 因此&#xff0c;只需要在层序遍历的基础上增加一个变…

网络基础:TCP/IP五层模型、数据在局域网传输和跨网络传输的基本流程、IP地址与MAC地址的简单解析

目录 背景介绍 网络协议 OSI七层模型 TCP/IP五层模型 TCP/IP协议与OS的关系 网络协议的本质 数据在局域网传输的基本流程 MAC地址 报文的封装和解包 补充内容 数据的跨网络传输基本流程 IP地址 IP地址和MAC地址的区别 ​​​ 背景介绍 网络的发展经理了四个阶段…