Residual basic block (without batchnorm), as in ImpalaCNN Preserves channel number and shape
| 37 | |
| 38 | |
| 39 | class CnnBasicBlock(nn.Module): |
| 40 | """ |
| 41 | Residual basic block (without batchnorm), as in ImpalaCNN |
| 42 | Preserves channel number and shape |
| 43 | """ |
| 44 | |
| 45 | def __init__(self, inchan, scale=1, batch_norm=False): |
| 46 | super().__init__() |
| 47 | self.inchan = inchan |
| 48 | self.batch_norm = batch_norm |
| 49 | s = math.sqrt(scale) |
| 50 | self.conv0 = NormedConv2d(self.inchan, self.inchan, 3, padding=1, scale=s) |
| 51 | self.conv1 = NormedConv2d(self.inchan, self.inchan, 3, padding=1, scale=s) |
| 52 | if self.batch_norm: |
| 53 | self.bn0 = nn.BatchNorm2d(self.inchan) |
| 54 | self.bn1 = nn.BatchNorm2d(self.inchan) |
| 55 | |
| 56 | def residual(self, x): |
| 57 | # inplace should be False for the first relu, so that it does not change the input, |
| 58 | # which will be used for skip connection. |
| 59 | # getattr is for backwards compatibility with loaded models |
| 60 | if getattr(self, "batch_norm", False): |
| 61 | x = self.bn0(x) |
| 62 | x = F.relu(x, inplace=False) |
| 63 | x = self.conv0(x) |
| 64 | if getattr(self, "batch_norm", False): |
| 65 | x = self.bn1(x) |
| 66 | x = F.relu(x, inplace=True) |
| 67 | x = self.conv1(x) |
| 68 | return x |
| 69 | |
| 70 | def forward(self, x): |
| 71 | return x + self.residual(x) |
| 72 | |
| 73 | |
| 74 | class CnnDownStack(nn.Module): |