code: 
  from torch.autograd import Variable
  from models.proposal_target_layer_cascade import *
  import torchvision.models as models
  from models.proposal import *
  #bocknet
  class ResNet(nn.Module):
      def __init__(self, block, layers, num_classes=1000,dropout_prob=0.2):
          self.inplanes = 64
          super(ResNet, self).__init__()
          self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
                                 bias=False)
          self.bn1 = nn.BatchNorm2d(64)
          self.relu = nn.ReLU(inplace=True)
          self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
          self.layer1 = self._make_layer(block, 64, layers[0])
          self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
          self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
          self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
          self.dropout = nn.Dropout(p=dropout_prob)
          self.avgpool = nn.AvgPool2d(7)
          self.fc = nn.Linear(512 * block.expansion, num_classes)
  
          for m in self.modules():
              if isinstance(m, nn.Conv2d):
                  n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                  m.weight.data.normal_(0, math.sqrt(2. / n))
              elif isinstance(m, nn.BatchNorm2d):
                  m.weight.data.fill_(1)
                  m.bias.data.zero_()
  
      def _make_layer(self, block, planes, blocks, stride=1):
          downsample = None
          if stride != 1 or self.inplanes != planes * block.expansion:
              downsample = nn.Sequential(
                  nn.Conv2d(self.inplanes, planes * block.expansion,
                            kernel_size=1, stride=stride, bias=False),
                  nn.BatchNorm2d(planes * block.expansion),
              )
  
          layers = []
          layers.append(block(self.inplanes, planes, stride, downsample))
          self.inplanes = planes * block.expansion
          for i in range(1, blocks):
              layers.append(block(self.inplanes, planes))
  
          return nn.Sequential(*layers)
  
      def forward(self, x):
          x = self.conv1(x)
          x = self.bn1(x)
          x = self.relu(x)
          x = self.maxpool(x)
  
          x = self.layer1(x)
          x = self.layer2(x)
          x = self.layer3(x)
          x = self.layer4(x)
  
          x = self.dropout(x)
          x = self.avgpool(x)
          x = x.view(x.size(0), -1)
          x = self.fc(x)
  
          return x
  
  class _fasterRCNN(nn.Module):
      """ faster RCNN """
      def __init__(self, classes, class_agnostic):
          super(_fasterRCNN, self).__init__()
          self.classes = classes
          self.n_classes = len(classes)
          self.class_agnostic = class_agnostic
          # loss
          self.RCNN_loss_cls = 0
          self.RCNN_loss_bbox = 0
  
  
  
      def forward(self, im_data, im_info, gt_boxes, num_boxes):
          batch_size = im_data.size(0)
  
          im_info = im_info.data
          gt_boxes = gt_boxes.data
          num_boxes = num_boxes.data
  
          # feed image cfgs to base model to obtain base feature map
          base_feat = self.RCNN_base(im_data)
  
          # feed base feature map to RPN to obtain rois
          rois, rpn_loss_cls, rpn_loss_bbox = self.RCNN_rpn(base_feat, im_info, gt_boxes, num_boxes)
  
          # if it is training phase, then use ground truth bboxes for refining
          if self.training:
              roi_data = self.RCNN_proposal_target(rois, gt_boxes, num_boxes)
              rois, rois_label, rois_target, rois_inside_ws, rois_outside_ws = roi_data
  
              rois_label = Variable(rois_label.view(-1).long())
          else:
              rois_label = None
              rpn_loss_cls = 0
              rpn_loss_bbox = 0
  
          rois = Variable(rois)
          # do roi pooling based on predicted rois
  
          pooled_feat = self.RCNN_roi_pool(base_feat, rois.view(-1,5))
  
          # feed pooled features to top model
          pooled_feat = self._head_to_tail(pooled_feat)
  
          # compute bbox offset
          bbox_pred = self.RCNN_bbox_pred(pooled_feat)
          if self.training and not self.class_agnostic:
              # select the corresponding columns according to roi labels
              bbox_pred_view = bbox_pred.view(bbox_pred.size(0), int(bbox_pred.size(1) / 4), 4)
              bbox_pred_select = torch.gather(bbox_pred_view, 1, rois_label.view(rois_label.size(0), 1, 1).expand(rois_label.size(0), 1, 4))
              bbox_pred = bbox_pred_select.squeeze(1)
  
          # compute object classification probability
          cls_score = self.RCNN_cls_score(pooled_feat)
          cls_prob = F.softmax(cls_score, 1)
  
          RCNN_loss_cls = 0
          RCNN_loss_bbox = 0
  
  
          cls_prob = cls_prob.view(batch_size, rois.size(1), -1)
          bbox_pred = bbox_pred.view(batch_size, rois.size(1), -1)
  
          return rois, cls_prob, bbox_pred, rpn_loss_cls, rpn_loss_bbox, RCNN_loss_cls, RCNN_loss_bbox, rois_label
  
      def _init_weights(self):
          def normal_init(m, mean, stddev, truncated=False):
              """
              weight initalizer: truncated normal and random normal.
              """
              # x is a parameter
              if truncated:
                  m.weight.data.normal_().fmod_(2).mul_(stddev).add_(mean) # not a perfect approximation
              else:
                  m.weight.data.normal_(mean, stddev)
                  m.bias.data.zero_()
      def create_architecture(self):
          self._init_modules()
          self._init_weights()
  
  
  
  #
  class BasicBlock(nn.Module):
    expansion = 1
  
    def __init__(self, inplanes, planes, stride=1, downsample=None):
      super(BasicBlock, self).__init__()
      self.bn1 = nn.BatchNorm2d(planes)
      self.relu = nn.ReLU(inplace=True)
      self.bn2 = nn.BatchNorm2d(planes)
      self.downsample = downsample
      self.stride = stride
  
    def forward(self, x):
      residual = x
  
      out = self.conv1(x)
      out = self.bn1(out)
      out = self.relu(out)
  
      out = self.conv2(out)
      out = self.bn2(out)
  
      if self.downsample is not None:
        residual = self.downsample(x)
  
      out += residual
      out = self.relu(out)
  
      return out
  
  class Model(nn.Module):
      def __init__(self, model_cfg='datanet.yaml', ch=3, nc=None):
          super(Model, self).__init__()
          if type(model_cfg) is dict:
              self.md = model_cfg
          else:
              import yaml
              with open(model_cfg) as f:
                  self.md = yaml.load(f, Loader=yaml.FullLoader)
  
          if nc and nc != self.md['nc']:
              print('Overriding %s nc=%g with nc=%g' % (model_cfg, self.md['nc'], nc))
              self.md['nc'] = nc
          self.model, self.save = BasicBlock(self.md, ch=[ch])
  
          m = self.model[-1]
          if isinstance(m, Detect):
              s = 128
              m.stride = torch.tensor([s / x.shape[-2] for x in self.forward(torch.zeros(1, ch, s, s))])
              m.anchors /= m.stride.view(-1, 1, 1)
              check_anchor_order(m)
              self.stride = m.stride
              self._initialize_biases()
  
          torch_utils.initialize_weights(self)
          self._initialize_biases()
          torch_utils.model_info(self)
          print('')
  
      def forward(self, x, augment=False, profile=False):
          if augment:
              img_size = x.shape[-2:]
              s = [0.83, 0.67]
              y = []
              for i, xi in enumerate((x,
                                      torch_utils.scale_img(x.flip(3), s[0]),
                                      torch_utils.scale_img(x, s[1]),
                                      )):
                  y.append(self.forward_once(xi)[0])
  
              y[1][..., :4] /= s[0]  # scale
              y[1][..., 0] = img_size[1] - y[1][..., 0]  # flip lr
              y[2][..., :4] /= s[1]  # scale
              return torch.cat(y, 1), None
          else:
              return self.forward_once(x, profile)
  
      def forward_once(self, x, profile=False):
          y, dt = [], []  # outputs
          for m in self.model:
              if m.f != -1:  # if not from previous layer
                  x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layers
  
              if profile:
                  try:
                      import thop
                      o = thop.profile(m, inputs=(x,), verbose=False)[0] / 1E9 * 2  # FLOPS
                  except:
                      o = 0
                  t = torch_utils.time_synchronized()
                  for _ in range(10):
                      _ = m(x)
                  dt.append((torch_utils.time_synchronized() - t) * 100)
                  print('%10.1f%10.0f%10.1fms %-40s' % (o, m.np, dt[-1], m.type))
  
              x = m(x)  # run
              y.append(x if m.i in self.save else None)  # save output
  
          if profile:
              print('%.1fms total' % sum(dt))
          return x
  
      def _initialize_biases(self, cf=None):  # initialize biases into Detect(), cf is class frequency
          m = self.model[-1]  # Detect() module
          for f, s in zip(m.f, m.stride):  #  from
              mi = self.model[f % m.i]
              b = mi.bias.view(m.na, -1)  # conv.bias(255) to (3,85)
              b[:, 4] += math.log(8 / (640 / s) ** 2)  # obj (8 objects per 640 image)
              b[:, 5:] += math.log(0.6 / (m.nc - 0.99)) if cf is None else torch.log(cf / cf.sum())  # cls
              mi.bias = torch.nn.Parameter(b.view(-1), requires_grad=True)
  
      def _print_biases(self):
          m = self.model[-1]  # Detect() module
          for f in sorted([x % m.i for x in m.f]):  #  from
              b = self.model[f].bias.detach().view(m.na, -1).T  # conv.bias(255) to (3,85)
              print(('%g Conv2d.bias:' + '%10.3g' * 6) % (f, *b[:5].mean(1).tolist(), b[5:].mean()))
  
  
      def fuse(self):  # fuse model Conv2d() + BatchNorm2d() layers
          print('Fusing layers... ', end='')
          for m in self.model.modules():
              if type(m) is Conv:
                  m.conv = torch_utils.fuse_conv_and_bn(m.conv, m.bn)  # update conv
                  m.bn = None  # remove batchnorm
                  m.forward = m.fuseforward  # update forward
          torch_utils.model_info(self)
          return self
  
  def BasicBlock(runwget, ch):
      anchors, nc, gd, gw = runwget['anchors'], runwget['nc'], runwget['depth_multiple'], runwget['width_multiple']
      na = (len(anchors[0]) // 2)  # number of anchors
      no = na * (nc + 5)  # number of outputs = anchors * (classes + 5)
  
      layers, save, c2 = [], [], ch[-1]  # layers, savelist, ch out
      for i, (f, n, m, args) in enumerate(runwget['backbone'] + runwget['head']):  # from, number, module, args
          m = eval(m) if isinstance(m, str) else m  # eval strings
          for j, a in enumerate(args):
              try:
                  args[j] = eval(a) if isinstance(a, str) else a  # eval strings
              except:
                  pass
  
          n = max(round(n * gd), 1) if n > 1 else n  # depth gain
          if m in [nn.Conv2d, Conv, Bottleneck, SPP, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP, C3]:
              c1, c2 = ch[f], args[0]
              c2 = make_divisible(c2 * gw, 8) if c2 != no else c2
              args = [c1, c2, *args[1:]]
              if m in [BottleneckCSP, C3]:
                  args.insert(2, n)
                  n = 1
          elif m is nn.BatchNorm2d:
              args = [ch[f]]
          elif m is Concat:
              c2 = sum([ch[-1 if x == -1 else x + 1] for x in f])
          elif m is Detect:
              f = f or list(reversed([(-1 if j == i else j - 1) for j, x in enumerate(ch) if x == no]))
          else:
              c2 = ch[f]
          m_ = nn.Sequential(*[m(*args) for _ in range(n)]) if n > 1 else m(*args)  # module
          t = str(m)[8:-2].replace('__main__.', '')  # module type
          np = sum([x.numel() for x in m_.parameters()])  # number params
          m_.i, m_.f, m_.type, m_.np = i, f, t, np  # attach index, 'from' index, type, number params
          save.extend(x % i for x in ([f] if isinstance(f, int) else f) if x != -1)  # append to savelist
          layers.append(m_)
          ch.append(c2)
      return nn.Sequential(*layers), sorted(save)
  
  class vgg16(_fasterRCNN):
      def __init__(self, classes, pretrained=False, class_agnostic=False):
          self.model_path = 'cfgs/pretrained_model/vgg16_caffe.pth'
          self.dout_base_model = 512
          self.pretrained = pretrained
          self.class_agnostic = class_agnostic
  
          _fasterRCNN.__init__(self, classes, class_agnostic)
  
      def _init_modules(self):
          vgg = models.vgg16()
          if self.pretrained:
              print("Loading pretrained weights from %s" % (self.model_path))
              state_dict = torch.load(self.model_path)
              vgg.load_state_dict({k: v for k, v in state_dict.items() if k in vgg.state_dict()})
  
          vgg.classifier = nn.Sequential(*list(vgg.classifier._modules.values())[:-1])
  
          self.RCNN_base = nn.Sequential(*list(vgg.features._modules.values())[:-1])
  
          for layer in range(10):
              for p in self.RCNN_base[layer].parameters(): p.requires_grad = False
  
          self.RCNN_top = vgg.classifier
  
          self.RCNN_cls_score = nn.Linear(4096, self.n_classes)
  
          if self.class_agnostic:
              self.RCNN_bbox_pred = nn.Linear(4096, 4)
          else:
              self.RCNN_bbox_pred = nn.Linear(4096, 4 * self.n_classes)
  
      def _head_to_tail(self, pool5):
  
          pool5_flat = pool5.view(pool5.size(0), -1)
          fc7 = self.RCNN_top(pool5_flat)
  
          return fc7
  
  
  
apis: torch.autograd.Variable