Table of contents
1. Prepare RepVgg
1. Refer to YOLOv7
In the yolov7 git repository, the detailed RepConv and the related CSPRepBettleneck module are provided in common.py
RepConv and RepBottleNeck codes are as follows (example):
class C3RepVGG(nn.Module):
# CSP RepBottleneck with 3 convolutions, modified by wqt
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5, act=True): # ch_in, ch_out, number, shortcut, groups, expansion
super(C3RepVGG, self).__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1, act=act)
self.cv2 = Conv(c1, c_, 1, 1, act=act)
self.cv3 = Conv(2 * c_, c2, 1, act=act) # act=FReLU(c2)
# self.m = nn.Sequential(*[RepBottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)]) #original RepBottleneck format
self.m = nn.Sequential(*[RepBottleneck(c_, c_, shortcut, g, e=0.5) for _ in range(n)]) # change e=0.5, otherwise, bugs happens.
def forward(self, x):
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))
class RepBottleneck(Bottleneck):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion
super().__init__(c1, c2, shortcut=True, g=1, e=0.5)
c_ = int(c2 * e) # hidden channels
self.cv2 = RepConv(c_, c2, 3, 1, g=g)
class RepBottleneckCSPA(BottleneckCSPA): #相当于Rep后的C3module
# CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__init__(c1, c2, n, shortcut, g, e)
c_ = int(c2 * e) # hidden channels
self.m = nn.Sequential(*[RepBottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])
The RepConv code segment is relatively long and is omitted here.
2. Use RepVgg
1. Building blocks
Add the module to the *.yaml file that defines the module in the config directory
backbone:
# [from, number, module, args]
[
# [ -1, 1, Focus, [ 64, 3 ] ], # 0-P1/2
[ -1, 1, Conv, [ 128, 4, 4, 0 ] ], # 1-P2/4
[ -1, 3, C3RepVGG, [ 128 ] ], #modify C3 with RepConv 次出添加来一层C3RepVGG
[ -1, 1, Conv, [ 256, 3, 2 ] ], # 3-P3/8
[ -1, 9, C3, [ 256 ] ],
[ -1, 1, Conv, [ 512, 3, 2 ] ], # 5-P4/16
[ -1, 9, C3, [ 512 ] ],
[ -1, 1, Conv, [ 768, 3, 2 ] ], # 7-P5/32
[ -1, 3, C3, [ 768 ] ],
[ -1, 1, Conv, [ 1024, 3, 2 ] ], # 9-P6/64
[ -1, 1, SPP, [ 1024, [ 3, 5, 7 ] ] ],
[ -1, 3, C3, [ 1024, False ] ], # 11
]
2. Analytical model
After defining the model, the parameters need to be parsed, so the newly added RepVgg module also needs parameter parsing, find parse_model in yolo.py:
if m in [DeConv, Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, DWConv, MixConv2d, Focus, ConvFocus, CrossConv, BottleneckCSP,
C3, C3RepVGG, RepBottleneckCSPA, C3TR]:
c1, c2 = ch[f], args[0]
if c2 != no: # if not output
c2 = make_divisible(c2 * gw, 8)
args = [c1, c2, *args[1:]]
if m in [BottleneckCSP, C3, C3RepVGG, RepBottleneckCSPA, C3TR]:
args.insert(2, n) # number of repeats
n = 1
if m in [DeConv, Conv, GhostConv, Bottleneck, GhostBottleneck, DWConv, MixConv2d, Focus, ConvFocus, CrossConv, BottleneckCSP,
RepBottleneckCSPA, C3, C3RepVGG, C3TR]:
if 'act' in d.keys():
args_dict = {
"act" : d['act']}
In the inference phase, fuse may be used
def fuse(self): # fuse model Conv2d() + BatchNorm2d() layers
print('Fusing layers... ')
for m in self.model.modules():
if isinstance(m, RepConv):
#print(f" fuse_repvgg_block")
m.fuse_repvgg_block()
elif isinstance(m, RepConv_OREPA):
#print(f" switch_to_deploy")
m.switch_to_deploy()
elif type(m) is Conv and hasattr(m, 'bn'):
m.conv = fuse_conv_and_bn(m.conv, m.bn) # update conv
delattr(m, 'bn') # remove batchnorm
m.forward = m.fuseforward # update forward
self.info()
return self
After adding the above code segment, you can run the train function.
3. Reasoning
Entering the test stage, we compared the parameters and Flops size of the two, and found that RepVgg can effectively reduce the number of parameters and improve performance.
Method | Stage | Params | Flops | [email protected] | [email protected]:0.95 |
---|---|---|---|---|---|
YOLO5FacePose | Train | 13.13 | 17.1 | 96.8 | 90.8 |
YOLO5FacePose +RepVgg | Train | 13.126 | 16.8 | 96.2 | 90.3 |
YOLO5FacePose +RepVgg | Test | 13.13 | 17.1 | 96.7 | 90.9 |
Summarize
According to the above operation, the train operation is normal; but the role of Rep is to reflect the role in the reasoning stage, and it is necessary to give a conclusion after further testing the inference.
reference
There are some other reference methods to achieve, which may be useful but need to be tested and verified
YOLOv5-Lite: Repvgg reparameterization experiment and thinking on YOLO industrial landing
YOLOv5-Lite
YOLOv7-common