import torch
from torch import nn, Tensor
from ...components import HighwayLayer
from typing import Tuple
__all__ = [
'ConvolutionalLayer', 'CoordConv2D', 'CoordConvolutionalLayer',
'HighwayConvolutionalLayer', 'Flatten', 'Reshape', 'InputNormalization',
'BiasLayer2D'
]
[docs]class ConvolutionalLayer(nn.Sequential):
"""
Simple convolutional layer: input -> conv2d -> activation -> norm 2d
"""
def __init__(
self, in_channels, out_channels,
kernel_size=3, stride=1, padding=0,
bias=False, activation=nn.ReLU, normalization=nn.BatchNorm2d
):
super(ConvolutionalLayer, self).__init__()
self.add_module(
"main",
nn.Sequential(
nn.Conv2d(
in_channels=in_channels,
out_channels=out_channels,
kernel_size=kernel_size,
stride=stride,
padding=padding,
bias=bias
),
activation(),
normalization(num_features=out_channels)
)
)
[docs]class CoordConv2D(nn.Conv2d):
"""
Implement CoordConv
https://arxiv.org/pdf/1807.03247.pdf
"""
def __init__(
self, in_channels, out_channels,
kernel_size, stride=1, padding=0,
dilation=1, groups=1, bias=True, padding_mode='zeros'
):
super(CoordConv2D, self).__init__(
in_channels + 2, out_channels,
kernel_size, stride, padding,
dilation, groups, bias, padding_mode
)
[docs] def forward(self, input):
augmented_input = CoordConv2D.augment_input(input)
return super().forward(augmented_input)
[docs]class CoordConvolutionalLayer(nn.Sequential):
"""
Simple convolutional layer: input -> conv2d -> activation -> batch norm 2d
"""
def __init__(
self, in_channels, out_channels,
kernel_size=3, stride=1, padding=0,
bias=False, activation=nn.ReLU
):
super(CoordConvolutionalLayer, self).__init__()
self.add_module(
"main",
nn.Sequential(
CoordConv2D(
in_channels=in_channels,
out_channels=out_channels,
kernel_size=kernel_size,
stride=stride,
padding=padding,
bias=bias
),
activation(),
nn.BatchNorm2d(num_features=out_channels)
)
)
[docs]class HighwayConvolutionalLayer(HighwayLayer):
"""
Highway layer (for images):
y = T(x) * H(x) + (1 - T(x)) * x
"""
def __init__(self, in_channels, main):
"""
:param in_channels: Number of channels of each input
:param main: The main network H(x). Return output of same number of channels and dimensions
"""
super(HighwayConvolutionalLayer, self).__init__(
in_features=in_channels,
main=main,
gate=ConvolutionalLayer(in_channels, in_channels, 3, padding=1, activation=nn.Sigmoid)
)
[docs]class Flatten(nn.Module):
[docs] def forward(self, input):
return input.view(input.size(0), -1)
[docs]class Reshape(nn.Module):
[docs] def forward(self, input, new_shape):
return input.view(new_shape)
[docs]class BiasLayer2D(nn.Module):
"""
Add a trainable bias vector to input:
y = x + bias
"""
def __init__(self, out_channels: int, init: float=0.0):
super().__init__()
self.bias = nn.Parameter(torch.zeros((out_channels, )) + init, requires_grad=True)
[docs] def forward(self, input: Tensor) -> Tensor: return input + self.bias[None, :, None, None]