神经网络----Pytorch实现残差网络Restnet18

神经网络----Pytorch实现残差网络ResNet18

前言

ResNet18是参照👉https://www.bilibili.com/video/BV1154y1S7WC?share_source=copy_web中up主搭建ResNet的思路来实现的。如有错误或其他问题,欢迎指出!!!

此外,本文只介绍实现的思路,不对ResNet做具体解读。

ResNet18结构介绍

网络的整体结构如下图
在这里插入图片描述

从图中可以看到红色框内八个比较特别的块,这些块就是该网络的特色:残差结构

残差结构

如图,可以看出最终的输出包括两个部分:经过处理后的F(x)和原始输入x
在这里插入图片描述

ResNet18

从刚刚的网络整体结构图我们可以看到红色框内的块不完全相同,有两类:Identity BlockConv Block

Identity Block
Conv Block

两者的结构如下图,左边的主干部分两者是相同的:两次 [卷积,标准化,激活函数] 和一次 [卷积,标准化]

不同的是在右侧的残差边,Identity Block直接将 原始输入 与左侧结果相连,而Conv Block对原始输入进行了一次 [卷积,标准化] 后再与左侧结果相连。

ResNet18与ResNet50网络对比

开始之前先对后面会用到的结构代称做个介绍
一个Stage中含有多个Bottleneck,Bottleneck是Conv Block和Identity Block的统称
在这里插入图片描述

相似点

C1结构分割
在参考的视频中,有这样一张图
在这里插入图片描述

作者把输出通道数相同的Bottleneck(包括Identity Block和Conv Block)整合成一个Stage,于是得到了4个输出通道数不同的Stage。

而对比以下ResNet18和ResNet50,我们也可以把ResNet18分成4个Stage。

PS:图源网络

C2对残差边的处理

将残差边由两部分决定,若此时的Bottleneck是Conv Block,则对x进行处理,将结果赋值给side;若是Identity Block则side = None。

后续定义残差边residual=初始输入x,然后读取side,若side不为None,则说明残差边进行了处理,把其值赋给residual;若side为None,则说明残差边没有进行处理,residual仍然为x。

不同点

D1ResNet18中每个 Stage中的 Bottleneck个数相同

  • 在ResNet50中,因为每个Stage的Bottleneck的个数不同,且都是第一个为Conv Block,剩下的都是Identity Block。

所以作者将Stage分成两部分:1)单独处理第一层的Conv Block,2)后续的Identity Block通过传入一个list:[3, 4, 6, 3],读取为block_num放入循环中实现剩余的Identity Block。

# Conv Block
        conv_block = block(self.inplane, midplane, stride=stride, downsample=downsample)

# Identity Block
for i in range (1, block_num):
    block_list.append(block(self.inplane, midplane, stride=1))
  • 在ResNet18中每个Stage中的Bottleneck个数相同,所以我们不用传入list,不用循环,直接实现
block1 = block(in_ch, self.out_ch, stride=stride, side=side)
block2 = block(self.out_ch, self.out_ch, stride=1, side=None)

D2ResNet18中 Stage1的第一个 Bottleneck是 Identity Block而不是 Conv Block

  • 在ResNet50中,Identity Block有两个特点:

1)stride=1

2)每个Identity Block的最终输出结果通道数 = 中间处理层 [卷积,标准化,激活函数] 结果通道数 * 4

所以不满足这两个特点的就是Conv Block,我们就需要对其残差边输入的x进行处理

if stride != 1 or self.inplane != midplane*block.extention:
    downsample = nn.Sequential(
        nn.Conv2d(self.inplane, midplane*block.extention, kernel_size=1, stride=stride, bias=False),
        nn.BatchNorm2d(midplane*block.extention)
    )
  • 在ResNet18中,Identity Block和Conv Block用stride就可以区别
if stride != 1:
    side = nn.Sequential(
        nn.Conv2d(in_ch, self.out_ch, kernel_size=1, stride=2, bias=False),
        nn.BatchNorm2d(self.out_ch)
    )

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
ResNet-18是一种残差神经网络模型,它是由18个卷积层和全连接层组成的深度神经网络。残差神经网络是一种通过引入残差连接来解决梯度消失和梯度爆炸问题的网络结构。在ResNet-18中,残差连接通过跳跃连接的方式将输入直接添加到输出中,使得网络可以更好地学习到残差信息,从而提高了网络的性能和训练效果。 关于如何使用Pytorch编写一个ResNet-18残差神经网络,你可以按照以下步骤进行操作: 1. 导入必要的库和模块: ```python import torch import torch.nn as nn import torchvision.models as models ``` 2. 定义ResNet-18模型: ```python model = models.resnet18(pretrained=False) ``` 3. 修改最后一层的输出维度: ```python num_classes = 10 # CIFAR10数据集的类别数 model.fc = nn.Linear(512, num_classes) ``` 4. 定义损失函数和优化器: ```python criterion = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9) ``` 5. 加载数据集并进行训练: ```python # 这里假设你已经准备好了CIFAR10数据集 train_loader = ... test_loader = ... num_epochs = 10 for epoch in range(num_epochs): for images, labels in train_loader: # 前向传播 outputs = model(images) loss = criterion(outputs, labels) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() # 在测试集上评估模型 with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total print(f'Epoch [{epoch+1}/{num_epochs}], Accuracy: {accuracy}%') ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值