subsampling_without_posenc.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. # Copyright 2020 Emiru Tsunoo
  2. # Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
  3. """Subsampling layer definition."""
  4. import math
  5. import torch
  6. class Conv2dSubsamplingWOPosEnc(torch.nn.Module):
  7. """Convolutional 2D subsampling.
  8. Args:
  9. idim (int): Input dimension.
  10. odim (int): Output dimension.
  11. dropout_rate (float): Dropout rate.
  12. kernels (list): kernel sizes
  13. strides (list): stride sizes
  14. """
  15. def __init__(self, idim, odim, dropout_rate, kernels, strides):
  16. """Construct an Conv2dSubsamplingWOPosEnc object."""
  17. assert len(kernels) == len(strides)
  18. super().__init__()
  19. conv = []
  20. olen = idim
  21. for i, (k, s) in enumerate(zip(kernels, strides)):
  22. conv += [
  23. torch.nn.Conv2d(1 if i == 0 else odim, odim, k, s),
  24. torch.nn.ReLU(),
  25. ]
  26. olen = math.floor((olen - k) / s + 1)
  27. self.conv = torch.nn.Sequential(*conv)
  28. self.out = torch.nn.Linear(odim * olen, odim)
  29. self.strides = strides
  30. self.kernels = kernels
  31. def forward(self, x, x_mask):
  32. """Subsample x.
  33. Args:
  34. x (torch.Tensor): Input tensor (#batch, time, idim).
  35. x_mask (torch.Tensor): Input mask (#batch, 1, time).
  36. Returns:
  37. torch.Tensor: Subsampled tensor (#batch, time', odim),
  38. where time' = time // 4.
  39. torch.Tensor: Subsampled mask (#batch, 1, time'),
  40. where time' = time // 4.
  41. """
  42. x = x.unsqueeze(1) # (b, c, t, f)
  43. x = self.conv(x)
  44. b, c, t, f = x.size()
  45. x = self.out(x.transpose(1, 2).contiguous().view(b, t, c * f))
  46. if x_mask is None:
  47. return x, None
  48. for k, s in zip(self.kernels, self.strides):
  49. x_mask = x_mask[:, :, : -k + 1 : s]
  50. return x, x_mask