glenn-jocher commited on
Commit
4e8c81a
1 Parent(s): e086347

Add `yolov5s-ghost.yaml` (#4412)

Browse files

* Add yolov5s-ghost.yaml

* Finish C3Ghost

* Add C3Ghost to list

* Add C3Ghost to number of repeats if statement

* Fixes

* Cleanup

models/common.py CHANGED
@@ -149,6 +149,14 @@ class C3SPP(C3):
149
  self.m = SPP(c_, c_, k)
150
 
151
 
 
 
 
 
 
 
 
 
152
  class SPP(nn.Module):
153
  # Spatial pyramid pooling layer used in YOLOv3-SPP
154
  def __init__(self, c1, c2, k=(5, 9, 13)):
@@ -177,6 +185,34 @@ class Focus(nn.Module):
177
  # return self.conv(self.contract(x))
178
 
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  class Contract(nn.Module):
181
  # Contract width-height into channels, i.e. x(1,64,80,80) to x(1,256,40,40)
182
  def __init__(self, gain=2):
 
149
  self.m = SPP(c_, c_, k)
150
 
151
 
152
+ class C3Ghost(C3):
153
+ # C3 module with GhostBottleneck()
154
+ def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
155
+ super().__init__(c1, c2, n, shortcut, g, e)
156
+ c_ = int(c2 * e) # hidden channels
157
+ self.m = nn.Sequential(*[GhostBottleneck(c_, c_) for _ in range(n)])
158
+
159
+
160
  class SPP(nn.Module):
161
  # Spatial pyramid pooling layer used in YOLOv3-SPP
162
  def __init__(self, c1, c2, k=(5, 9, 13)):
 
185
  # return self.conv(self.contract(x))
186
 
187
 
188
+ class GhostConv(nn.Module):
189
+ # Ghost Convolution https://github.com/huawei-noah/ghostnet
190
+ def __init__(self, c1, c2, k=1, s=1, g=1, act=True): # ch_in, ch_out, kernel, stride, groups
191
+ super().__init__()
192
+ c_ = c2 // 2 # hidden channels
193
+ self.cv1 = Conv(c1, c_, k, s, None, g, act)
194
+ self.cv2 = Conv(c_, c_, 5, 1, None, c_, act)
195
+
196
+ def forward(self, x):
197
+ y = self.cv1(x)
198
+ return torch.cat([y, self.cv2(y)], 1)
199
+
200
+
201
+ class GhostBottleneck(nn.Module):
202
+ # Ghost Bottleneck https://github.com/huawei-noah/ghostnet
203
+ def __init__(self, c1, c2, k=3, s=1): # ch_in, ch_out, kernel, stride
204
+ super().__init__()
205
+ c_ = c2 // 2
206
+ self.conv = nn.Sequential(GhostConv(c1, c_, 1, 1), # pw
207
+ DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(), # dw
208
+ GhostConv(c_, c2, 1, 1, act=False)) # pw-linear
209
+ self.shortcut = nn.Sequential(DWConv(c1, c1, k, s, act=False),
210
+ Conv(c1, c2, 1, 1, act=False)) if s == 2 else nn.Identity()
211
+
212
+ def forward(self, x):
213
+ return self.conv(x) + self.shortcut(x)
214
+
215
+
216
  class Contract(nn.Module):
217
  # Contract width-height into channels, i.e. x(1,64,80,80) to x(1,256,40,40)
218
  def __init__(self, gain=2):
models/experimental.py CHANGED
@@ -43,34 +43,6 @@ class Sum(nn.Module):
43
  return y
44
 
45
 
46
- class GhostConv(nn.Module):
47
- # Ghost Convolution https://github.com/huawei-noah/ghostnet
48
- def __init__(self, c1, c2, k=1, s=1, g=1, act=True): # ch_in, ch_out, kernel, stride, groups
49
- super().__init__()
50
- c_ = c2 // 2 # hidden channels
51
- self.cv1 = Conv(c1, c_, k, s, None, g, act)
52
- self.cv2 = Conv(c_, c_, 5, 1, None, c_, act)
53
-
54
- def forward(self, x):
55
- y = self.cv1(x)
56
- return torch.cat([y, self.cv2(y)], 1)
57
-
58
-
59
- class GhostBottleneck(nn.Module):
60
- # Ghost Bottleneck https://github.com/huawei-noah/ghostnet
61
- def __init__(self, c1, c2, k=3, s=1): # ch_in, ch_out, kernel, stride
62
- super().__init__()
63
- c_ = c2 // 2
64
- self.conv = nn.Sequential(GhostConv(c1, c_, 1, 1), # pw
65
- DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(), # dw
66
- GhostConv(c_, c2, 1, 1, act=False)) # pw-linear
67
- self.shortcut = nn.Sequential(DWConv(c1, c1, k, s, act=False),
68
- Conv(c1, c2, 1, 1, act=False)) if s == 2 else nn.Identity()
69
-
70
- def forward(self, x):
71
- return self.conv(x) + self.shortcut(x)
72
-
73
-
74
  class MixConv2d(nn.Module):
75
  # Mixed Depth-wise Conv https://arxiv.org/abs/1907.09595
76
  def __init__(self, c1, c2, k=(1, 3), s=1, equal_ch=True):
 
43
  return y
44
 
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  class MixConv2d(nn.Module):
47
  # Mixed Depth-wise Conv https://arxiv.org/abs/1907.09595
48
  def __init__(self, c1, c2, k=(1, 3), s=1, equal_ch=True):
models/hub/yolov5s-ghost.yaml ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Parameters
2
+ nc: 80 # number of classes
3
+ depth_multiple: 0.33 # model depth multiple
4
+ width_multiple: 0.50 # layer channel multiple
5
+ anchors:
6
+ - [10,13, 16,30, 33,23] # P3/8
7
+ - [30,61, 62,45, 59,119] # P4/16
8
+ - [116,90, 156,198, 373,326] # P5/32
9
+
10
+ # YOLOv5 backbone
11
+ backbone:
12
+ # [from, number, module, args]
13
+ [[-1, 1, Focus, [64, 3]], # 0-P1/2
14
+ [-1, 1, GhostConv, [128, 3, 2]], # 1-P2/4
15
+ [-1, 3, C3Ghost, [128]],
16
+ [-1, 1, GhostConv, [256, 3, 2]], # 3-P3/8
17
+ [-1, 9, C3Ghost, [256]],
18
+ [-1, 1, GhostConv, [512, 3, 2]], # 5-P4/16
19
+ [-1, 9, C3Ghost, [512]],
20
+ [-1, 1, GhostConv, [1024, 3, 2]], # 7-P5/32
21
+ [-1, 1, SPP, [1024, [5, 9, 13]]],
22
+ [-1, 3, C3Ghost, [1024, False]], # 9
23
+ ]
24
+
25
+ # YOLOv5 head
26
+ head:
27
+ [[-1, 1, GhostConv, [512, 1, 1]],
28
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
29
+ [[-1, 6], 1, Concat, [1]], # cat backbone P4
30
+ [-1, 3, C3Ghost, [512, False]], # 13
31
+
32
+ [-1, 1, GhostConv, [256, 1, 1]],
33
+ [-1, 1, nn.Upsample, [None, 2, 'nearest']],
34
+ [[-1, 4], 1, Concat, [1]], # cat backbone P3
35
+ [-1, 3, C3Ghost, [256, False]], # 17 (P3/8-small)
36
+
37
+ [-1, 1, GhostConv, [256, 3, 2]],
38
+ [[-1, 14], 1, Concat, [1]], # cat head P4
39
+ [-1, 3, C3Ghost, [512, False]], # 20 (P4/16-medium)
40
+
41
+ [-1, 1, GhostConv, [512, 3, 2]],
42
+ [[-1, 10], 1, Concat, [1]], # cat head P5
43
+ [-1, 3, C3Ghost, [1024, False]], # 23 (P5/32-large)
44
+
45
+ [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
46
+ ]
models/yolo.py CHANGED
@@ -236,13 +236,13 @@ def parse_model(d, ch): # model_dict, input_channels(3)
236
 
237
  n = n_ = max(round(n * gd), 1) if n > 1 else n # depth gain
238
  if m in [Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP,
239
- C3, C3TR, C3SPP]:
240
  c1, c2 = ch[f], args[0]
241
  if c2 != no: # if not output
242
  c2 = make_divisible(c2 * gw, 8)
243
 
244
  args = [c1, c2, *args[1:]]
245
- if m in [BottleneckCSP, C3, C3TR]:
246
  args.insert(2, n) # number of repeats
247
  n = 1
248
  elif m is nn.BatchNorm2d:
 
236
 
237
  n = n_ = max(round(n * gd), 1) if n > 1 else n # depth gain
238
  if m in [Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP,
239
+ C3, C3TR, C3SPP, C3Ghost]:
240
  c1, c2 = ch[f], args[0]
241
  if c2 != no: # if not output
242
  c2 = make_divisible(c2 * gw, 8)
243
 
244
  args = [c1, c2, *args[1:]]
245
+ if m in [BottleneckCSP, C3, C3TR, C3Ghost]:
246
  args.insert(2, n) # number of repeats
247
  n = 1
248
  elif m is nn.BatchNorm2d: