Source code for enchanter.addons.layers.se_layer
from torch import Tensor
from torch import nn
__all__ = ["SELayer1d", "SELayer2d"]
[docs]class SELayer1d(nn.Module):
"""
Squeeze and Excitation block for time series data.
Paper: `Squeeze-and-Excitation Networks <https://arxiv.org/abs/1709.01507>`_
"""
def __init__(self, in_features: int, reduction: int = 16) -> None:
super(SELayer1d, self).__init__()
reduction_size = max(1, in_features // reduction)
self.avg_pool = nn.AdaptiveAvgPool1d(1)
self.fc = nn.Sequential(
nn.Linear(in_features, reduction_size, bias=False),
nn.ReLU(inplace=True),
nn.Linear(reduction_size, in_features, bias=False),
nn.Sigmoid(),
)
[docs] def forward(self, x: Tensor) -> Tensor:
"""
Forward pass
Args:
x: input data [N, C, L]
Returns:
"""
b, c, _ = x.shape
y = self.avg_pool(x).view(b, c)
y = self.fc(y).view(b, c, 1)
scaling = x * y.expand_as(x)
return scaling
[docs]class SELayer2d(nn.Module):
"""
Squeeze and Excitation block for image data.
Paper: `Squeeze-and-Excitation Networks <https://arxiv.org/abs/1709.01507>`_
"""
def __init__(self, in_features: int, reduction: int = 16) -> None:
super(SELayer2d, self).__init__()
reduction_size = max(1, in_features // reduction)
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Sequential(
nn.Linear(in_features, reduction_size, bias=False),
nn.ReLU(inplace=True),
nn.Linear(reduction_size, in_features, bias=False),
nn.Sigmoid(),
)
[docs] def forward(self, x: Tensor) -> Tensor:
"""
Forward pass
Args:
x: input data [N, C, H, W]
Returns:
"""
b, c, _, _ = x.shape
y = self.avg_pool(x).view(b, c)
y = self.fc(y).view(b, c, 1, 1)
scaling = x * y.expand_as(x)
return scaling