resnet.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import torch
  2. import torch.nn as nn
  3. import torch.nn.functional as F
  4. import torchvision.models.resnet
  5. class BasicBlock(nn.Module):
  6. expansion = 1
  7. def __init__(self, in_planes, planes, stride=1):
  8. super(BasicBlock, self).__init__()
  9. self.conv1 = nn.Conv2d(
  10. in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
  11. self.bn1 = nn.BatchNorm2d(planes)
  12. self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,
  13. stride=1, padding=1, bias=False)
  14. self.bn2 = nn.BatchNorm2d(planes)
  15. self.shortcut = nn.Sequential()
  16. if stride != 1 or in_planes != self.expansion * planes:
  17. self.shortcut = nn.Sequential(
  18. nn.Conv2d(in_planes, self.expansion * planes,
  19. kernel_size=1, stride=stride, bias=False),
  20. nn.BatchNorm2d(self.expansion * planes)
  21. )
  22. def forward(self, x):
  23. out = F.relu(self.bn1(self.conv1(x)))
  24. out = self.bn2(self.conv2(out))
  25. out += self.shortcut(x)
  26. out = F.relu(out)
  27. return out
  28. class Bottleneck(nn.Module):
  29. expansion = 4
  30. def __init__(self, in_planes, planes, stride=1):
  31. super(Bottleneck, self).__init__()
  32. self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
  33. self.bn1 = nn.BatchNorm2d(planes)
  34. self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,
  35. stride=stride, padding=1, bias=False)
  36. self.bn2 = nn.BatchNorm2d(planes)
  37. self.conv3 = nn.Conv2d(planes, self.expansion *
  38. planes, kernel_size=1, bias=False)
  39. self.bn3 = nn.BatchNorm2d(self.expansion * planes)
  40. self.shortcut = nn.Sequential()
  41. if stride != 1 or in_planes != self.expansion * planes:
  42. self.shortcut = nn.Sequential(
  43. nn.Conv2d(in_planes, self.expansion * planes,
  44. kernel_size=1, stride=stride, bias=False),
  45. nn.BatchNorm2d(self.expansion * planes)
  46. )
  47. def forward(self, x):
  48. out = F.relu(self.bn1(self.conv1(x)))
  49. out = F.relu(self.bn2(self.conv2(out)))
  50. out = self.bn3(self.conv3(out))
  51. out += self.shortcut(x)
  52. out = F.relu(out)
  53. return out
  54. class ResNet(nn.Module):
  55. """ResNet
  56. Note two main differences from official pytorch version:
  57. 1. conv1 kernel size: pytorch version uses kernel_size=7
  58. 2. average pooling: pytorch version uses AdaptiveAvgPool
  59. """
  60. def __init__(self, block, num_blocks, num_classes=10):
  61. super(ResNet, self).__init__()
  62. self.in_planes = 64
  63. self.feature_dim = 512 * block.expansion
  64. self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
  65. self.bn1 = nn.BatchNorm2d(64)
  66. self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
  67. self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
  68. self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
  69. self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
  70. self.avgpool = nn.AvgPool2d((4, 4))
  71. self.fc = 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 = self.avgpool(out)
  86. out = out.view(out.size(0), -1)
  87. out = self.fc(out)
  88. return out
  89. def ResNet18(num_classes=10):
  90. return ResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes)
  91. def ResNet34(num_classes=10):
  92. return ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes)
  93. def ResNet50(num_classes=10):
  94. return ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes)
  95. def ResNet101(num_classes=10):
  96. return ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes)
  97. def ResNet152(num_classes=10):
  98. return ResNet(Bottleneck, [3, 8, 36, 3], num_classes=num_classes)