In Masterarbeit:"Anomalie-Detektion in Zellbildern zur Anwendung der Leukämieerkennung" verwendete Methode des 3. Platzes der ISBI2019.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

model.py 6.0KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. # Code adapted from: https://github.com/Cadene/pretrained-models.pytorch
  2. import math
  3. from collections import OrderedDict
  4. from itertools import chain
  5. import torch.nn as nn
  6. from torch.utils import model_zoo
  7. from utils import Flatten
  8. class SEModule(nn.Module):
  9. def __init__(self, channels, reduction):
  10. super(SEModule, self).__init__()
  11. self.avg_pool = nn.AdaptiveAvgPool2d(1)
  12. self.fc1 = nn.Conv2d(channels, channels // reduction, kernel_size=1, padding=0)
  13. self.relu = nn.ReLU(inplace=True)
  14. self.fc2 = nn.Conv2d(channels // reduction, channels, kernel_size=1, padding=0)
  15. self.sigmoid = nn.Sigmoid()
  16. def forward(self, x):
  17. module_input = x
  18. x = self.avg_pool(x)
  19. x = self.fc1(x)
  20. x = self.relu(x)
  21. x = self.fc2(x)
  22. x = self.sigmoid(x)
  23. return module_input * x
  24. class SEResNeXtBottleneck(nn.Module):
  25. """
  26. ResNeXt bottleneck type C with a Squeeze-and-Excitation module.
  27. """
  28. expansion = 4
  29. def __init__(self, inplanes, planes, groups, reduction, stride=1, downsample=None, base_width=4):
  30. super(SEResNeXtBottleneck, self).__init__()
  31. width = math.floor(planes * (base_width / 64)) * groups
  32. self.conv1 = nn.Conv2d(inplanes, width, kernel_size=1, bias=False, stride=1)
  33. self.bn1 = nn.BatchNorm2d(width)
  34. self.conv2 = nn.Conv2d(width, width, kernel_size=3, stride=stride, padding=1, groups=groups, bias=False)
  35. self.bn2 = nn.BatchNorm2d(width)
  36. self.conv3 = nn.Conv2d(width, planes * 4, kernel_size=1, bias=False)
  37. self.bn3 = nn.BatchNorm2d(planes * 4)
  38. self.relu = nn.ReLU(inplace=True)
  39. self.se_module = SEModule(planes * 4, reduction=reduction)
  40. self.downsample = downsample
  41. self.stride = stride
  42. def forward(self, x):
  43. residual = x
  44. out = self.conv1(x)
  45. out = self.bn1(out)
  46. out = self.relu(out)
  47. out = self.conv2(out)
  48. out = self.bn2(out)
  49. out = self.relu(out)
  50. out = self.conv3(out)
  51. out = self.bn3(out)
  52. if self.downsample is not None:
  53. residual = self.downsample(x)
  54. out = self.se_module(out) + residual
  55. out = self.relu(out)
  56. return out
  57. class SENet(nn.Module):
  58. def __init__(self, block, layers, groups, reduction, inplanes=128,
  59. downsample_kernel_size=3, downsample_padding=1):
  60. super(SENet, self).__init__()
  61. self.inplanes = inplanes
  62. layer0_modules = [
  63. ('conv1', nn.Conv2d(3, inplanes, kernel_size=7, stride=2, padding=3, bias=False)),
  64. ('bn1', nn.BatchNorm2d(inplanes)),
  65. ('relu1', nn.ReLU(inplace=True)),
  66. # To preserve compatibility with Caffe weights `ceil_mode=True`
  67. # is used instead of `padding=1`.
  68. ('pool', nn.MaxPool2d(3, stride=2, ceil_mode=True))
  69. ]
  70. self.layer0 = nn.Sequential(OrderedDict(layer0_modules))
  71. self.layer1 = self._make_layer(
  72. block,
  73. planes=64,
  74. blocks=layers[0],
  75. groups=groups,
  76. reduction=reduction,
  77. downsample_kernel_size=1,
  78. downsample_padding=0
  79. )
  80. self.layer2 = self._make_layer(
  81. block,
  82. planes=128,
  83. blocks=layers[1],
  84. stride=2,
  85. groups=groups,
  86. reduction=reduction,
  87. downsample_kernel_size=downsample_kernel_size,
  88. downsample_padding=downsample_padding
  89. )
  90. self.layer3 = self._make_layer(
  91. block,
  92. planes=256,
  93. blocks=layers[2],
  94. stride=2,
  95. groups=groups,
  96. reduction=reduction,
  97. downsample_kernel_size=downsample_kernel_size,
  98. downsample_padding=downsample_padding
  99. )
  100. self.layer4 = self._make_layer(
  101. block,
  102. planes=512,
  103. blocks=layers[3],
  104. stride=2,
  105. groups=groups,
  106. reduction=reduction,
  107. downsample_kernel_size=downsample_kernel_size,
  108. downsample_padding=downsample_padding
  109. )
  110. self.cls = nn.Sequential(
  111. nn.AdaptiveAvgPool2d(1),
  112. Flatten(),
  113. nn.Linear(512 * block.expansion, 1)
  114. )
  115. def _make_layer(self, block, planes, blocks, groups, reduction, stride=1,
  116. downsample_kernel_size=1, downsample_padding=0):
  117. downsample = None
  118. if stride != 1 or self.inplanes != planes * block.expansion:
  119. downsample = nn.Sequential(
  120. nn.Conv2d(self.inplanes, planes * block.expansion,
  121. kernel_size=downsample_kernel_size, stride=stride,
  122. padding=downsample_padding, bias=False),
  123. nn.BatchNorm2d(planes * block.expansion),
  124. )
  125. layers = [block(self.inplanes, planes, groups, reduction, stride, downsample)]
  126. self.inplanes = planes * block.expansion
  127. for i in range(1, blocks):
  128. layers.append(block(self.inplanes, planes, groups, reduction))
  129. return nn.Sequential(*layers)
  130. def paramgroup01(self):
  131. return chain(
  132. self.layer0.parameters(),
  133. self.layer1.parameters(),
  134. )
  135. def paramgroup234(self):
  136. return chain(
  137. self.layer2.parameters(),
  138. self.layer3.parameters(),
  139. self.layer4.parameters(),
  140. )
  141. def parameters_classifier(self):
  142. return self.cls.parameters()
  143. def forward(self, x):
  144. x = self.layer0(x)
  145. x = self.layer1(x)
  146. x = self.layer2(x)
  147. x = self.layer3(x)
  148. x = self.layer4(x)
  149. c = self.cls(x)
  150. return c
  151. def get_model():
  152. model = SENet(SEResNeXtBottleneck, [3, 4, 6, 3], groups=32, reduction=16, inplanes=64,
  153. downsample_kernel_size=1, downsample_padding=0)
  154. checkpoint = model_zoo.load_url('http://data.lip6.fr/cadene/pretrainedmodels/se_resnext50_32x4d-a260b3a4.pth')
  155. model.load_state_dict(checkpoint, strict=False)
  156. return model