layers.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from typing import Tuple
  2. import torch
  3. from jaxtyping import Float
  4. from torch import nn
  5. class SepCNV3d(nn.Module):
  6. def __init__(
  7. self,
  8. in_channels: int,
  9. out_channels: int,
  10. kernel_size: Tuple[int, int, int],
  11. stride: int | Tuple[int, int, int] = 1,
  12. padding: int | str = 0,
  13. bias: bool = False,
  14. ):
  15. super(SepCNV3d, self).__init__()
  16. self.depthwise = nn.Conv3d(
  17. in_channels,
  18. out_channels,
  19. kernel_size,
  20. groups=out_channels,
  21. padding=padding,
  22. bias=bias,
  23. stride=stride,
  24. )
  25. def forward(self, x: Float[torch.Tensor, "N C D H W"]):
  26. x = self.depthwise(x)
  27. return x
  28. class SplitCNVBlock(nn.Module):
  29. def __init__(
  30. self,
  31. in_channels: int,
  32. mid_channels: int,
  33. out_channels: int,
  34. split_dim: int,
  35. drop_rate: float,
  36. ):
  37. super(SplitCNVBlock, self).__init__()
  38. self.split_dim = split_dim
  39. # Build both branches once here. Previously these Sequentials were
  40. # (re)assigned to ``self`` inside forward(), which registered
  41. # ``leftblock``/``rightblock`` as submodules at runtime and duplicated
  42. # their parameters into the state_dict. A freshly constructed model (no
  43. # forward yet) lacked those keys, so a strict load_state_dict of a trained
  44. # checkpoint failed with "Unexpected key(s)" at evaluation time.
  45. self.leftblock = nn.Sequential(
  46. SepCNVBlock(
  47. in_channels // 2, mid_channels // 2, (3, 4, 3), droprate=drop_rate
  48. ),
  49. SepCNVBlock(
  50. mid_channels // 2, out_channels // 2, (3, 4, 3), droprate=drop_rate
  51. ),
  52. )
  53. self.rightblock = nn.Sequential(
  54. SepCNVBlock(
  55. in_channels // 2, mid_channels // 2, (3, 4, 3), droprate=drop_rate
  56. ),
  57. SepCNVBlock(
  58. mid_channels // 2, out_channels // 2, (3, 4, 3), droprate=drop_rate
  59. ),
  60. )
  61. def forward(self, x: Float[torch.Tensor, "N C D H W"]):
  62. left, right = torch.tensor_split(x, 2, dim=self.split_dim)
  63. left = self.leftblock(left)
  64. right = self.rightblock(right)
  65. return torch.cat((left, right), dim=self.split_dim)
  66. class MidFlowBlock(nn.Module):
  67. def __init__(self, channels: int, drop_rate: float):
  68. super(MidFlowBlock, self).__init__()
  69. self.cnv1 = CNVBlock(
  70. channels, channels, (3, 3, 3), droprate=drop_rate, padding="same"
  71. )
  72. self.cnv2 = CNVBlock(
  73. channels, channels, (3, 3, 3), droprate=drop_rate, padding="same"
  74. )
  75. self.cnv3 = CNVBlock(
  76. channels, channels, (3, 3, 3), droprate=drop_rate, padding="same"
  77. )
  78. self.block = nn.Sequential(self.cnv1, self.cnv2, self.cnv3)
  79. #self.block = self.cnv1
  80. def forward(self, x: Float[torch.Tensor, "N C D H W"]):
  81. a = nn.ELU()(self.block(x) + x)
  82. return a
  83. class CNVBlock(nn.Module):
  84. def __init__(
  85. self,
  86. in_channels: int,
  87. out_channels: int,
  88. kernel_size: Tuple[int, int, int],
  89. stride: Tuple[int, int, int] = (1, 1, 1),
  90. padding: str = "valid",
  91. droprate: float = 0.0,
  92. pool: bool = False,
  93. ):
  94. super(CNVBlock, self).__init__()
  95. self.cnv = nn.Conv3d(in_channels, out_channels, kernel_size, stride, padding)
  96. self.norm = nn.BatchNorm3d(out_channels)
  97. self.elu = nn.ELU()
  98. self.dropout = nn.Dropout(droprate)
  99. if pool:
  100. self.maxpool = nn.MaxPool3d(3, stride=2)
  101. else:
  102. self.maxpool = None
  103. def forward(self, x: Float[torch.Tensor, "N C D H W"]):
  104. a = self.cnv(x)
  105. a = self.norm(a)
  106. a = self.elu(a)
  107. if self.maxpool:
  108. a = self.maxpool(a)
  109. a = self.dropout(a)
  110. return a
  111. class FullConnBlock(nn.Module):
  112. def __init__(self, in_channels: int, out_channels: int, droprate: float = 0.0):
  113. super(FullConnBlock, self).__init__()
  114. self.dense = nn.Linear(in_channels, out_channels)
  115. self.norm = nn.BatchNorm1d(out_channels)
  116. self.elu = nn.ELU()
  117. self.dropout = nn.Dropout(droprate)
  118. def forward(self, x: Float[torch.Tensor, "N C"]):
  119. x = self.dense(x)
  120. x = self.norm(x)
  121. x = self.elu(x)
  122. x = self.dropout(x)
  123. return x
  124. class SepCNVBlock(nn.Module):
  125. def __init__(
  126. self,
  127. in_channels: int,
  128. out_channels: int,
  129. kernel_size: Tuple[int, int, int],
  130. stride: Tuple[int, int, int] = (1, 1, 1),
  131. padding: str | int = "valid",
  132. droprate: float = 0.0,
  133. pool: bool = False,
  134. ):
  135. super(SepCNVBlock, self).__init__()
  136. self.cnv = SepCNV3d(in_channels, out_channels, kernel_size, stride, padding)
  137. self.norm = nn.BatchNorm3d(out_channels)
  138. self.elu = nn.ELU()
  139. self.dropout = nn.Dropout(droprate)
  140. if pool:
  141. self.maxpool = nn.MaxPool3d(3, stride=2)
  142. else:
  143. self.maxpool = None
  144. def forward(self, x: Float[torch.Tensor, "N C D H W"]):
  145. x = self.cnv(x)
  146. x = self.norm(x)
  147. x = self.elu(x)
  148. if self.maxpool:
  149. x = self.maxpool(x)
  150. x = self.dropout(x)
  151. return x