| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import torch |
| from scaling import ( |
| ActivationBalancer, |
| BasicNorm, |
| DoubleSwish, |
| ScaledConv2d, |
| ScaledLinear, |
| ) |
|
|
|
|
| class Conv2dSubsampling(torch.nn.Module): |
| """Convolutional 2D subsampling (to 1/4 length). |
| |
| Convert an input of shape (N, T, idim) to an output |
| with shape (N, T', odim), where |
| T' = ((T-1)//2 - 1)//2, which approximates T' == T//4 |
| |
| It is based on |
| https://github.com/espnet/espnet/blob/master/espnet/nets/pytorch_backend/transformer/subsampling.py # noqa |
| """ |
|
|
| def __init__( |
| self, |
| in_channels: int, |
| out_channels: int, |
| layer1_channels: int = 8, |
| layer2_channels: int = 32, |
| layer3_channels: int = 128, |
| ) -> None: |
| """ |
| Args: |
| in_channels: |
| Number of channels in. The input shape is (N, T, in_channels). |
| Caution: It requires: T >=7, in_channels >=7 |
| out_channels |
| Output dim. The output shape is (N, ((T-1)//2 - 1)//2, out_channels) |
| layer1_channels: |
| Number of channels in layer1 |
| layer1_channels: |
| Number of channels in layer2 |
| """ |
| assert in_channels >= 7 |
| super().__init__() |
|
|
| self.conv = torch.nn.Sequential( |
| ScaledConv2d( |
| in_channels=1, |
| out_channels=layer1_channels, |
| kernel_size=3, |
| padding=1, |
| ), |
| ActivationBalancer(channel_dim=1), |
| DoubleSwish(), |
| ScaledConv2d( |
| in_channels=layer1_channels, |
| out_channels=layer2_channels, |
| kernel_size=3, |
| stride=2, |
| ), |
| ActivationBalancer(channel_dim=1), |
| DoubleSwish(), |
| ScaledConv2d( |
| in_channels=layer2_channels, |
| out_channels=layer3_channels, |
| kernel_size=3, |
| stride=2, |
| ), |
| ActivationBalancer(channel_dim=1), |
| DoubleSwish(), |
| ) |
| self.out = ScaledLinear( |
| layer3_channels * (((in_channels - 1) // 2 - 1) // 2), out_channels |
| ) |
| |
| |
| |
| self.out_norm = BasicNorm(out_channels, learn_eps=False) |
| |
| self.out_balancer = ActivationBalancer( |
| channel_dim=-1, min_positive=0.45, max_positive=0.55 |
| ) |
|
|
| def forward(self, x: torch.Tensor) -> torch.Tensor: |
| """Subsample x. |
| |
| Args: |
| x: |
| Its shape is (N, T, idim). |
| |
| Returns: |
| Return a tensor of shape (N, ((T-1)//2 - 1)//2, odim) |
| """ |
| |
| x = x.unsqueeze(1) |
| x = self.conv(x) |
| |
| b, c, t, f = x.size() |
| x = self.out(x.transpose(1, 2).contiguous().view(b, t, c * f)) |
| |
| x = self.out_norm(x) |
| x = self.out_balancer(x) |
| return x |
|
|
|
|
| class Conv2dSubsampling2(torch.nn.Module): |
| """Convolutional 2D subsampling (to 1/2 length). |
| |
| Convert an input of shape (N, T, idim) to an output |
| with shape (N, T', odim) where |
| T' = (T - 1) // 2 - 2, which approximates T' == T // 2 |
| """ |
|
|
| def __init__( |
| self, |
| in_channels: int, |
| out_channels: int, |
| layer1_channels: int = 8, |
| layer2_channels: int = 32, |
| layer3_channels: int = 128, |
| ) -> None: |
| assert in_channels >= 7 |
| super().__init__() |
|
|
| self.conv = torch.nn.Sequential( |
| ScaledConv2d( |
| in_channels=1, |
| out_channels=layer1_channels, |
| kernel_size=3, |
| padding=1, |
| ), |
| ActivationBalancer(channel_dim=1), |
| DoubleSwish(), |
| ScaledConv2d( |
| in_channels=layer1_channels, |
| out_channels=layer2_channels, |
| kernel_size=3, |
| stride=2, |
| ), |
| ActivationBalancer(channel_dim=1), |
| DoubleSwish(), |
| ScaledConv2d( |
| in_channels=layer2_channels, |
| out_channels=layer3_channels, |
| kernel_size=3, |
| stride=1, |
| ), |
| ActivationBalancer(channel_dim=1), |
| DoubleSwish(), |
| ) |
| self.out = ScaledLinear( |
| layer3_channels * ((in_channels - 1) // 2 - 2), out_channels |
| ) |
| self.out_norm = BasicNorm(out_channels, learn_eps=False) |
| self.out_balancer = ActivationBalancer( |
| channel_dim=-1, min_positive=0.45, max_positive=0.55 |
| ) |
|
|
| def forward(self, x: torch.Tensor) -> torch.Tensor: |
| x = x.unsqueeze(1) |
| x = self.conv(x) |
| b, c, t, f = x.size() |
| x = self.out(x.transpose(1, 2).contiguous().view(b, t, c * f)) |
| x = self.out_norm(x) |
| x = self.out_balancer(x) |
| return x |
|
|