ResNet网络

ResNet网络

一.手写ResNet网络

(1)对于残差块有两种:

1.有1*1卷积层

Y=Y+conv_1x1(X)

2.无1*1卷积层

Y=Y+X

image

(2)整体ResNet架构

image

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+X
        return 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)

二.训练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
        #卷积层
        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+X
        return 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)
)
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)
)
train_iter,test_iter=d2l.load_data_fashion_mnist(256,resize=96)
d2l.train_ch6(net,train_iter,test_iter,10,1,d2l.try_gpu())

 

posted @ 2025-10-18 15:56  Annaprincess  阅读(6)  评论(0)    收藏  举报