ResNet网络
一.手写ResNet网络
(1)对于残差块有两种:
1.有1*1卷积层
Y=Y+conv_1x1(X)
2.无1*1卷积层
Y=Y+X
(2)整体ResNet架构
import torch
from d2l import torch as d2l
from torch import nn
from torch.nn import functional as F
#1.单个ResNet块(残差块)
class Residual(nn.Module):#每个残差快包含两个卷积层def __init__(self,in_chanels,out_chanels,use_1x1convd=False,strides=1):super().__init__()if use_1x1convd==True:#用了1*1卷积层self.conv1x1=nn.Conv2d(in_chanels,out_chanels,1,stride=strides)else:self.conv1x1 =None#没用1*1卷积层#卷积层self.convd1=nn.Conv2d(in_chanels,out_chanels,3,padding=1,stride=strides)self.convd2=nn.Conv2d(out_chanels,out_chanels,3,padding=1)#批量归一化层self.bn1=nn.BatchNorm2d(out_chanels)self.bn2=nn.BatchNorm2d(out_chanels)def forward(self,X):#前向函数Y=F.relu(self.bn1(self.convd1(X)))Y=self.bn2(self.convd2(Y))if self.conv1x1 is not None:X=self.conv1x1(X)Y=Y+Xreturn F.relu(Y)
#ResNet网络构造(有5个stage)
b1=nn.Sequential(nn.Conv2d(1,64,7,2,3),nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(3,2,1)
)
#多个残差块连接
def resnet_block(in_chanels,outchanels,num_residuals,first_block=False):#残差块数blk=[]for i in range(num_residuals):if i==0 and first_block==False:#通道数*2,高宽减半blk.append(Residual(in_chanels,outchanels,use_1x1convd=True,strides=2))else:blk.append(Residual(outchanels,outchanels))#通道数不变,高宽不变return blk
b2=nn.Sequential(*resnet_block(64,64,2,first_block=True)#通道数不变,高宽不变
)
#下面几步的第一块都要通道数*2
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)),#表示输出特征图的空间尺寸为 1x1(即高 = 1,宽 = 1)。例如:若输入是 (512, 7, 7)(通道数 = 512,高 = 7,宽 = 7),经过该层后会输出 (512, 1, 1)。若输入是 (512, 14, 14),输出仍为 (512, 1, 1)。nn.Flatten(),nn.Linear(512,10)
)
X=torch.rand((1,1,224,224))
for layer in net:X=layer(X)print(layer.__class__.__name__,X.shape)