ResNet34学习笔记+用pytorch手写实现

ResNet34学习笔记+用pytorch手写实现看懂ResNet,需要理解两个点:shortcut的处理,以及网络结构理解1——IdentityMappingbyShortcuts(快捷恒等映射)我们每隔几个堆叠层采用残差学习。构建块如图2所示。在本文中我们考虑构建块正式定义为x和y是考虑的层的输入和输出向量。函数F(x,Wi)表示要学习的残差映射。图2中的例子有两层,F=W2σ(W1x)中σ表示ReLU[29],为了…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

看懂ResNet,需要理解两个点:shortcut的处理,以及网络结构

理解1——Identity Mapping by Shortcuts(快捷恒等映射)

ResNet34学习笔记+用pytorch手写实现

我们每隔几个堆叠层采用残差学习。构建块如图2所示。在本文中我们考虑构建块正式定义为

ResNet34学习笔记+用pytorch手写实现

x和y是考虑的层的输入和输出向量。函数F(x,Wi)表示要学习的残差映射。图2中的例子有两层,F=W2σ(W1x)中σ表示ReLU[29],为了简化忽略偏置项。F+x操作通过快捷连接和各个元素相加来执行。在相加之后我们采纳了第二种非线性(即σ(y),看图2)。

公式(1)中的快捷连接既没有引入外部参数又没有增加计算复杂度。这不仅在实践中有吸引力,而且在简单网络和残差网络的比较中也很重要。我们可以公平地比较同时具有相同数量的参数,相同深度,宽度和计算成本的简单/残差网络(除了不可忽略的元素加法之外)。

方程(1)中x和F的维度必须是相等的。如果不是这种情况(例如,当更改输入/输出通道时),我们可以对快捷连接执行线性投影Ws(进行卷积操作)来匹配维度:

ResNet34学习笔记+用pytorch手写实现

我们也可以在方程(1)中使用方阵Ws。但是我们将通过实验表明,恒等映射足以解决退化问题,并且是合算的,因此Ws仅在匹配维度时使用。

 

理解2——网络架构:

ResNet34学习笔记+用pytorch手写实现

 

简单网络:我们简单网络的基准(图3,中间)主要受到VGG网络[40](图3,左图)的启发。卷积层主要有3×3的滤波器,并遵循两个简单的设计规则:(i)对于相同的输出特征图尺寸,每层具有相同数量的滤波器;(ii)如果特征图尺寸减半,则滤波器数量加倍,以便保持每层的时间复杂度。我们直接用步长为2的卷积层进行下采样。网络以全局平均池化层和具有softmax的1000维全连接层结束。图3(中间)的加权层总数为34。

残差网络。 基于上述的简单网络,我们插入快捷连接(图3,右),将网络转换为其对应的残差版本。当输入和输出具有相同的维度时(图3中的实线连接)时,可以直接使用恒等快捷连接(方程(1))当维度增加(图3中的虚线连接)时,我们考虑两个选项:(A)快捷连接仍然执行恒等映射,额外填充零输入以增加维度。此选项不会引入额外的参数;(B)方程(2)中的投影快捷连接Ws用于匹配维度(由1×1卷积完成)。对于这两个选项,当快捷连接跨越两种尺寸的特征图时,它们执行时步长为2。

B比A好一点,所以代码里用的是B。

文章后面比较了optionA,B,C 。恒等和投影快捷连接我们已经表明没有参数,恒等快捷连接有助于训练。接下来我们调查投影快捷连接(方程2)。我们比较了三个选项:(A) 零填充快捷连接用来增加维度,所有的快捷连接是没有参数的(与表2和图4右相同);(B)投影快捷连接用来增加维度,其它的快捷连接是恒等的;(C)所有的快捷连接都是投影。

表3显示,所有三个选项都比对应的简单网络好很多。选项B比A略好。我们认为这是因为A中的零填充确实没有残差学习。选项C比B稍好,我们把这归因于许多(十三)投影快捷连接引入了额外参数。但A/B/C之间的细微差异表明,投影快捷连接对于解决退化问题不是至关重要的。因为我们在本文的剩余部分不再使用选项C,以减少内存/时间复杂性和模型大小。恒等快捷连接对于不增加下面介绍的瓶颈结构的复杂性尤为重要。

表1。ImageNet架构。构建块显示在括号中,以及构建块的堆叠数量。下采样通过步长为2的conv3_1, conv4_1和conv5_1执行。

ResNet34学习笔记+用pytorch手写实现

ResNet34实现代码:

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

class ResidualBlock(nn.Module):
    #实现子module:Residual Block
    def __init__(self, in_ch, out_ch, stride=1, shortcut=None):
        super(ResidualBlock,self).__init__()
        self.left = nn.Sequential(
            nn.Conv2d(in_ch,out_ch,3,stride,padding=1,bias=False),
            nn.BatchNorm2d(out_ch),
            nn.ReLU(inplace = True),#inplace = True原地操作
            nn.Conv2d(out_ch,out_ch,3,stride=1,padding=1,bias=False),
            nn.BatchNorm2d(out_ch)
            )
        self.right = shortcut
        
    def forward(self,x):
        out = self.left(x)
        residual = x if self.right is None else self.right(x)
        out += residual
        return F.relu(out)
        
class ResNet34(nn.Module):#224x224x3
    #实现主module:ResNet34
    def __init__(self, num_classes=1):
        super(ResNet34,self).__init__()
        self.pre = nn.Sequential(
                nn.Conv2d(3,64,7,stride=2,padding=3,bias=False),# (224+2*p-)/2(向下取整)+1,size减半->112
                nn.BatchNorm2d(64),#112x112x64
                nn.ReLU(inplace = True),
                nn.MaxPool2d(3,2,1)#kernel_size=3, stride=2, padding=1
                )#56x56x64
        
        #重复的layer,分别有3,4,6,3个residual block
        self.layer1 = self.make_layer(64,64,3)#56x56x64,layer1层输入输出一样,make_layer里,应该不用对shortcut进行处理,但是为了统一操作。。。
        self.layer2 = self.make_layer(64,128,4,stride=2)#第一个stride=2,剩下3个stride=1;28x28x128
        self.layer3 = self.make_layer(128,256,6,stride=2)#14x14x256
        self.layer4 = self.make_layer(256,512,3,stride=2)#7x7x512
        #分类用的全连接
        self.fc = nn.Linear(512,num_classes)
        
    def make_layer(self,in_ch,out_ch,block_num,stride=1):
        #当维度增加时,对shortcut进行option B的处理
        shortcut = nn.Sequential(#首个ResidualBlock需要进行option B处理
                nn.Conv2d(in_ch,out_ch,1,stride,bias=False),#1x1卷积用于增加维度;stride=2用于减半size;为简化不考虑偏差
                nn.BatchNorm2d(out_ch)
                )
        layers = []
        layers.append(ResidualBlock(in_ch,out_ch,stride,shortcut))
        
        for i in range(1,block_num):
            layers.append(ResidualBlock(out_ch,out_ch))#后面的几个ResidualBlock,shortcut直接相加
        return nn.Sequential(*layers)
        
    def forward(self,x):    #224x224x3
        x = self.pre(x)     #56x56x64
        x = self.layer1(x)  #56x56x64
        x = self.layer2(x)  #28x28x128
        x = self.layer3(x)  #14x14x256
        x = self.layer4(x)  #7x7x512
        x = F.avg_pool2d(x,7)#1x1x512
        x = x.view(x.size(0),-1)#将输出拉伸为一行:1x512
        x = self.fc(x)    #1x1
        # nn.BCELoss:二分类用的交叉熵,用的时候需要在该层前面加上 Sigmoid 函数
        return nn.Sigmoid()(x)#1x1,将结果化为(0~1)之间

 

Reference:

ResNet原文

ResNet网络结构

ResNet论文翻译——中文版

Pytorch学习(三)–用50行代码搭建ResNet

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185627.html原文链接:https://javaforall.net

(0)
上一篇 2022年10月5日 下午4:46
下一篇 2022年10月5日 下午4:46


相关推荐

  • Android面试题(四大组件篇)[通俗易懂]

    Android面试题(四大组件篇)[通俗易懂]Android面试题(四大组件篇)window、进程、线程篇Android面试题(数据存储、view篇)ActivityQ:说下Activity的生命周期?Q:onStart()和onResume()/onPause()和onStop()的区别?是否位于前台,对用户是否可见的区别Q:ActivityA启动另一个ActivityB会回调哪些方法?如果A…

    2022年5月21日
    44
  • FISCO BCOS JAVA SDK(以HelloWorld合约为例)

    FISCO BCOS JAVA SDK(以HelloWorld合约为例)FISCOBCOSJAV 环境搭建 文章目录 FISCOBCOSJAV 环境搭建 前言一 环境准备 1 开发工具 2 开发环境二 开发步骤 1 创建一个 Gradle 应用 2 引入 JavaSDK3 配置 SDK 证书 5 创建配置文件 6 使用 JavaSDK 部署和调用智能合约 7 运用测试总结前言参考官方文档提示 以下是本篇文章正文内容 下面案例可供参考一 环境准备 1 开发工具 Java JDK14 JDK1 8 至 JDK14 都支持 IDE IntelliJID

    2026年3月26日
    2
  • 网页制作实验步骤_web简易开发

    网页制作实验步骤_web简易开发web实验2制作简单网页(HTML+CSS)一、实验目的1.掌握文本样式的设置。2.掌握图像样式的设置。3.掌握各种媒体的插入方法。二、实验内容采用DIV+CSS,制作“在线电影”页面。三、操作提示1.新建网站的文件夹,网站图像素材保存在images文件夹中,媒体文件放在flash文件中。2.新建index.html页面,要求: 页面字体大小为14px,文本颜色为#000; 页面背景颜色为#edb8d2; 上下左右距均为0。3.利用div布局,宽度为900px,居中对齐。

    2022年10月13日
    6
  • 各种系统架构图与详细说明

    各种系统架构图与详细说明共享平台逻辑架构设计 如上图所示为本次共享资源平台逻辑架构图,上图整体展现说明包括以下几个方面:1应用系统建设本次项目的一项重点就是实现原有应用系统的全面升级以及新的应用系统的开发,从而建立行业的全面的应用系统架构群。整体应用系统通过SOA面向服务管理架构模式实现应用组件的有效整合,完成应用系统的统一化管理与维护。2应用资源采集整体应用系统资源统一分为两类,具体包…

    2022年6月6日
    171
  • partprobe报错问题解决

    partprobe报错问题解决在 VMware 下 在 dev sdb 的空余空间用 fdisk 划分新的分区 完毕后 使用 partprobe 重读分区表时报错 root localhost partprobeWar WARNING thekernelfai readtheparti dev sdb Deviceorreso

    2026年3月26日
    1
  • 清理谷歌浏览器注册表_将谷歌浏览器的注册表彻底删除的方法

    清理谷歌浏览器注册表_将谷歌浏览器的注册表彻底删除的方法解决谷歌浏览器无法重装问题。WindowsRegistryEditorVersion5.00;WARNING,thisfilewillremoveGoogleChromeregistryentries;fromyourWindowsRegistry.Considerbackingupyourregistrybefore;usingthisfile:…

    2025年6月14日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号