图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]
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