glenn-jocher commited on
Commit
b1be685
·
unverified ·
1 Parent(s): f7d8562

Module `super().__init__()` (#4065)

Browse files

* Module `super().__init__()`

* remove NMS

Files changed (3) hide show
  1. models/common.py +18 -24
  2. models/experimental.py +6 -6
  3. models/yolo.py +3 -17
models/common.py CHANGED
@@ -36,7 +36,7 @@ def DWConv(c1, c2, k=1, s=1, act=True):
36
  class Conv(nn.Module):
37
  # Standard convolution
38
  def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
39
- super(Conv, self).__init__()
40
  self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
41
  self.bn = nn.BatchNorm2d(c2)
42
  self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
@@ -87,7 +87,7 @@ class TransformerBlock(nn.Module):
87
  class Bottleneck(nn.Module):
88
  # Standard bottleneck
89
  def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion
90
- super(Bottleneck, self).__init__()
91
  c_ = int(c2 * e) # hidden channels
92
  self.cv1 = Conv(c1, c_, 1, 1)
93
  self.cv2 = Conv(c_, c2, 3, 1, g=g)
@@ -100,7 +100,7 @@ class Bottleneck(nn.Module):
100
  class BottleneckCSP(nn.Module):
101
  # CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks
102
  def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
103
- super(BottleneckCSP, self).__init__()
104
  c_ = int(c2 * e) # hidden channels
105
  self.cv1 = Conv(c1, c_, 1, 1)
106
  self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False)
@@ -119,7 +119,7 @@ class BottleneckCSP(nn.Module):
119
  class C3(nn.Module):
120
  # CSP Bottleneck with 3 convolutions
121
  def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
122
- super(C3, self).__init__()
123
  c_ = int(c2 * e) # hidden channels
124
  self.cv1 = Conv(c1, c_, 1, 1)
125
  self.cv2 = Conv(c1, c_, 1, 1)
@@ -139,10 +139,18 @@ class C3TR(C3):
139
  self.m = TransformerBlock(c_, c_, 4, n)
140
 
141
 
 
 
 
 
 
 
 
 
142
  class SPP(nn.Module):
143
  # Spatial pyramid pooling layer used in YOLOv3-SPP
144
  def __init__(self, c1, c2, k=(5, 9, 13)):
145
- super(SPP, self).__init__()
146
  c_ = c1 // 2 # hidden channels
147
  self.cv1 = Conv(c1, c_, 1, 1)
148
  self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
@@ -156,7 +164,7 @@ class SPP(nn.Module):
156
  class Focus(nn.Module):
157
  # Focus wh information into c-space
158
  def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
159
- super(Focus, self).__init__()
160
  self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
161
  # self.contract = Contract(gain=2)
162
 
@@ -196,27 +204,13 @@ class Expand(nn.Module):
196
  class Concat(nn.Module):
197
  # Concatenate a list of tensors along dimension
198
  def __init__(self, dimension=1):
199
- super(Concat, self).__init__()
200
  self.d = dimension
201
 
202
  def forward(self, x):
203
  return torch.cat(x, self.d)
204
 
205
 
206
- class NMS(nn.Module):
207
- # Non-Maximum Suppression (NMS) module
208
- conf = 0.25 # confidence threshold
209
- iou = 0.45 # IoU threshold
210
- classes = None # (optional list) filter by class
211
- max_det = 1000 # maximum number of detections per image
212
-
213
- def __init__(self):
214
- super(NMS, self).__init__()
215
-
216
- def forward(self, x):
217
- return non_max_suppression(x[0], self.conf, iou_thres=self.iou, classes=self.classes, max_det=self.max_det)
218
-
219
-
220
  class AutoShape(nn.Module):
221
  # YOLOv5 input-robust model wrapper for passing cv2/np/PIL/torch inputs. Includes preprocessing, inference and NMS
222
  conf = 0.25 # NMS confidence threshold
@@ -225,7 +219,7 @@ class AutoShape(nn.Module):
225
  max_det = 1000 # maximum number of detections per image
226
 
227
  def __init__(self, model):
228
- super(AutoShape, self).__init__()
229
  self.model = model.eval()
230
 
231
  def autoshape(self):
@@ -292,7 +286,7 @@ class AutoShape(nn.Module):
292
  class Detections:
293
  # YOLOv5 detections class for inference results
294
  def __init__(self, imgs, pred, files, times=None, names=None, shape=None):
295
- super(Detections, self).__init__()
296
  d = pred[0].device # device
297
  gn = [torch.tensor([*[im.shape[i] for i in [1, 0, 1, 0]], 1., 1.], device=d) for im in imgs] # normalizations
298
  self.imgs = imgs # list of images as numpy arrays
@@ -383,7 +377,7 @@ class Detections:
383
  class Classify(nn.Module):
384
  # Classification head, i.e. x(b,c1,20,20) to x(b,c2)
385
  def __init__(self, c1, c2, k=1, s=1, p=None, g=1): # ch_in, ch_out, kernel, stride, padding, groups
386
- super(Classify, self).__init__()
387
  self.aap = nn.AdaptiveAvgPool2d(1) # to x(b,c1,1,1)
388
  self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g) # to x(b,c2,1,1)
389
  self.flat = nn.Flatten()
 
36
  class Conv(nn.Module):
37
  # Standard convolution
38
  def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
39
+ super().__init__()
40
  self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
41
  self.bn = nn.BatchNorm2d(c2)
42
  self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
 
87
  class Bottleneck(nn.Module):
88
  # Standard bottleneck
89
  def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion
90
+ super().__init__()
91
  c_ = int(c2 * e) # hidden channels
92
  self.cv1 = Conv(c1, c_, 1, 1)
93
  self.cv2 = Conv(c_, c2, 3, 1, g=g)
 
100
  class BottleneckCSP(nn.Module):
101
  # CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks
102
  def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
103
+ super().__init__()
104
  c_ = int(c2 * e) # hidden channels
105
  self.cv1 = Conv(c1, c_, 1, 1)
106
  self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False)
 
119
  class C3(nn.Module):
120
  # CSP Bottleneck with 3 convolutions
121
  def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
122
+ super().__init__()
123
  c_ = int(c2 * e) # hidden channels
124
  self.cv1 = Conv(c1, c_, 1, 1)
125
  self.cv2 = Conv(c1, c_, 1, 1)
 
139
  self.m = TransformerBlock(c_, c_, 4, n)
140
 
141
 
142
+ class C3SPP(C3):
143
+ # C3 module with SPP()
144
+ def __init__(self, c1, c2, k=(5, 9, 13), n=1, shortcut=True, g=1, e=0.5):
145
+ super().__init__(c1, c2, n, shortcut, g, e)
146
+ c_ = int(c2 * e)
147
+ self.m = SPP(c_, c_, k)
148
+
149
+
150
  class SPP(nn.Module):
151
  # Spatial pyramid pooling layer used in YOLOv3-SPP
152
  def __init__(self, c1, c2, k=(5, 9, 13)):
153
+ super().__init__()
154
  c_ = c1 // 2 # hidden channels
155
  self.cv1 = Conv(c1, c_, 1, 1)
156
  self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
 
164
  class Focus(nn.Module):
165
  # Focus wh information into c-space
166
  def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
167
+ super().__init__()
168
  self.conv = Conv(c1 * 4, c2, k, s, p, g, act)
169
  # self.contract = Contract(gain=2)
170
 
 
204
  class Concat(nn.Module):
205
  # Concatenate a list of tensors along dimension
206
  def __init__(self, dimension=1):
207
+ super().__init__()
208
  self.d = dimension
209
 
210
  def forward(self, x):
211
  return torch.cat(x, self.d)
212
 
213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  class AutoShape(nn.Module):
215
  # YOLOv5 input-robust model wrapper for passing cv2/np/PIL/torch inputs. Includes preprocessing, inference and NMS
216
  conf = 0.25 # NMS confidence threshold
 
219
  max_det = 1000 # maximum number of detections per image
220
 
221
  def __init__(self, model):
222
+ super().__init__()
223
  self.model = model.eval()
224
 
225
  def autoshape(self):
 
286
  class Detections:
287
  # YOLOv5 detections class for inference results
288
  def __init__(self, imgs, pred, files, times=None, names=None, shape=None):
289
+ super().__init__()
290
  d = pred[0].device # device
291
  gn = [torch.tensor([*[im.shape[i] for i in [1, 0, 1, 0]], 1., 1.], device=d) for im in imgs] # normalizations
292
  self.imgs = imgs # list of images as numpy arrays
 
377
  class Classify(nn.Module):
378
  # Classification head, i.e. x(b,c1,20,20) to x(b,c2)
379
  def __init__(self, c1, c2, k=1, s=1, p=None, g=1): # ch_in, ch_out, kernel, stride, padding, groups
380
+ super().__init__()
381
  self.aap = nn.AdaptiveAvgPool2d(1) # to x(b,c1,1,1)
382
  self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g) # to x(b,c2,1,1)
383
  self.flat = nn.Flatten()
models/experimental.py CHANGED
@@ -12,7 +12,7 @@ class CrossConv(nn.Module):
12
  # Cross Convolution Downsample
13
  def __init__(self, c1, c2, k=3, s=1, g=1, e=1.0, shortcut=False):
14
  # ch_in, ch_out, kernel, stride, groups, expansion, shortcut
15
- super(CrossConv, self).__init__()
16
  c_ = int(c2 * e) # hidden channels
17
  self.cv1 = Conv(c1, c_, (1, k), (1, s))
18
  self.cv2 = Conv(c_, c2, (k, 1), (s, 1), g=g)
@@ -25,7 +25,7 @@ class CrossConv(nn.Module):
25
  class Sum(nn.Module):
26
  # Weighted sum of 2 or more layers https://arxiv.org/abs/1911.09070
27
  def __init__(self, n, weight=False): # n: number of inputs
28
- super(Sum, self).__init__()
29
  self.weight = weight # apply weights boolean
30
  self.iter = range(n - 1) # iter object
31
  if weight:
@@ -46,7 +46,7 @@ class Sum(nn.Module):
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(GhostConv, self).__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)
@@ -59,7 +59,7 @@ class GhostConv(nn.Module):
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(GhostBottleneck, self).__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
@@ -74,7 +74,7 @@ class GhostBottleneck(nn.Module):
74
  class MixConv2d(nn.Module):
75
  # Mixed Depthwise Conv https://arxiv.org/abs/1907.09595
76
  def __init__(self, c1, c2, k=(1, 3), s=1, equal_ch=True):
77
- super(MixConv2d, self).__init__()
78
  groups = len(k)
79
  if equal_ch: # equal c_ per group
80
  i = torch.linspace(0, groups - 1E-6, c2).floor() # c2 indices
@@ -98,7 +98,7 @@ class MixConv2d(nn.Module):
98
  class Ensemble(nn.ModuleList):
99
  # Ensemble of models
100
  def __init__(self):
101
- super(Ensemble, self).__init__()
102
 
103
  def forward(self, x, augment=False, profile=False, visualize=False):
104
  y = []
 
12
  # Cross Convolution Downsample
13
  def __init__(self, c1, c2, k=3, s=1, g=1, e=1.0, shortcut=False):
14
  # ch_in, ch_out, kernel, stride, groups, expansion, shortcut
15
+ super().__init__()
16
  c_ = int(c2 * e) # hidden channels
17
  self.cv1 = Conv(c1, c_, (1, k), (1, s))
18
  self.cv2 = Conv(c_, c2, (k, 1), (s, 1), g=g)
 
25
  class Sum(nn.Module):
26
  # Weighted sum of 2 or more layers https://arxiv.org/abs/1911.09070
27
  def __init__(self, n, weight=False): # n: number of inputs
28
+ super().__init__()
29
  self.weight = weight # apply weights boolean
30
  self.iter = range(n - 1) # iter object
31
  if weight:
 
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)
 
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
 
74
  class MixConv2d(nn.Module):
75
  # Mixed Depthwise Conv https://arxiv.org/abs/1907.09595
76
  def __init__(self, c1, c2, k=(1, 3), s=1, equal_ch=True):
77
+ super().__init__()
78
  groups = len(k)
79
  if equal_ch: # equal c_ per group
80
  i = torch.linspace(0, groups - 1E-6, c2).floor() # c2 indices
 
98
  class Ensemble(nn.ModuleList):
99
  # Ensemble of models
100
  def __init__(self):
101
+ super().__init__()
102
 
103
  def forward(self, x, augment=False, profile=False, visualize=False):
104
  y = []
models/yolo.py CHANGED
@@ -33,7 +33,7 @@ class Detect(nn.Module):
33
  onnx_dynamic = False # ONNX export parameter
34
 
35
  def __init__(self, nc=80, anchors=(), ch=(), inplace=True): # detection layer
36
- super(Detect, self).__init__()
37
  self.nc = nc # number of classes
38
  self.no = nc + 5 # number of outputs per anchor
39
  self.nl = len(anchors) # number of detection layers
@@ -77,7 +77,7 @@ class Detect(nn.Module):
77
 
78
  class Model(nn.Module):
79
  def __init__(self, cfg='yolov5s.yaml', ch=3, nc=None, anchors=None): # model, input channels, number of classes
80
- super(Model, self).__init__()
81
  if isinstance(cfg, dict):
82
  self.yaml = cfg # model dict
83
  else: # is *.yaml
@@ -209,20 +209,6 @@ class Model(nn.Module):
209
  self.info()
210
  return self
211
 
212
- def nms(self, mode=True): # add or remove NMS module
213
- present = type(self.model[-1]) is NMS # last layer is NMS
214
- if mode and not present:
215
- LOGGER.info('Adding NMS... ')
216
- m = NMS() # module
217
- m.f = -1 # from
218
- m.i = self.model[-1].i + 1 # index
219
- self.model.add_module(name='%s' % m.i, module=m) # add
220
- self.eval()
221
- elif not mode and present:
222
- LOGGER.info('Removing NMS... ')
223
- self.model = self.model[:-1] # remove
224
- return self
225
-
226
  def autoshape(self): # add AutoShape module
227
  LOGGER.info('Adding AutoShape... ')
228
  m = AutoShape(self) # wrap model
@@ -250,7 +236,7 @@ def parse_model(d, ch): # model_dict, input_channels(3)
250
 
251
  n = max(round(n * gd), 1) if n > 1 else n # depth gain
252
  if m in [Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP,
253
- C3, C3TR]:
254
  c1, c2 = ch[f], args[0]
255
  if c2 != no: # if not output
256
  c2 = make_divisible(c2 * gw, 8)
 
33
  onnx_dynamic = False # ONNX export parameter
34
 
35
  def __init__(self, nc=80, anchors=(), ch=(), inplace=True): # detection layer
36
+ super().__init__()
37
  self.nc = nc # number of classes
38
  self.no = nc + 5 # number of outputs per anchor
39
  self.nl = len(anchors) # number of detection layers
 
77
 
78
  class Model(nn.Module):
79
  def __init__(self, cfg='yolov5s.yaml', ch=3, nc=None, anchors=None): # model, input channels, number of classes
80
+ super().__init__()
81
  if isinstance(cfg, dict):
82
  self.yaml = cfg # model dict
83
  else: # is *.yaml
 
209
  self.info()
210
  return self
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  def autoshape(self): # add AutoShape module
213
  LOGGER.info('Adding AutoShape... ')
214
  m = AutoShape(self) # wrap model
 
236
 
237
  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)