首页 > 其他分享 >秃姐学AI系列之:残差网络 ResNet

秃姐学AI系列之:残差网络 ResNet

时间:2024-08-28 10:26:35浏览次数:13  
标签:nn AI self ResNet 秃姐学 残差 channels num

目录

残差网络——ResNet

残差块思想

ResNet块细节

ResNet架构

总结

代码实现

残差块

两种 ResNet 块的情况 

ResNet 模型

QA


由上图发现,只有当较复杂的函数类包含较小的函数类时,才能确保提高它们的性能。

对于深度神经网络,如果我们能将新添加的层训练成恒等映射(identity function)f(x)=x,新模型和原模型将同样有效。 同时,由于新模型可能得出更优的解来拟合训练数据集,因此添加层似乎更容易降低训练误差。

针对这一问题,何恺明等人提出了残差网络(ResNet) 。它在2015年的 ImageNet 图像识别挑战赛夺魁,并深刻影响了后来的深度神经网络的设计。

残差网络——ResNet

残差网络的核心思想是:每个附加层都应该更容易地包含原始函数作为其元素之一。

于是,残差块(residual blocks)便诞生了,这个设计对如何建立深层神经网络产生了深远的影响。 凭借它,ResNet赢得了2015年ImageNet大规模视觉识别挑战赛。

残差块思想

残差块加入快速通道来得到f(x) = x + g(x) 的结构

如下图所示,假设我们的原始输入为x,而希望学出的理想映射为 f(x)(作为上方激活函数的输入)。

左图虚线框中的部分需要直接拟合出该映射 f(x),而右图虚线框中的部分则需要拟合出残差映射 f(x)−x。残差映射在现实中往往更容易优化

开头提到的恒等映射作为我们希望学出的理想映射 f(x),我们只需将右图虚线框内上方的加权运算(如仿射)的权重和偏置参数设成 0,那么 f(x) 即为恒等映射。 实际中,当理想映射 f(x) 极接近于恒等映射时,残差映射也易于捕捉恒等映射的细微波动。

右图是 ResNet 的基础架构–残差块(residual block)。 在残差块中,输入可通过跨层数据线路更快地向前传播。

相当于ResNet觉得,你就算虚线框里面所有层都没学到东西,下一层还是可以接收到这层的上一层传递来的东西(残差连接)即一个简单的直接传递的小模型。这个想法从函数的角度来说,可以认为更大、更复杂的模型里面包含一个小模型。

ResNet块细节

ResNet 是从 VGG 过来的,所以采用的是 3x3Conv

以下是 ResNet 块的两个不同的实现

右边存在的意义是:如果虚线的block对通道做了变换,那直接的X加不回去了,所以需要用卷积来对x做一个通道数的变换用于相加 。

ResNet架构

ResNet 最主要的思想就是单拎出来一条路让你可以把输入和输出加起来

抛开这个其他的你可以认为和 VGG 以及GoogLeNet 很像,也是由5个Stage拼成,只是把组合成网络的 Stage 替换成了 ResNet 块

  • 一个高宽减半的 ResNet 块(步幅为2)(那个支线上有Conv的Block,用来把输入的通道数翻一倍)
  • 重复多个高宽不变的 ResNet 块 

总结

  • 残差块使得很深的网络更加容易训练

    • 甚至可以训练以前层的网络

  • 残差网络对随后的深层神经网络设计产生了深远的影响,无论是卷积类网络还是全连接类网络 

  • 学习嵌套函数(nested function)是训练神经网络的理想情况。在深层神经网络中,学习另一层作为恒等映射(identity function)较容易(尽管这是一个极端情况)。

  • 残差映射可以更容易地学习同一函数,例如将权重层中的参数近似为零。

  • 利用残差块(residual blocks)可以训练出一个有效的深层神经网络:输入可以通过层间的残余连接更快地向前传播。

代码实现

残差块

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


class Residual(nn.Module):  #@save
    def __init__(self, input_channels, num_channels,
                 use_1x1conv=False, strides=1):
        super().__init__()
        self.conv1 = nn.Conv2d(input_channels, num_channels,
                               kernel_size=3, padding=1, stride=strides)
        self.conv2 = nn.Conv2d(num_channels, num_channels,
                               kernel_size=3, padding=1)
        if use_1x1conv:
            self.conv3 = nn.Conv2d(input_channels, num_channels,
                                   kernel_size=1, stride=strides)
        else:
            self.conv3 = None
        self.bn1 = nn.BatchNorm2d(num_channels)
        self.bn2 = nn.BatchNorm2d(num_channels)

    def forward(self, X):
        Y = F.relu(self.bn1(self.conv1(X)))
        Y = self.bn2(self.conv2(Y))
        if self.conv3:
            X = self.conv3(X)
        Y += X
        return F.relu(Y)

两种 ResNet 块的情况 

输入和输出形状一致

blk = Residual(3,3)
X = torch.rand(4, 3, 6, 6)
Y = blk(X)
Y.shape

# 输出
torch.Size([4, 3, 6, 6])

增加输出通道数的同时,减半输出的高和宽

blk = Residual(3, 6, use_1x1conv=True, strides= 2)
blk(X).shape

# 输出
torch.Size([4, 6, 3, 3])

ResNet 模型

ResNet 的前两层跟之前介绍的 GoogLeNet 中的一样:

在输出通道数为 64、步幅为 2 的 7×7 卷积层后,

接步幅为 2 的 3×3 的最大汇聚层。

不同之处在于 ResNet 每个卷积层后增加了批量规范化层。

b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
                   nn.BatchNorm2d(64), nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

GoogLeNet 在后面接了 4 个由 Inception 块组成的模块。ResNet 则使用 4 个由残差块组成的模块,

每个模块使用若干个同样输出通道数的残差块。

第一个模块的通道数同输入通道数一致。由于之前已经使用了步幅为 2 的最大汇聚层,所以无须减小高和宽。

之后的每个模块在第一个残差块里将上一个模块的通道数翻倍,并将高和宽减半。

def resnet_block(input_channels, num_channels, num_residuals,
                 first_block=False):
    blk = []
    for i in range(num_residuals):
        if i == 0 and not first_block:
            blk.append(Residual(input_channels, num_channels,
                                use_1x1conv=True, strides=2))
        else:
            blk.append(Residual(num_channels, num_channels))
    return blk

b2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))
b3 = nn.Sequential(*resnet_block(64, 128, 2))
b4 = nn.Sequential(*resnet_block(128, 256, 2))
b5 = nn.Sequential(*resnet_block(256, 512, 2))

net = nn.Sequential(b1, b2, b3, b4, b5,
                    nn.AdaptiveAvgPool2d((1,1)),
                    nn.Flatten(), nn.Linear(512, 10))

老规矩,不同模块的数据形状变化

X = torch.rand(size=(1, 1, 224, 224))
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__,'output shape:\t', X.shape)

QA

  • 残差概念体现在哪里?

可以理解成,因为 f(x) 是由 x 和 g(x) 相加得来的,x 又是由上一层网络训练的来的,可以被视为一个小网络的输出。所以整个 ResNet 就是先训练小网络,然后小网络 fit 不到的(小的差距)再由上面的层去补充。这就是残差(残留的差距)的概念。

  •  为什么 BN 需要定义两个,而 ReLU 不需要?

BN 是两个独立的层,每个层都有自己需要学的不同的参数,而 ReLU 没有什么学习性,所以公用一个层就可以

  • 训练 ACC 是不是在不 overfitting 的情况下,永远大于测试 ACC?

不一定哦,后面会看到当你做了大量的数据噪音的时候,测试精度会高于训练精度,因为你测试的时候不会添加噪声。

  • 为什么 ResNet 可以训练 100 层网络? 

 假设 g(x) 是在 f(x) 之外新加的一个层,那对于梯度的计算公式根据链式求导法展开,多出来的第一项就是新套的那层的输入和输出求导。假设加的这个层的拟合能力比较强,这一项会很快的变得特别小。一个很小的值乘我们之前那一层的梯度,梯度就会变得比之前小很多。梯度变小之后可以选择增大学习率,但是很有可能增大学习率也没啥用。因为也不能增的太大,f 这一层比 g 更靠近数据,如果增加太大那 g 这一层会变得不稳定。这就是为什么之前模型变深之后会出现梯度消失的问题。

主要原因就是层数叠加,梯度是一直做乘法。回传的时候就会出现底部的梯度特别小。

而 ResNet 是怎么解决这个问题的呢?

因为 ResNet 的网络设计使得它的梯度计算是相加的,哪怕有哪一块比较小也没关系,哪怕当g(x)不存在的时候去拟合,也有 f(x) 的梯度存在。

大数 + 小数没问题,但是 大数*小数问题很大! 

标签:nn,AI,self,ResNet,秃姐学,残差,channels,num
From: https://blog.csdn.net/m0_62415132/article/details/141610902

相关文章

  • 秃姐学AI系列之:批量归一化 + 代码实现
    目录批量归一化核心想法批归一化在做什么总结代码实现从零实现创建一个正确的BatchNorm层应用BatchNorm于LeNet模型简单实现QA批量归一化训练深层神经网络是十分困难的,特别是在较短的时间内使他们收敛更加棘手。因为数据在网络最开始,而损失在结尾。训练的过程是......
  • C. Turtle and Good Pairs
    https://codeforces.com/contest/2003/problem/C题意:。。。思路:如果要使满足条件的有序对最多,那么首先如果两个字符相等,那么无论如何排列,最终的贡献值都不会变。再看字符不相等的情况,假如有aabbcc,那么abcabc总是优于aabbcc,因为如果一个字符出现了多次,那么像aab,bcc这种就会没......
  • ai取名生成器在哪?让你的命名过程更轻松
    创建产品或企业时,一个响亮的名字往往能让你一秒记住。但寻找一个完美的名字却是一项艰巨的任务,足以让人头疼不已。不过别担心,今天就要向你介绍一些ai取名生成器在线免费工具。只需一句话,它们就能为你提供一系列充满创意的名称。还在为取名而烦恼的小伙伴,快看过来吧~▌ai取......
  • 1-0.AI工具
    1.知道或使用过的AI大模型平台ChatGPT文心一言豆包。2.AI提升学习效率的例子解答疑惑:学习数学时,如高等数学中的多元函数积分问题,向AI提问,它会给出解题步骤和思路,帮助快速理解,同时比如在上学期学习计算机网络这一门课的时候,会涉及到许多新的名词,这时我会直接向AI......
  • 掀起社交娱乐新浪潮!AI如何应用到短视频APP?
    随着人工智能技术的迅速发展和全球社交媒体用户的增长,AI视频生成应用正逐渐成为短视频社交媒体中的关键工具。AI工具不仅可以提高内容的创造效率,还能为用户带来全新的互动体验。人工智能(AI)已经成为我们日常生活和工作中不可或缺的一部分,随着数据的爆炸性增长和计算能力的提......
  • AI产品经理知识体系:驾驭未来的核心技能
    随着人工智能(AI)的快速发展,AI产品经理的角色变得至关重要。他们不仅需要具备传统产品经理的技能,还必须深入理解AI技术的各个方面,才能推动AI技术在实际产品中的落地和应用。从最基础的技术知识,到跨领域的创新思维,AI产品经理的知识体系需要非常全面。本文将基于AI产品经理知识......
  • .NET与AI的碰撞:开启智能编程新纪元
    设想一下,你是一名.NET开发者,正为一个复杂的数据分析项目绞尽脑汁。突然,你的IDE仿佛有了生命,不仅能理解你的想法,还能自动生成大部分代码,甚至主动指出潜在的优化空间。这听起来像是科幻电影中的场景,但实际上,这种“魔法”正在成为现实!让我们一同探讨.NET世界正在经历的激动人心的变革......
  • SDKD 2024 Summer Training Contest E2补题
    SDKD2024SummerTrainingContestE2A-PaperWatering题意对x进行至多k次操作(平方或开方后向下取整),求可以得到多少不同的数。思路平方完一定不同,且平方完后一定能开方出整数,所以只用额外考虑开方后平方的情况。若开方再平方与原来不同,则答案加上当前变化数的次数,直到变......
  • Datawhale AI夏令营 Task 1 《深度学习详解》 - 1.1 通过案例了解机器学习的学
        一、学习目标通过具体案例深入理解机器学习的概念、工作原理以及在实际应用中的作用。二、主要内容案例介绍:详细阐述了图像识别、语音识别、自然语言处理等领域的具体案例,如人脸识别系统、智能语音助手、文本......
  • 聚星文社AIGC推文软件
    聚星文社AIGC推文软件是一款由聚星文社开发的推文编辑和发布工具。Docshttps://iimenvrieak.feishu.cn/docx/ZhRNdEWT6oGdCwxdhOPcdds7nof这款软件可以帮助用户快速编写和发布推文,提供了丰富的编辑功能和推广工具。用户可以在软件中编辑推文内容,同时也能够添加图片、链接......