resnet和dens

resnet 

 可以想象这样一个场景,随着模型的更新,对真实结果的拟合反而越来越差,就像一个非嵌套函数。但是如果是嵌套类函数,结果只会越来越好,这就是残差网络的核心了。

嵌套就是前一个结果一定在下一个结果之中

核心是乘法变加法,确实更清晰了,本来也差不多是这么想的。 

假设我们的原始输入为x,而希望学出的理想映射为f(x)。

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

(感觉就是一个adaboost,可以说是非常像了,神经网络的串联集成)

(半年后:我当时好像真明白了🧐,确实有点像GBDT,现在怎么忘了。。。把预测值从0.3训练到0要比80.3到80简单,感觉挺共通的)

又忘了,甚至又回去看了一遍视频,把图片复制好了,结果。。。

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

 两种不同的残差块,一个多了一个1x1卷积核来调整通道数和分辨率。

残差神经网络(Residual Neural Network,ResNet)具有以下几个优点:

1. 解决了梯度消失和梯度爆炸问题:在深层神经网络中,梯度在反向传播过程中可能会变得非常小或非常大,导致训练困难。通过引入残差连接,ResNet可以跨越多层传递梯度,避免梯度在深层网络中消失或爆炸。

(反向传播更新的不就是卷积核的那几个参数嘛,而主干后面参数基本都是0,只有x,那么梯度就会一直在1左右徘徊喽,所以不会梯度消失和爆炸)

2. 提供了更深的网络结构:传统的深层神经网络往往随着层数的增加而遇到性能下降的问题,称为退化问题。ResNet通过使用残差块,它允许网络变得更深,因为残差块可以直接输出恒等映射,即不引入额外的复杂性,保持原始信号的流动性。

不会梯度消失和爆炸,而且模型还不会退化,那不多整几层0.0

3. 提高了网络的收敛速度:由于残差连接的存在,ResNet可以更快地收敛。残差模块使训练过程中的信息流动更加顺畅,减少了训练过程中的信息丢失和冗余。

残差连接提供了一个直接的、无衰减(identity)的路径,一般的神经网络到开始那几个的时候基本上就已经没有梯度了,所以更新特别慢,而有了恒等映射(identity mapping),梯度不会消失,那更新肯定快。

4. 减少了参数量:通过使用全局平均池化层,ResNet可以将特征图降维为一个单一的特征向量,将特征图的空间维度降低。这样一来,相比于传统的全连接层,ResNet在模型参数方面更加高效,减少了存储需求和计算复杂度。

5. 提高了模型的泛化能力:残差连接可以传递信息和梯度,使得浅层的特征可以直接与更深层的特征进行交互。这种跨层联系有助于提取具有判别性的特征,提高了模型的泛化能力。

就像yolov2一样,未变化的特征图直接进入下层,可以提高泛化能力

总的来说,残差神经网络通过引入残差连接解决了梯度问题、改善了网络性能、减少了参数量、提高了泛化能力等方面的优点,成为当前深度学习中非常重要和成功的模型架构之一。

densenet

ResNet将f分解为两部分:一个简单的线性项和一个复杂的非线性项。那么再向前拓展一步,如
果我们想将f拓展成超过两部分的信息呢?一种方案便是DenseNet。

  DenseBlock(2, 3, 10)两个块,3个输入通道,10个输出通道
3个变10个,连起来,输出13个
13个变10个,连起来,输出23个
13个通道分别是从前两个原封不动继承来的。

def conv_block(input_channels, num_channels):
    return nn.Sequential(
        nn.BatchNorm2d(input_channels), nn.ReLU(),
        nn.Conv2d(input_channels, num_channels, kernel_size=3, padding=1))

class DenseBlock(nn.Module):
    def __init__(self, num_convs, input_channels, num_channels):
        super(DenseBlock, self).__init__()
        layer = []
        for i in range(num_convs):
            layer.append(conv_block(
                num_channels * i + input_channels, num_channels))
        self.net = nn.Sequential(*layer)

    def forward(self, X):
        for blk in self.net:
            Y = blk(X)
            # 连接通道维度上每个块的输入和输出
            X = torch.cat((X, Y), dim=1)
        return X
blk = DenseBlock(2, 3, 10)
X = torch.randn(4, 3, 8, 8)
Y = blk(X)
Y.shape
torch.Size([4, 23, 8, 8])

每个稠密块都会带来通道数的增加,使用过多则会过于复杂化模型。而过渡层可以用来控制模型复杂度。
它通过1 × 1卷积层来减小通道数,并使用步幅为2的平均汇聚层减半高和宽,从而进一步降低模型复杂度。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值