text: # -*- coding: utf-8 -*-
  ''' python 3.4+
  author: Yu Yang
  '''
  """
  this code is modified from torchivision.resnet
  
  The main change is the basicblock, which is added dropout between two conv layers.
  """
  
  import torch.nn as nn
  import math
  import torch.utils.model_zoo as model_zoo
  
  
  __all__ = ['ResNet', 'myresnet18', 'myresnet34', 'myresnet50', 'myresnet101',
             'myresnet152']
  
  
  model_urls = {
      'myresnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
      'myresnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',
      'myresnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
      'myresnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',
      'myresnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',
  }
  
  
  def conv3x3(in_planes, out_planes, stride=1):
      "3x3 convolution with padding"
      return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
                       padding=1, bias=False)
  
  
  class MyBasicBlock(nn.Module):
      expansion = 1
  
      def __init__(self, inplanes, planes, stride=1, downsample=None):
          super(MyBasicBlock, self).__init__()
          self.conv1 = conv3x3(inplanes, planes, stride)
          self.bn1 = nn.BatchNorm2d(planes)
          self.relu = nn.ReLU(inplace=True)
          self.dropout = nn.Dropout2d()
          self.conv2 = conv3x3(planes, planes)
          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.dropout(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 MyBottleneck(nn.Module):
      expansion = 4
  
      def __init__(self, inplanes, planes, stride=1, downsample=None):
          super(MyBottleneck, self).__init__()
          self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
          self.bn1 = nn.BatchNorm2d(planes)
          self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
                                 padding=1, bias=False)
          self.bn2 = nn.BatchNorm2d(planes)
          self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
          self.bn3 = nn.BatchNorm2d(planes * 4)
          self.dropout = nn.Dropout2d()
          self.relu = nn.ReLU(inplace=True)
          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.dropout(out)
  
          out = self.conv2(out)
          out = self.bn2(out)
          out = self.relu(out)
  
          out = self.conv3(out)
          out = self.bn3(out)
  
          if self.downsample is not None:
              residual = self.downsample(x)
  
          out += residual
          out = self.relu(out)
  
          return out
  
  
  class ResNet(nn.Module):
  
      def __init__(self, block, layers, num_classes=1000):
          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.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.avgpool(x)
          x = x.view(x.size(0), -1)
          x = self.fc(x)
  
          return x
  
  
  def myresnet18(pretrained=False, **kwargs):
      """Constructs a ResNet-18 model.
      Args:
          pretrained (bool): If True, returns a model pre-trained on ImageNet
      """
      model = ResNet(MyBasicBlock, [2, 2, 2, 2], **kwargs)
      if pretrained:
          model.load_state_dict(model_zoo.load_url(model_urls['myresnet18']))
      return model
  
  
  def myresnet34(pretrained=False, **kwargs):
      """Constructs a ResNet-34 model.
      Args:
          pretrained (bool): If True, returns a model pre-trained on ImageNet
      """
      model = ResNet(MyBasicBlock, [3, 4, 6, 3], **kwargs)
      if pretrained:
          model.load_state_dict(model_zoo.load_url(model_urls['myresnet34']))
      return model
  
  
  def myresnet50(pretrained=False, **kwargs):
      """Constructs a ResNet-50 model.
      Args:
          pretrained (bool): If True, returns a model pre-trained on ImageNet
      """
      model = ResNet(MyBottleneck, [3, 4, 6, 3], **kwargs)
      if pretrained:
          model.load_state_dict(model_zoo.load_url(model_urls['myresnet50']))
      return model
  
  
  def myresnet101(pretrained=False, **kwargs):
      """Constructs a ResNet-101 model.
      Args:
          pretrained (bool): If True, returns a model pre-trained on ImageNet
      """
      model = ResNet(MyBottleneck, [3, 4, 23, 3], **kwargs)
      if pretrained:
          model.load_state_dict(model_zoo.load_url(model_urls['myresnet101']))
      return model
  
  
  def myresnet152(pretrained=False, **kwargs):
      """Constructs a ResNet-152 model.
      Args:
          pretrained (bool): If True, returns a model pre-trained on ImageNet
      """
      model = ResNet(MyBottleneck, [3, 8, 36, 3], **kwargs)
      if pretrained:
          model.load_state_dict(model_zoo.load_url(model_urls['myresnet152']))
      return model