ShuffleNetV2 作为backbone代码实现 【torchsummary 使用】

 

图Fig.3 (c)、(d)对应的代码block:

class ShuffleV2Block(nn.Module):
    def __init__(self, inp, oup, mid_channels, *, ksize, stride):
        super(ShuffleV2Block, self).__init__()
        self.stride = stride
        assert stride in [1, 2]

        self.mid_channels = mid_channels
        self.ksize = ksize
        pad = ksize // 2
        self.pad = pad
        self.inp = inp

        outputs = oup - inp

        branch_main = [
            # pw
            nn.Conv2d(inp, mid_channels, 1, 1, 0, bias=False),
            nn.BatchNorm2d(mid_channels),
            nn.ReLU(inplace=True),
            # dw 卷积一次应用在单个通道上 深度卷积
            nn.Conv2d(mid_channels, mid_channels, ksize, stride, pad, groups=mid_channels, bias=False),
            nn.BatchNorm2d(mid_channels),
            # pw-linear  逐点卷积
            nn.Conv2d(mid_channels, outputs, 1, 1, 0, bias=False),
            nn.BatchNorm2d(outputs),
            nn.ReLU(inplace=True),
        ]
        self.branch_main = nn.Sequential(*branch_main)

        if stride == 2:
            branch_proj = [
                # dw
                nn.Conv2d(inp, inp, ksize, stride, pad, groups=inp, bias=False),
                nn.BatchNorm2d(inp),
                # pw-linear
                nn.Conv2d(inp, inp, 1, 1, 0, bias=False),
                nn.BatchNorm2d(inp),
                nn.ReLU(inplace=True),
            ]
            self.branch_proj = nn.Sequential(*branch_proj)
        else:
            self.branch_proj = None

    def forward(self, old_x):
        if self.stride==1:
            x_proj, x = self.channel_shuffle(old_x)
            return torch.cat((x_proj, self.branch_main(x)), 1)
        elif self.stride==2:
            x_proj = old_x
            x = old_x
            return torch.cat((self.branch_proj(x_proj), self.branch_main(x)), 1)
    
    # Fig.3 (c)
    def channel_shuffle(self, x):
        # N C H W
        batchsize, num_channels, height, width = x.data.size()
        assert (num_channels % 4 == 0)
        x = x.reshape(batchsize * num_channels // 2, 2, height * width)
        x = x.permute(1, 0, 2)
        x = x.reshape(2, -1, num_channels // 2, height, width)
        return x[0], x[1]

补充:深度分离卷积 【来源:MobileNet v1中 深度可分离卷积(Depthwise Separable Convolution) 是怎么回事_flyfish-CSDN博客_深度可分离卷积深度可分离卷积是如何减少计算量的flyfish深度可分卷积,深度可分离卷积,depthwise separable convolution相同的意思,不同的名字输入是 7 * 7 * 3输出是 5 * 5 * 128标准卷积步骤一步就完成因为 7 * 7 * 3 -》3 * 3 * 3 = 5 * 5 * 1所以 7 * 7 * 3 -》3 * 3 * 3(128个) = 5 * ...https://flyfish.blog.csdn.net/article/details/94006907

 

 ShuffleNet V2 具体网络结构示意图。不同的通道倍数关系,每个stage 由上图Fig.3(c)、(d)所示的block组成,block的具体数量对应于Repeat列。

 ​​​​​

torchsummary 用来计算网络的参数信息。

使用流程:

安装:pip install torchsummary

使用方法:调用summary,传入模型及输入数据的shape。

 import torch, torchvision
 model = torchvision.models.vgg
 model = torchvision.models.vgg16()
 from torchsummary import summary
 summary(model, (3, 224, 224))

 

 

 具体使用可以参照下面完整code。

backbone完整代码: 

import torch
import torch.nn as nn
from torchsummary import summary

class ShuffleV2Block(nn.Module):
    def __init__(self, inp, oup, mid_channels, *, ksize, stride):
        super(ShuffleV2Block, self).__init__()
        self.stride = stride
        assert stride in [1, 2]

        self.mid_channels = mid_channels
        self.ksize = ksize
        pad = ksize // 2
        self.pad = pad
        self.inp = inp

        outputs = oup - inp

        branch_main = [
            # pw
            nn.Conv2d(inp, mid_channels, 1, 1, 0, bias=False),
            nn.BatchNorm2d(mid_channels),
            nn.ReLU(inplace=True),
            # dw 卷积一次应用在单个通道上 深度卷积
            nn.Conv2d(mid_channels, mid_channels, ksize, stride, pad, groups=mid_channels, bias=False),
            nn.BatchNorm2d(mid_channels),
            # pw-linear  逐点卷积
            nn.Conv2d(mid_channels, outputs, 1, 1, 0, bias=False),
            nn.BatchNorm2d(outputs),
            nn.ReLU(inplace=True),
        ]
        self.branch_main = nn.Sequential(*branch_main)

        if stride == 2:
            branch_proj = [
                # dw
                nn.Conv2d(inp, inp, ksize, stride, pad, groups=inp, bias=False),
                nn.BatchNorm2d(inp),
                # pw-linear
                nn.Conv2d(inp, inp, 1, 1, 0, bias=False),
                nn.BatchNorm2d(inp),
                nn.ReLU(inplace=True),
            ]
            self.branch_proj = nn.Sequential(*branch_proj)
        else:
            self.branch_proj = None

    def forward(self, old_x):
        if self.stride==1:
            x_proj, x = self.channel_shuffle(old_x)
            return torch.cat((x_proj, self.branch_main(x)), 1)
        elif self.stride==2:
            x_proj = old_x
            x = old_x
            return torch.cat((self.branch_proj(x_proj), self.branch_main(x)), 1)

    def channel_shuffle(self, x):
        # N C H W
        batchsize, num_channels, height, width = x.data.size()
        assert (num_channels % 4 == 0)
        x = x.reshape(batchsize * num_channels // 2, 2, height * width)
        x = x.permute(1, 0, 2)
        x = x.reshape(2, -1, num_channels // 2, height, width)
        return x[0], x[1]

class ShuffleNetV2(nn.Module):
    # load_param 是否加载参数
    def __init__(self, stage_out_channels, load_param):
        super(ShuffleNetV2, self).__init__()

        self.stage_repeats = [4, 8, 4]  # [(1,3), (1,7), (1,3)] #Repeat 第一个步长为2 ,第二个步长为1 (可以看对应的总结图)
        # stage_out_channels = [-1, 24, 48, 96, 192]  各个阶段的输出通道数
        self.stage_out_channels = stage_out_channels

        # building first layer
        input_channel = self.stage_out_channels[1] # 24
        # 3 -> 24   Kernel-size=3x3 stride=2 repeat=1
        self.first_conv = nn.Sequential(
            nn.Conv2d(3, input_channel, 3, 2, 1, bias=False),
            nn.BatchNorm2d(input_channel),
            nn.ReLU(inplace=True),
        )
        # 24 -> 24 Ksize=3x3 stride=2 repeat=1 
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)

        stage_names = ["stage2", "stage3", "stage4"]
        for idxstage in range(len(self.stage_repeats)):
            numrepeat = self.stage_repeats[idxstage]
            output_channel = self.stage_out_channels[idxstage+2]
            stageSeq = []
            for i in range(numrepeat):
                # 步长为2
                if i == 0:
                    stageSeq.append(ShuffleV2Block(input_channel, output_channel, 
                                                mid_channels=output_channel // 2, ksize=3, stride=2))
                # 步长为1
                else:
                    stageSeq.append(ShuffleV2Block(input_channel // 2, output_channel, 
                                                mid_channels=output_channel // 2, ksize=3, stride=1))
                input_channel = output_channel
            setattr(self, stage_names[idxstage], nn.Sequential(*stageSeq))
        
        if load_param == False:
            self._initialize_weights()
        else:
            print("load param...")

    def forward(self, x):
        x = self.first_conv(x)
        x = self.maxpool(x)
        C1 = self.stage2(x)
        C2 = self.stage3(C1)
        C3 = self.stage4(C2)

        return C2, C3

    def _initialize_weights(self):
        print("initialize_weights...")
        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        self.load_state_dict(torch.load("./model/backbone/backbone.pth", map_location=device), strict = True)

if __name__ == "__main__":
    stage_out_channels=[-1, 24, 48, 96, 192]
    model = ShuffleNetV2(stage_out_channels,load_param=False)
    print(model)
    print(summary(model,(3,320,320)))  # torchsummary 查看模型的参数量
    test_data = torch.rand(1, 3, 320, 320)
    test_outputs = model(test_data)
    for out in test_outputs:
        print(out.size())

运行结果: 

ShuffleNetV2(
  (first_conv): Sequential(
    (0): Conv2d(3, 24, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
    (1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (2): ReLU(inplace=True)
  )
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (stage2): Sequential(
    (0): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(24, 24, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=24, bias=False)
        (4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
      (branch_proj): Sequential(
        (0): Conv2d(24, 24, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=24, bias=False)
        (1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (4): ReLU(inplace=True)
      )
    )
    (1): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(24, 24, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=24, bias=False)
        (4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (2): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(24, 24, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=24, bias=False)
        (4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (3): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(24, 24, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=24, bias=False)
        (4): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(24, 24, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(24, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
  )
  (stage3): Sequential(
    (0): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(48, 48, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=48, bias=False)
        (4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
      (branch_proj): Sequential(
        (0): Conv2d(48, 48, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=48, bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (4): ReLU(inplace=True)
      )
    )
    (1): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(48, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=48, bias=False)
        (4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (2): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(48, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=48, bias=False)
        (4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (3): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(48, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=48, bias=False)
        (4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (4): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(48, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=48, bias=False)
        (4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (5): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(48, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=48, bias=False)
        (4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (6): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(48, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=48, bias=False)
        (4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (7): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(48, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=48, bias=False)
        (4): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
  )
  (stage4): Sequential(
    (0): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(96, 96, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=96, bias=False)
        (4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
      (branch_proj): Sequential(
        (0): Conv2d(96, 96, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), groups=96, bias=False)
        (1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (3): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (4): ReLU(inplace=True)
      )
    )
    (1): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96, bias=False)
        (4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (2): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96, bias=False)
        (4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
    (3): ShuffleV2Block(
      (branch_main): Sequential(
        (0): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace=True)
        (3): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=96, bias=False)
        (4): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): Conv2d(96, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (6): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (7): ReLU(inplace=True)
      )
    )
  )
)
E:\Anaconda3\envs\YOLOX\lib\site-packages\torch\nn\functional.py:718: UserWarning: Named tensors and all their associated APIs are an experimental feature and subject to change. Please do not use them for anything important until they are released as stable. (Triggered internally at  ..\c10/core/TensorImpl.h:1156.)
  return torch.max_pool2d(input, kernel_size, stride, padding, dilation, ceil_mode)
----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1         [-1, 24, 160, 160]             648
       BatchNorm2d-2         [-1, 24, 160, 160]              48
              ReLU-3         [-1, 24, 160, 160]               0
         MaxPool2d-4           [-1, 24, 80, 80]               0
            Conv2d-5           [-1, 24, 40, 40]             216
       BatchNorm2d-6           [-1, 24, 40, 40]              48
            Conv2d-7           [-1, 24, 40, 40]             576
       BatchNorm2d-8           [-1, 24, 40, 40]              48
              ReLU-9           [-1, 24, 40, 40]               0
           Conv2d-10           [-1, 24, 80, 80]             576
      BatchNorm2d-11           [-1, 24, 80, 80]              48
             ReLU-12           [-1, 24, 80, 80]               0
           Conv2d-13           [-1, 24, 40, 40]             216
      BatchNorm2d-14           [-1, 24, 40, 40]              48
           Conv2d-15           [-1, 24, 40, 40]             576
      BatchNorm2d-16           [-1, 24, 40, 40]              48
             ReLU-17           [-1, 24, 40, 40]               0
   ShuffleV2Block-18           [-1, 48, 40, 40]               0
           Conv2d-19           [-1, 24, 40, 40]             576
      BatchNorm2d-20           [-1, 24, 40, 40]              48
             ReLU-21           [-1, 24, 40, 40]               0
           Conv2d-22           [-1, 24, 40, 40]             216
      BatchNorm2d-23           [-1, 24, 40, 40]              48
           Conv2d-24           [-1, 24, 40, 40]             576
      BatchNorm2d-25           [-1, 24, 40, 40]              48
             ReLU-26           [-1, 24, 40, 40]               0
   ShuffleV2Block-27           [-1, 48, 40, 40]               0
           Conv2d-28           [-1, 24, 40, 40]             576
      BatchNorm2d-29           [-1, 24, 40, 40]              48
             ReLU-30           [-1, 24, 40, 40]               0
           Conv2d-31           [-1, 24, 40, 40]             216
      BatchNorm2d-32           [-1, 24, 40, 40]              48
           Conv2d-33           [-1, 24, 40, 40]             576
      BatchNorm2d-34           [-1, 24, 40, 40]              48
             ReLU-35           [-1, 24, 40, 40]               0
   ShuffleV2Block-36           [-1, 48, 40, 40]               0
           Conv2d-37           [-1, 24, 40, 40]             576
      BatchNorm2d-38           [-1, 24, 40, 40]              48
             ReLU-39           [-1, 24, 40, 40]               0
           Conv2d-40           [-1, 24, 40, 40]             216
      BatchNorm2d-41           [-1, 24, 40, 40]              48
           Conv2d-42           [-1, 24, 40, 40]             576
      BatchNorm2d-43           [-1, 24, 40, 40]              48
             ReLU-44           [-1, 24, 40, 40]               0
   ShuffleV2Block-45           [-1, 48, 40, 40]               0
           Conv2d-46           [-1, 48, 20, 20]             432
      BatchNorm2d-47           [-1, 48, 20, 20]              96
           Conv2d-48           [-1, 48, 20, 20]           2,304
      BatchNorm2d-49           [-1, 48, 20, 20]              96
             ReLU-50           [-1, 48, 20, 20]               0
           Conv2d-51           [-1, 48, 40, 40]           2,304
      BatchNorm2d-52           [-1, 48, 40, 40]              96
             ReLU-53           [-1, 48, 40, 40]               0
           Conv2d-54           [-1, 48, 20, 20]             432
      BatchNorm2d-55           [-1, 48, 20, 20]              96
           Conv2d-56           [-1, 48, 20, 20]           2,304
      BatchNorm2d-57           [-1, 48, 20, 20]              96
             ReLU-58           [-1, 48, 20, 20]               0
   ShuffleV2Block-59           [-1, 96, 20, 20]               0
           Conv2d-60           [-1, 48, 20, 20]           2,304
      BatchNorm2d-61           [-1, 48, 20, 20]              96
             ReLU-62           [-1, 48, 20, 20]               0
           Conv2d-63           [-1, 48, 20, 20]             432
      BatchNorm2d-64           [-1, 48, 20, 20]              96
           Conv2d-65           [-1, 48, 20, 20]           2,304
      BatchNorm2d-66           [-1, 48, 20, 20]              96
             ReLU-67           [-1, 48, 20, 20]               0
   ShuffleV2Block-68           [-1, 96, 20, 20]               0
           Conv2d-69           [-1, 48, 20, 20]           2,304
      BatchNorm2d-70           [-1, 48, 20, 20]              96
             ReLU-71           [-1, 48, 20, 20]               0
           Conv2d-72           [-1, 48, 20, 20]             432
      BatchNorm2d-73           [-1, 48, 20, 20]              96
           Conv2d-74           [-1, 48, 20, 20]           2,304
      BatchNorm2d-75           [-1, 48, 20, 20]              96
             ReLU-76           [-1, 48, 20, 20]               0
   ShuffleV2Block-77           [-1, 96, 20, 20]               0
           Conv2d-78           [-1, 48, 20, 20]           2,304
      BatchNorm2d-79           [-1, 48, 20, 20]              96
             ReLU-80           [-1, 48, 20, 20]               0
           Conv2d-81           [-1, 48, 20, 20]             432
      BatchNorm2d-82           [-1, 48, 20, 20]              96
           Conv2d-83           [-1, 48, 20, 20]           2,304
      BatchNorm2d-84           [-1, 48, 20, 20]              96
             ReLU-85           [-1, 48, 20, 20]               0
   ShuffleV2Block-86           [-1, 96, 20, 20]               0
           Conv2d-87           [-1, 48, 20, 20]           2,304
      BatchNorm2d-88           [-1, 48, 20, 20]              96
             ReLU-89           [-1, 48, 20, 20]               0
           Conv2d-90           [-1, 48, 20, 20]             432
      BatchNorm2d-91           [-1, 48, 20, 20]              96
           Conv2d-92           [-1, 48, 20, 20]           2,304
      BatchNorm2d-93           [-1, 48, 20, 20]              96
             ReLU-94           [-1, 48, 20, 20]               0
   ShuffleV2Block-95           [-1, 96, 20, 20]               0
           Conv2d-96           [-1, 48, 20, 20]           2,304
      BatchNorm2d-97           [-1, 48, 20, 20]              96
             ReLU-98           [-1, 48, 20, 20]               0
           Conv2d-99           [-1, 48, 20, 20]             432
     BatchNorm2d-100           [-1, 48, 20, 20]              96
          Conv2d-101           [-1, 48, 20, 20]           2,304
     BatchNorm2d-102           [-1, 48, 20, 20]              96
            ReLU-103           [-1, 48, 20, 20]               0
  ShuffleV2Block-104           [-1, 96, 20, 20]               0
          Conv2d-105           [-1, 48, 20, 20]           2,304
     BatchNorm2d-106           [-1, 48, 20, 20]              96
            ReLU-107           [-1, 48, 20, 20]               0
          Conv2d-108           [-1, 48, 20, 20]             432
     BatchNorm2d-109           [-1, 48, 20, 20]              96
          Conv2d-110           [-1, 48, 20, 20]           2,304
     BatchNorm2d-111           [-1, 48, 20, 20]              96
            ReLU-112           [-1, 48, 20, 20]               0
  ShuffleV2Block-113           [-1, 96, 20, 20]               0
          Conv2d-114           [-1, 48, 20, 20]           2,304
     BatchNorm2d-115           [-1, 48, 20, 20]              96
            ReLU-116           [-1, 48, 20, 20]               0
          Conv2d-117           [-1, 48, 20, 20]             432
     BatchNorm2d-118           [-1, 48, 20, 20]              96
          Conv2d-119           [-1, 48, 20, 20]           2,304
     BatchNorm2d-120           [-1, 48, 20, 20]              96
            ReLU-121           [-1, 48, 20, 20]               0
  ShuffleV2Block-122           [-1, 96, 20, 20]               0
          Conv2d-123           [-1, 96, 10, 10]             864
     BatchNorm2d-124           [-1, 96, 10, 10]             192
          Conv2d-125           [-1, 96, 10, 10]           9,216
     BatchNorm2d-126           [-1, 96, 10, 10]             192
            ReLU-127           [-1, 96, 10, 10]               0
          Conv2d-128           [-1, 96, 20, 20]           9,216
     BatchNorm2d-129           [-1, 96, 20, 20]             192
            ReLU-130           [-1, 96, 20, 20]               0
          Conv2d-131           [-1, 96, 10, 10]             864
     BatchNorm2d-132           [-1, 96, 10, 10]             192
          Conv2d-133           [-1, 96, 10, 10]           9,216
     BatchNorm2d-134           [-1, 96, 10, 10]             192
            ReLU-135           [-1, 96, 10, 10]               0
  ShuffleV2Block-136          [-1, 192, 10, 10]               0
          Conv2d-137           [-1, 96, 10, 10]           9,216
     BatchNorm2d-138           [-1, 96, 10, 10]             192
            ReLU-139           [-1, 96, 10, 10]               0
          Conv2d-140           [-1, 96, 10, 10]             864
     BatchNorm2d-141           [-1, 96, 10, 10]             192
          Conv2d-142           [-1, 96, 10, 10]           9,216
     BatchNorm2d-143           [-1, 96, 10, 10]             192
            ReLU-144           [-1, 96, 10, 10]               0
  ShuffleV2Block-145          [-1, 192, 10, 10]               0
          Conv2d-146           [-1, 96, 10, 10]           9,216
     BatchNorm2d-147           [-1, 96, 10, 10]             192
            ReLU-148           [-1, 96, 10, 10]               0
          Conv2d-149           [-1, 96, 10, 10]             864
     BatchNorm2d-150           [-1, 96, 10, 10]             192
          Conv2d-151           [-1, 96, 10, 10]           9,216
     BatchNorm2d-152           [-1, 96, 10, 10]             192
            ReLU-153           [-1, 96, 10, 10]               0
  ShuffleV2Block-154          [-1, 192, 10, 10]               0
          Conv2d-155           [-1, 96, 10, 10]           9,216
     BatchNorm2d-156           [-1, 96, 10, 10]             192
            ReLU-157           [-1, 96, 10, 10]               0
          Conv2d-158           [-1, 96, 10, 10]             864
     BatchNorm2d-159           [-1, 96, 10, 10]             192
          Conv2d-160           [-1, 96, 10, 10]           9,216
     BatchNorm2d-161           [-1, 96, 10, 10]             192
            ReLU-162           [-1, 96, 10, 10]               0
  ShuffleV2Block-163          [-1, 192, 10, 10]               0
================================================================
Total params: 143,136
Trainable params: 143,136
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 1.17
Forward/backward pass size (MB): 48.78
Params size (MB): 0.55
Estimated Total Size (MB): 50.50
----------------------------------------------------------------
None
torch.Size([1, 96, 20, 20])
torch.Size([1, 192, 10, 10])

代码参考:https://github.com/dog-qiuqiu/Yolo-FastestV2https://github.com/dog-qiuqiu/Yolo-FastestV2

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是将ShuffleNetV2替换为CSPDarknet53的代码示例: 首先,我们需要导入必要的库和模块: ```python import torch import torch.nn as nn import torch.nn.functional as F ``` 然后,我们定义ShuffleNetV2模块: ```python class ShuffleNetV2Block(nn.Module): def __init__(self, input_channels, output_channels, mid_channels=None, ksize=3, stride=1, use_bn=True): super(ShuffleNetV2Block, self).__init__() if mid_channels is None: mid_channels = output_channels // 2 self.stride = stride self.use_bn = use_bn if stride == 1: self.branch1 = nn.Sequential() else: self.branch1 = nn.Sequential( nn.AvgPool2d(kernel_size=3, stride=stride, padding=1), nn.Conv2d(input_channels, input_channels, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(input_channels), nn.ReLU(inplace=True), ) self.branch2 = nn.Sequential( nn.Conv2d(input_channels if stride > 1 else mid_channels, mid_channels, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(mid_channels), nn.ReLU(inplace=True), nn.Conv2d(mid_channels, mid_channels, kernel_size=ksize, stride=stride, padding=ksize // 2, groups=mid_channels, bias=False), nn.BatchNorm2d(mid_channels), nn.Conv2d(mid_channels, output_channels, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(output_channels), ) def forward(self, x): x1 = self.branch1(x) x2 = self.branch2(x if self.stride > 1 else F.relu(x1)) out = torch.cat((x1, x2), dim=1) out = F.shuffle(out, 2) if self.stride == 2 else out return out ``` 接下来,我们定义CSPDarknet53模块: ```python class CSPDarknet53(nn.Module): def __init__(self): super(CSPDarknet53, self).__init__() self.stem = nn.Sequential( nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False), nn.BatchNorm2d(32), nn.ReLU(inplace=True), ) self.layer1 = nn.Sequential( nn.Conv2d(32, 64, kernel_size=3, stride=2, padding=1, bias=False), nn.BatchNorm2d(64), nn.ReLU(inplace=True), ShuffleNetV2Block(64, 64, ksize=3, stride=1), nn.Conv2d(128, 64, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(64), nn.ReLU(inplace=True), ShuffleNetV2Block(64, 64, ksize=3, stride=1), nn.Conv2d(128, 64, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(64), nn.ReLU(inplace=True), ShuffleNetV2Block(64, 64, ksize=3, stride=1), ) self.layer2 = nn.Sequential( nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1, bias=False), nn.BatchNorm2d(128), nn.ReLU(inplace=True), ShuffleNetV2Block(128, 128, ksize=3, stride=1), nn.Conv2d(256, 128, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(128), nn.ReLU(inplace=True), ShuffleNetV2Block(128, 128, ksize=3, stride=1), nn.Conv2d(256, 128, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(128), nn.ReLU(inplace=True), ShuffleNetV2Block(128, 128, ksize=3, stride=1), nn.Conv2d(256, 128, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(128), nn.ReLU(inplace=True), ShuffleNetV2Block(128, 128, ksize=3, stride=1), nn.Conv2d(256, 128, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(128), nn.ReLU(inplace=True), ShuffleNetV2Block(128, 128, ksize=3, stride=1), ) self.layer3 = nn.Sequential( nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1, bias=False), nn.BatchNorm2d(256), nn.ReLU(inplace=True), ShuffleNetV2Block(256, 256, ksize=3, stride=1), nn.Conv2d(512, 256, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(256), nn.ReLU(inplace=True), ShuffleNetV2Block(256, 256, ksize=3, stride=1), nn.Conv2d(512, 256, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(256), nn.ReLU(inplace=True), ShuffleNetV2Block(256, 256, ksize=3, stride=1), nn.Conv2d(512, 256, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(256), nn.ReLU(inplace=True), ShuffleNetV2Block(256, 256, ksize=3, stride=1), nn.Conv2d(512, 256, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(256), nn.ReLU(inplace=True), ShuffleNetV2Block(256, 256, ksize=3, stride=1), nn.Conv2d(512, 256, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(256), nn.ReLU(inplace=True), ShuffleNetV2Block(256, 256, ksize=3, stride=1), ) self.layer4 = nn.Sequential( nn.Conv2d(256, 512, kernel_size=3, stride=2, padding=1, bias=False), nn.BatchNorm2d(512), nn.ReLU(inplace=True), ShuffleNetV2Block(512, 512, ksize=3, stride=1), nn.Conv2d(1024, 512, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(512), nn.ReLU(inplace=True), ShuffleNetV2Block(512, 512, ksize=3, stride=1), nn.Conv2d(1024, 512, kernel_size=1, stride=1, padding=0, bias=False), nn.BatchNorm2d(512), nn.ReLU(inplace=True), ShuffleNetV2Block(512, 512, ksize=3, stride=1), ) def forward(self, x): x = self.stem(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) return x ``` 最后,我们可以使用CSPDarknet53替换任何需要使用Darknet53的模型。 例如,下面是一个RetinaNet模型,其中使用CSPDarknet53代替了标准的Darknet53: ```python class RetinaNet(nn.Module): def __init__(self, num_classes): super(RetinaNet, self).__init__() self.backbone = CSPDarknet53() self.fpn = FPN([512, 1024, 2048], 256) self.head = RetinaNetHead(num_classes) def forward(self, x): x = self.backbone(x) features = self.fpn(x) out = self.head(features) return out ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐亦亦乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值