深度学习知识沉淀四——ResNet

1.网络简介

​ ResNet网络是在2015年由微软实验室何凯明等人提出的,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名。获得COCO数据集中目标检测第一名,图像分割第一名。各项名誉加身,引领了深度学习发展潮流。

​ 在ResNet网络提出之前,传统的卷积神经网络都是通过将一系列卷积层与下采样层进行堆叠得到的。但是当堆叠到一定网络深度时,就会出现两个问题。1)梯度消失或梯度爆炸。 2)退化问题(degradation problem)。在ResNet论文中说通过数据的预处理以及在网络中使用BN(Batch Normalization)层能够解决梯度消失或者梯度爆炸问题。但是对于退化问题(并没有很好的解决办法。

​ ResNet论文提出了residual结构(残差结构)来减轻退化问题。

​ 亮点:

(1)解决深度网络退化问题

  • 随着神经网络深度的增加,传统的网络结构会出现训练误差增大、性能下降的问题,这被称为深度网络退化。ResNet 的核心思想是引入了残差学习(residual learning)来解决这个问题。
  • 残差学习的基本思想是让网络学习输入和输出之间的残差,而不是直接学习输出。这样可以使网络更容易优化,即使网络非常深,也能有效地训练。

(2)残差块结构

  • ResNet 的基本构建块是残差块(residual block)。一个典型的残差块由两部分组成:
    • 主路径(identity path):也称为直连路径,直接将输入传递到输出。这部分通常包含一些卷积层和批量归一化层(Batch Normalization),用于提取特征。
    • 残差路径(residual path):由几个卷积层和批量归一化层组成,用于学习输入和输出之间的残差。残差路径的输出与主路径的输入相加,得到最终的输出。
  • 这种结构使得网络可以更容易地学习输入和输出之间的微小变化,从而提高了网络的性能和训练效率。

​ 下面是网络的整体结构:

在这里插入图片描述

2.网络搭建

网络包含两种残差结构,较浅层的网络采用两个3x3卷积模块和一个residual分支,此浅层模块定义为BasicBlock。

注意,此结构的conv1和conv2 stride的区别,conv2_x上s=1,但是后面的conv3_x,4_x,5_x上的两个3x3卷积,第一个3x3卷积s=2。

在这里插入图片描述

# 18,34基础残差块
class BasicBlock(nn.Module):
    expansion = 1  # 18,34层第一层卷积核个数是一样的,更深层的卷积核个数不一样,对应expansion=4

    def __init__(self, in_channel, out_channel, stride=1, downsample=None):
        super(BasicBlock, self).__init__()
        # 第一层卷积输入输出维度一样,由于采取了BN,故不需要bias
        self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,
                               kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channel)
        self.relu = nn.ReLU()

        self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,
                               kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_channel)                       
        self.downsample = downsample  # 下采样操作,如果输入输出通道数不同,需要下采样调整

    def forward(self, x):
        identity = x  # 跳层连接
        if self.downsample is 
请解释此段代码class GATrainer(): def __init__(self, input_A, input_B): self.program = fluid.default_main_program().clone() with fluid.program_guard(self.program): self.fake_B = build_generator_resnet_9blocks(input_A, name="g_A")#真A-假B self.fake_A = build_generator_resnet_9blocks(input_B, name="g_B")#真B-假A self.cyc_A = build_generator_resnet_9blocks(self.fake_B, "g_B")#假B-复原A self.cyc_B = build_generator_resnet_9blocks(self.fake_A, "g_A")#假A-复原B self.infer_program = self.program.clone() diff_A = fluid.layers.abs( fluid.layers.elementwise_sub( x=input_A, y=self.cyc_A)) diff_B = fluid.layers.abs( fluid.layers.elementwise_sub( x=input_B, y=self.cyc_B)) self.cyc_loss = ( fluid.layers.reduce_mean(diff_A) + fluid.layers.reduce_mean(diff_B)) * cycle_loss_factor #cycle loss self.fake_rec_B = build_gen_discriminator(self.fake_B, "d_B")#区分假B为真还是假 self.disc_loss_B = fluid.layers.reduce_mean( fluid.layers.square(self.fake_rec_B - 1))###优化生成器A2B,所以判别器结果越接近1越好 self.g_loss_A = fluid.layers.elementwise_add(self.cyc_loss, self.disc_loss_B) vars = [] for var in self.program.list_vars(): if fluid.io.is_parameter(var) and var.name.startswith("g_A"): vars.append(var.name) self.param = vars lr = 0.0002 optimizer = fluid.optimizer.Adam( learning_rate=fluid.layers.piecewise_decay( boundaries=[ 100 * step_per_epoch, 120 * step_per_epoch, 140 * step_per_epoch, 160 * step_per_epoch, 180 * step_per_epoch ], values=[ lr, lr * 0.8, lr * 0.6, lr * 0.4, lr * 0.2, lr * 0.1 ]), beta1=0.5, name="g_A") optimizer.minimize(self.g_loss_A, parameter_list=vars)
06-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值