Multihead SSD implementation for fastai v1

I’m trying to define a multilayer model architecture from here with Colab, but after I append any StdConv and OutConv to SSDHead, I get this error:

LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-16-3c6003eb6534> in <module>()
----> 1 ssd.lr_find()

<ipython-input-14-894bf8122171> in lr_find(self)
     58     def lr_find(self):
     59         from IPython.display import clear_output
---> 60         self.learn.lr_find(num_it=100)
     61         clear_output()
     62         self.learn.recorder.plot()

/usr/local/lib/python3.6/dist-packages/fastai/train.py in lr_find(learn, start_lr, end_lr, num_it, stop_div, wd)
     30     cb = LRFinder(learn, start_lr, end_lr, num_it, stop_div)
     31     epochs = int(np.ceil(num_it/len(learn.data.train_dl)))
---> 32     learn.fit(epochs, start_lr, callbacks=[cb], wd=wd)
     33 
     34 def to_fp16(learn:Learner, loss_scale:float=None, max_noskip:int=1000, dynamic:bool=False, clip:float=None,

/usr/local/lib/python3.6/dist-packages/fastai/basic_train.py in fit(self, epochs, lr, wd, callbacks)
    194         callbacks = [cb(self) for cb in self.callback_fns] + listify(callbacks)
    195         if defaults.extra_callbacks is not None: callbacks += defaults.extra_callbacks
--> 196         fit(epochs, self, metrics=self.metrics, callbacks=self.callbacks+callbacks)
    197 
    198     def create_opt(self, lr:Floats, wd:Floats=0.)->None:

/usr/local/lib/python3.6/dist-packages/fastai/basic_train.py in fit(epochs, learn, callbacks, metrics)
     98             for xb,yb in progress_bar(learn.data.train_dl, parent=pbar):
     99                 xb, yb = cb_handler.on_batch_begin(xb, yb)
--> 100                 loss = loss_batch(learn.model, xb, yb, learn.loss_func, learn.opt, cb_handler)
    101                 if cb_handler.on_batch_end(loss): break
    102 

/usr/local/lib/python3.6/dist-packages/fastai/basic_train.py in loss_batch(model, xb, yb, loss_func, opt, cb_handler)
     27 
     28     if not loss_func: return to_detach(out), yb[0].detach()
---> 29     loss = loss_func(out, *yb)
     30 
     31     if opt is not None:

<ipython-input-14-894bf8122171> in _ssd_loss(self, pred, targ1, targ2, print_it)
    141         lcs,lls = 0.,0.
    142         for b_c,b_bb,bbox,clas in zip(*pred, targ1, targ2):
--> 143             loc_loss,clas_loss = self._ssd_1_loss(b_c,b_bb,bbox.cuda(),clas.cuda(),print_it)
    144             lls += loc_loss
    145             lcs += clas_loss

<ipython-input-14-894bf8122171> in _ssd_1_loss(self, b_c, b_bb, bbox, clas, print_it)
    123         bbox = self._normalize_bbox(bbox)
    124 
--> 125         a_ic = self._actn_to_bb(b_bb, self._anchors, self._grid_sizes)
    126         overlaps = self._jaccard(bbox.data, self._anchor_cnr.data)
    127         try:

<ipython-input-14-894bf8122171> in _actn_to_bb(self, actn, anchors, grid_sizes)
    106     def _actn_to_bb(self, actn, anchors, grid_sizes):
    107         actn_bbs = torch.tanh(actn)
--> 108         actn_centers = (actn_bbs[:,:2]/2 * grid_sizes) + anchors[:,:2]
    109         actn_hw = (actn_bbs[:,2:]/2+1) * anchors[:,2:]
    110         return self._hw2corners(actn_centers, actn_hw)

RuntimeError: The size of tensor a (216) must match the size of tensor b (189) at non-singleton dimension 0

I’ve modified the code like this:

class SSDHead(nn.Module):
    def __init__(self, grids, anchors_per_cell, num_classes, drop=0.3, bias=-4.):
        super().__init__()
        
        self.drop = nn.Dropout(drop)
        
        self.sconvs = nn.ModuleList([])
        self.oconvs = nn.ModuleList([])
        
        self.anc_grids = grids
        
        self._k = anchors_per_cell

        
        self.sconvs.append(StdConv(512, 256, stride=1, drop=drop))
        
        
        for i in range(len(grids)):
            
            if i == 0:
                stride, pad, filter_size = conv_params(7, grids[i]) # get '7' by base model
            else:
                stride, pad, filter_size = conv_params(grids[i-1], grids[i])
            
            if stride is None:
                print(grids[i-1], ' --> ', grids[i])
                raise Exception('cannot create model for specified grids')
                
            self.sconvs.append(StdConv(256, 256))
            self.sconvs.append(StdConv(256, 256))
            self.oconvs.append(OutConv(self._k, 256, num_classes=num_classes, bias=bias))
            self.oconvs.append(OutConv(self._k, 256, num_classes=num_classes, bias=bias))
                
    def forward(self, x):
        x = self.drop(F.relu(x))
        x = self.sconvs[0](x)
        out_classes = []
        out_bboxes = []
        for sconv, oconv in zip(self.sconvs[1:], self.oconvs[:]):
            x = sconv(x)
            out_class, out_bbox = oconv(x)
            out_classes.append(out_class)
            out_bboxes.append(out_bbox)
            
        return [torch.cat(out_classes, dim=1),
                torch.cat(out_bboxes, dim=1)]

I don’t know what can I do to match both tensor sizes or how to implement more layers without errors