J6 - ResNeXt50模型的实现



环境

  • 系统: Linux
  • 语言: Python3.8.10
  • 深度学习框架: Pytorch2.0.0+cu118
  • 显卡:GTX2080TI

代码在之前的章节都有,我后续只贴出模型设计

Block对比
对比ResNet的Block和ResNeXt的Block可以发现,最重要的改动就是卷积变成了分组卷积

构建过程如下

  1. 创建Block
class Block(nn.Module):
    def __init__(self, input_size, hidden_size, strides=1, groups=32, conv_shortcut=True):
        super().__init__()
        
        if conv_shortcut:
            self.start = nn.Sequential(
                nn.Conv2d(input_size, hidden_size * 2, 1, stride=strides, bias=False),
                nn.BatchNorm2d(hidden_size*2, eps=1.001e-5)
            )
        else:
            self.start = nn.Identity()
        
        self.conv1 = nn.Conv2d(input_size, hidden_size, 1, padding='same', bias=False)
        self.bn1 = nn.BatchNorm2d(hidden_size, eps=1.001e-5)
        self.relu1 = nn.ReLU()
        
        self.conv2 = nn.Conv2d(hidden_size, hidden_size, 3, padding='same', groups=groups, bias=False)
        self.bn2 = nn.BatchNorm2d(hidden_size, eps=1.001e-5)
        self.relu2 = nn.ReLU()
        
        self.conv3 = nn.Conv2d(hidden_size, hidden_size * 2, 1, stride=strides, bias=False)
        self.bn3 = nn.BatchNorm2d(hidden_size*2, eps=1.001e-5)
        self.relu3 = nn.ReLU()
    def forward(self, inputs):
        short = self.start(inputs)
        
        x = self.conv1(inputs)
        x = self.bn1(x)
        x = self.relu1(x)
        
        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu2(x)
        
        x = self.conv3(x)
        x = self.bn3(x)
        x = self.relu3(x)
        
        x = x + short
        return x
  1. 创建Stack
class Stack(nn.Module):
    def __init__(self, input_size, hidden_size, blocks, strides, groups=32):
        super().__init__()
        
        self.layers = nn.Sequential()
        self.layers.add_module('first', Block(input_size, hidden_size, strides=strides, groups=groups))
        current_size = input_size
        for i in range(blocks):
            self.layers.add_module('layer%d' % (i+1), Block(hidden_size*2, hidden_size, groups=groups, conv_shortcut=False))
        
    def forward(self, inputs):
        x = self.layers(inputs)
        return x
  1. 创建模型
class ResNeXt50(nn.Module):
    def __init__(self, num_classes):
        super().__init__()
        
        self.pre = nn.Sequential(
            nn.ZeroPad2d(3),
            nn.Conv2d(3, 64, 7, stride=2),
            nn.BatchNorm2d(64, eps=1.001e-5),
            nn.ReLU(),
            nn.ZeroPad2d(1),
            nn.MaxPool2d(3, stride=2),
        )
        
        self.stack1 = Stack(64, 128, blocks=2, strides=1)
        self.stack2 = Stack(256, 256, blocks=3, strides=2)
        self.stack3 = Stack(512, 512, blocks=5, strides=2)
        self.stack4 = Stack(1024, 1024, blocks=2, strides=2)
        
        self.avg = nn.AdaptiveAvgPool2d(5)
        self.classifier = nn.Linear(5*5*2048, num_classes)
        self.softmax = nn.Softmax(dim=1)
        
    def forward(self, inputs):
        x = self.pre(inputs)
        x = self.stack1(x)
        x = self.stack2(x)
        x = self.stack3(x)
        x = self.stack4(x)
        x = self.avg(x)
        x = x.view(x.size(0), -1)
        x = self.classifier(x)
        x = self.softmax(x)
        return x

打印模型结构

model = ResNeXt50(2).to(device)
model
ResNeXt50(
  (pre): Sequential(
    (0): ZeroPad2d((3, 3, 3, 3))
    (1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2))
    (2): BatchNorm2d(64, eps=1.001e-05, momentum=0.1, affine=True, track_running_stats=True)
    (3): ReLU()
    (4): ZeroPad2d((1, 1, 1, 1))
    (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (stack1): Stack(
    (layers): Sequential(
      (first): Block(
        (start): Sequential(
          (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(256, eps=1.001e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (conv1): Conv2d(64, 128, kernel_size=(1, 1), stride=(1, 1), padding=same, bias=False)
        (bn1): BatchNorm2d(128, eps=1.001e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu1): ReLU()
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=same, groups=32, bias=False)
        (bn2): BatchNorm2d(128, eps=1.001e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu2): ReLU()
        (conv3): Conv2d(128, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(256, eps=1.001e-05, momentum
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值