首页 > 其他分享 >ResNet模型原理及Pytorch实现

ResNet模型原理及Pytorch实现

时间:2024-09-19 23:24:44浏览次数:3  
标签:nn self 残差 ResNet channels Pytorch 模型 out

ResNet(Residual Network,残差网络)模型是由微软亚洲研究院的何凯明等人在2015年提出的一种深度神经网络结构。其核心原理在于通过残差连接(residual connections)解决了深层网络训练中的梯度消失和梯度爆炸问题,使得网络可以训练得更深,性能更强。以下是ResNet模型原理的详细解析:

一、背景与挑战

在深度学习中,随着神经网络层数的增加,通常认为网络能够学习到更复杂的特征表示,从而提高模型的性能。然而,在实际应用中,过深的网络往往会导致梯度消失、梯度爆炸、过拟合以及低级特征丢失等问题,进而引发性能退化。梯度消失问题尤为严重,它指的是在网络训练过程中,梯度在反向传播过程中可能会逐渐变小,导致网络无法进行有效的参数更新,从而影响模型的性能。

二、残差学习

为了解决上述问题,ResNet引入了残差学习的概念。残差学习的基本思想是,网络的输入和输出之间的差异(即残差)可以通过添加一个残差块来学习。残差块的设计允许输入信号直接传递到块的输出端,与经过卷积层处理后的信号相加。这样,残差块的目标就变成了学习一个残差函数,即输入到输出之间的差异,而不是整个映射函数。

三、残差块结构

ResNet的核心是残差块(Residual Block),一个标准的残差块包含两个或更多的卷积层,以及一个从输入直接连接到块输出的“捷径连接”(Shortcut Connection)。这个捷径连接允许输入信号直接传递到块的输出端,与经过卷积层处理后的信号相加。残差块可以表示为:

y = F ( x , { W i } ) + x y = F(x, \{W_i\}) + x y=F(x,{Wi​})+x

其中, x x x 是输入, y y y 是输出, F ( x , { W i } ) F(x, \{W_i\}) F(x,{Wi​}) 是残差块中卷积层对输入 x x x 的变换(包括卷积、归一化、激活等操作), W i W_i Wi​ 是残差块中卷积层的权重参数。

需要注意的是,当输入和输出的维度不同时,需要在捷径连接上增加一个1x1的卷积层来调整输入的维度,以便进行相加操作。

四、优势与效果

ResNet通过引入残差连接,实现了以下优势:

  1. 缓解梯度消失问题:残差连接允许梯度在反向传播时直接传递到浅层,避免了梯度在传递过程中的损失,从而缓解了梯度消失问题。
  2. 提升网络深度:由于解决了梯度消失问题,ResNet可以训练更深的网络,从而获得更强的性能。
  3. 提高训练效率:残差学习使得网络更容易优化,提高了训练效率。
  4. 降低过拟合风险:较深的网络虽然具有更强的表达能力,但也更容易过拟合。然而,由于ResNet的特殊结构,它在一定程度上降低了过拟合的风险。

五、应用场景

ResNet自提出以来,在计算机视觉领域取得了广泛的应用和成功。它已经成为许多视觉任务的基线模型,如图像分类、目标检测、语义分割等。此外,ResNet的思想也被广泛应用于其他深度学习任务中,推动了深度学习的发展。

六、Pytorch实现

在PyTorch中实践ResNet模型涉及到定义残差块(Residual Block)并将它们堆叠成完整的网络架构。以下是一个简化的ResNet模型在PyTorch中的实践示例。这个示例将展示如何定义残差块,并将它们用于构建一个具有多个残差块的ResNet网络。

首先,我们需要定义残差块。残差块通常包含两个或三个卷积层,以及一个捷径连接(shortcut connection),该连接允许输入信号直接跳过卷积层并添加到块的输出上。

然后,我们将使用这些残差块来构建ResNet的主体部分,包括卷积层、残差块堆叠、以及可能的下采样操作。

最后,我们将添加必要的分类层(如全局平均池化层和全连接层)来完成网络。

以下是一个简单的ResNet-18(一个具有18层的ResNet变体)的PyTorch实现示例:

import torch
import torch.nn as nn
import torch.nn.functional as F

class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, in_channels, out_channels, stride=1, downsample=None):
        super(BasicBlock, 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.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)
        self.downsample = downsample

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out

class ResNet(nn.Module):
    def __init__(self, block, layers, num_classes=1000):
        super(ResNet, self).__init__()
        self.in_channels = 64
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = self._make_layer(block, 64, layers[0])
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(512 * block.expansion, num_classes)

    def _make_layer(self, block, out_channels, blocks, stride=1):
        downsample = None
        if stride != 1 or self.in_channels != out_channels * block.expansion:
            downsample = nn.Sequential(
                nn.Conv2d(self.in_channels, out_channels * block.expansion,
                          kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(out_channels * block.expansion),
            )

        layers = []
        layers.append(block(self.in_channels, out_channels, stride, downsample))
        self.in_channels = out_channels * block.expansion
        for _ in range(1, blocks):
            layers.append(block(self.in_channels, out_channels))

        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)

        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)

        return x

# 定义ResNet-18
def resnet18(num_classes=1000):
    return ResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes)

# 实例化模型
model = resnet18(num_classes=10)  # 假设有10个类别
print(model)

在这个示例中,BasicBlock 类定义了ResNet的基本残差块,它包含两个卷积层和一个捷径连接。ResNet 类定义了完整的ResNet网络架构,包括初始卷积层、池化层、多个残差块堆叠层以及最后的分类层。resnet18 函数是一个工厂函数,用于创建具有特定层数和类别数的ResNet-18模型。

请注意,这个示例是一个简化的ResNet-18实现,用于教学目的。在实际应用中,你可能需要根据具体任务调整网络架构(如层数、卷积核大小、步长等)和训练参数(如学习率、优化器、正则化等)。

综上所述,ResNet模型通过引入残差学习的概念,成功地解决了深层网络训练中的梯度消失和梯度爆炸问题,推动了深度神经网络在计算机视觉等领域的发展。

标签:nn,self,残差,ResNet,channels,Pytorch,模型,out
From: https://blog.csdn.net/u013571432/article/details/142372132

相关文章

  • 利用AutoGpt将任何模型支持o1模型的推理实现
    利用AutoGpt将任何模型支持o1模型的推理实现相信大家都对于OpenAI最新出的o1模型都非常关注,它已经能通过推理让回复的效果更加理想,但是目前o1的限制太大,而且使用o1至少也是需要购买OpenAI官方的会员价格也在20美刀(好贵!!),于是乎社区出现非常多相似的实现,通过更低成本得到更好的效果......
  • 如何在Java中实现多种深度学习模型的集成学习
    如何在Java中实现多种深度学习模型的集成学习大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!集成学习是一种通过组合多个模型来提高预测性能的技术。通过将不同模型的优势结合起来,集成学习可以有效地提高模型的准确性和鲁棒性。在深度学习领域,集成......
  • Java中的高效模型压缩技术:从剪枝到知识蒸馏
    Java中的高效模型压缩技术:从剪枝到知识蒸馏大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!随着深度学习模型在各种任务中的广泛应用,模型的规模和复杂度也在不断增加。然而,较大的模型通常会占用大量的计算资源和内存,使其在资源有限的设备上(如移动设......
  • 每天五分钟深度学习框架pytorch:pytorch中已经定义好的损失函数
    本文重点前面我们学习了pytorch中两种模式的损失函数,一种是nn,另外一种是functional,本文将讲解pytorch中已经封装好的损失函数。其实nn的方式就是类,而functional的方式就是方法。nn中使用的也是functional。损失函数中的参数无论是nn还是functional,大多数的损失函数都有size......
  • day4[大模型全链路开源开放体系学习小结]
    书生·浦语大模型全链路开源开放体系涵盖数据收集、标注、训练、微调、评测、部署等全链路,学习了解其技术发展、性能提升、模型架构、开源生态等。书生·浦语大模型(英文名INTurnLLM)多次开源,性能不断提升,达到国际先进水平,在推理能力、上下文记忆、自主规划等方面表现优异,可应用......
  • 【大模型开发】 迎接AI新时代:Qwen2.5发布,超越LLaMA3!如何通过一键API调用不同模型?(附源
    迎接AI新时代:Qwen2.5发布,超越LLaMA3!如何通过一键API调用不同模型?人工智能领域迎来了新的突破,阿里巴巴近期发布了全新的Qwen2.5模型系列,凭借其72B参数的核心模型,不仅在参数量上显著优化,还成功超越了LLaMA3(405B),在多个自然语言处理和代码生成任务中取得了卓越的表现。Qwen......
  • 大模型-调用星火大模型api进行翻译-04
    目录1.描述2代码1.描述项目描述:本项目使用了streamlit框架来构建前端,展示一些标语、输入框和按钮。后端的大模型是星火大模型V3.0版本。项目运行说明:1、首先,从开放平台获取密钥信息,用于调用星火大模型时的鉴权密钥(前提是已经获得了token授权)。获取地址:https://console.xf......
  • 1-bit 大模型(LLM)时代的到来
     人工智能咨询培训老师叶梓转载标明出处模型规模的扩大带来了部署上的挑战,并因其高能耗引对环境和经济产生了影响。为了应对这些挑战,研究者们开始探索使用低位宽量化技术来降低模型的推理成本,同时保持模型性能。微软公司和中国科学院大学的研究团队提出了一种名为BitNetb1.......
  • LLM - 理解 多模态大语言模型(MLLM) 的 评估(Evaluation) 与相关技术 (六)
    欢迎关注我的CSDN:https://spike.blog.csdn.net/本文地址:https://spike.blog.csdn.net/article/details/142364884免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。评估(Evaluation)是研发多模态大语言模型(MLLM)的重要部分,也为模型的优化提......
  • 大语言模型都能做什么
    与一般的AI模型相比,大模型的参数特别多(通常在10亿以上),训练时需要大规模的数据(动辄百万计,往往还需要进行大量的人工标注),可见大模型的训练成本通常比较高昂。当前AI的本质能力上是预测:AI能通过大数据训练,总结过去的规律,预测未来。比如我们问AI:“内蒙古的首府是哪个城市?”,其实AI并......