Resnet网络:
非常深度的网络在增加更多层时会表现得更差,Resnet在很大程度上避免了网络深度加深时出现的梯度消失,提高很深网络的准确度
ResNet 的认为:直接映射是难以学习的,他们提出了一种修正方法:不再学习从 x 到 H(x) 的基本映射关系,而是学习这两者之间的差异,也就是残差(residual)。然后,为了计算 H(x),只需要将这个残差加到输入上即可。
假设残差为 F(x)=H(x)-x,网络不会直接学习 H(x) 了,而是学习 F(x)+x。
简单的加法运算不会增加额外的参数和计算量。在极端情况下若F(x)=0,则会引起梯度消失,而如果加入了残差,即使F(x)无限趋近于零,此时加上了x,进行恒等映射,此时梯度没有消失,仍然能够进行反向传播,使网络学习到有用的东西。
ResNet 的每一个模块(block)都由一系列层和一个shortcut连接组成,该模块的输入和输出连接到了一起。然后在元素层面上执行加法运算,如果输入和输出的大小不同,那就可以使用零填充或投射(通过 1×1 卷积)来得到匹配的大小。
resnet34实现代码:
from torch import nn
class ResidualBlock(nn.Module):
def __init__(self, inchannel, outchannel, stride, shortcut=None):
super(ResidualBlock, self).__init__()
self.basic = nn.Sequential(
nn.Conv2d(inchannel, outchannel, 3, stride, 1, bias=False),
nn.BatchNorm2d(outchannel),
nn.ReLU(),
nn.Conv2d(outchannel, outchannel, 3, 1, 1, bias=False),
nn.BatchNorm2d(outchannel),
)
self.shortcut = shortcut
def forward(self, x):
out = self.basic(x)
residual = x if self.shortcut is None else self.shortcut(x) # 计算残差
out += residual
return nn.ReLU(out)
class ResNet(nn.Module):
def __init__(self):
super(ResNet, self).__init__()
self.pre = nn.Sequential(
nn.Conv2d(3, 64, 7, 2, 3, bias=False),
nn.BatchNorm2d(64),