resnet50.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. '''ResNet in PyTorch.
  2. For Pre-activation ResNet, see 'preact_resnet.py'.
  3. Reference:
  4. [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
  5. Deep Residual Learning for Image Recognition. arXiv:1512.03385
  6. '''
  7. import torch
  8. import torch.nn as nn
  9. import torch.nn.functional as F
  10. from easyfl.models import BaseModel
  11. class BasicBlock(BaseModel):
  12. expansion = 1
  13. def __init__(self, in_planes, planes, stride=1):
  14. super(BasicBlock, self).__init__()
  15. self.conv1 = nn.Conv2d(
  16. in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
  17. self.bn1 = nn.BatchNorm2d(planes)
  18. self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,
  19. stride=1, padding=1, bias=False)
  20. self.bn2 = nn.BatchNorm2d(planes)
  21. self.shortcut = nn.Sequential()
  22. if stride != 1 or in_planes != self.expansion * planes:
  23. self.shortcut = nn.Sequential(
  24. nn.Conv2d(in_planes, self.expansion * planes,
  25. kernel_size=1, stride=stride, bias=False),
  26. nn.BatchNorm2d(self.expansion * planes)
  27. )
  28. def forward(self, x):
  29. out = F.relu(self.bn1(self.conv1(x)))
  30. out = self.bn2(self.conv2(out))
  31. out += self.shortcut(x)
  32. out = F.relu(out)
  33. return out
  34. class Bottleneck(BaseModel):
  35. expansion = 4
  36. def __init__(self, in_planes, planes, stride=1):
  37. super(Bottleneck, self).__init__()
  38. self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
  39. self.bn1 = nn.BatchNorm2d(planes)
  40. self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,
  41. stride=stride, padding=1, bias=False)
  42. self.bn2 = nn.BatchNorm2d(planes)
  43. self.conv3 = nn.Conv2d(planes, self.expansion *
  44. planes, kernel_size=1, bias=False)
  45. self.bn3 = nn.BatchNorm2d(self.expansion * planes)
  46. self.shortcut = nn.Sequential()
  47. if stride != 1 or in_planes != self.expansion * planes:
  48. self.shortcut = nn.Sequential(
  49. nn.Conv2d(in_planes, self.expansion * planes,
  50. kernel_size=1, stride=stride, bias=False),
  51. nn.BatchNorm2d(self.expansion * planes)
  52. )
  53. def forward(self, x):
  54. out = F.relu(self.bn1(self.conv1(x)))
  55. out = F.relu(self.bn2(self.conv2(out)))
  56. out = self.bn3(self.conv3(out))
  57. out += self.shortcut(x)
  58. out = F.relu(out)
  59. return out
  60. class Model(BaseModel):
  61. def __init__(self, block=Bottleneck, num_blocks=[3, 4, 6, 3], num_classes=10):
  62. super(Model, self).__init__()
  63. self.in_planes = 64
  64. self.conv1 = nn.Conv2d(3, 64, kernel_size=3,
  65. stride=1, padding=1, bias=False)
  66. self.bn1 = nn.BatchNorm2d(64)
  67. self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
  68. self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
  69. self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
  70. self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
  71. self.linear = nn.Linear(512 * block.expansion, num_classes)
  72. def _make_layer(self, block, planes, num_blocks, stride):
  73. strides = [stride] + [1] * (num_blocks - 1)
  74. layers = []
  75. for stride in strides:
  76. layers.append(block(self.in_planes, planes, stride))
  77. self.in_planes = planes * block.expansion
  78. return nn.Sequential(*layers)
  79. def forward(self, x):
  80. out = F.relu(self.bn1(self.conv1(x)))
  81. out = self.layer1(out)
  82. out = self.layer2(out)
  83. out = self.layer3(out)
  84. out = self.layer4(out)
  85. out = F.avg_pool2d(out, 4)
  86. out = out.view(out.size(0), -1)
  87. out = self.linear(out)
  88. return out
  89. def ResNet50():
  90. return Model(Bottleneck, [3, 4, 6, 3])