Compute convolution module. Args: x (torch.Tensor): Input tensor (#batch, time, channels). mask_pad (torch.Tensor): used for batch padding (#batch, 1, time), (0, 0, 0) means fake mask. cache (torch.Tensor): left context cache, it is only
(
self,
x: torch.Tensor,
mask_pad: torch.Tensor = torch.ones((0, 0, 0), dtype=torch.bool),
cache: torch.Tensor = torch.zeros((0, 0, 0)),
)
| 73 | self.activation = activation |
| 74 | |
| 75 | def forward( |
| 76 | self, |
| 77 | x: torch.Tensor, |
| 78 | mask_pad: torch.Tensor = torch.ones((0, 0, 0), dtype=torch.bool), |
| 79 | cache: torch.Tensor = torch.zeros((0, 0, 0)), |
| 80 | ) -> Tuple[torch.Tensor, torch.Tensor]: |
| 81 | """Compute convolution module. |
| 82 | Args: |
| 83 | x (torch.Tensor): Input tensor (#batch, time, channels). |
| 84 | mask_pad (torch.Tensor): used for batch padding (#batch, 1, time), |
| 85 | (0, 0, 0) means fake mask. |
| 86 | cache (torch.Tensor): left context cache, it is only |
| 87 | used in causal convolution (#batch, channels, cache_t), |
| 88 | (0, 0, 0) meas fake cache. |
| 89 | Returns: |
| 90 | torch.Tensor: Output tensor (#batch, time, channels). |
| 91 | """ |
| 92 | # exchange the temporal dimension and the feature dimension |
| 93 | x = x.transpose(1, 2) # (#batch, channels, time) |
| 94 | |
| 95 | # mask batch padding |
| 96 | if mask_pad.size(2) > 0: # time > 0 |
| 97 | x.masked_fill_(~mask_pad, 0.0) |
| 98 | |
| 99 | if self.lorder > 0: |
| 100 | if cache.size(2) == 0: # cache_t == 0 |
| 101 | x = nn.functional.pad(x, (self.lorder, 0), "constant", 0.0) |
| 102 | else: |
| 103 | assert cache.size(0) == x.size(0) # equal batch |
| 104 | assert cache.size(1) == x.size(1) # equal channel |
| 105 | x = torch.cat((cache, x), dim=2) |
| 106 | assert x.size(2) > self.lorder |
| 107 | new_cache = x[:, :, -self.lorder :] |
| 108 | else: |
| 109 | # It's better we just return None if no cache is required, |
| 110 | # However, for JIT export, here we just fake one tensor instead of |
| 111 | # None. |
| 112 | new_cache = torch.zeros((0, 0, 0), dtype=x.dtype, device=x.device) |
| 113 | |
| 114 | # GLU mechanism |
| 115 | x = self.pointwise_conv1(x) # (batch, 2*channel, dim) |
| 116 | x = nn.functional.glu(x, dim=1) # (batch, channel, dim) |
| 117 | |
| 118 | # 1D Depthwise Conv |
| 119 | x = self.depthwise_conv(x) |
| 120 | if self.use_layer_norm: |
| 121 | x = x.transpose(1, 2) |
| 122 | x = self.activation(self.norm(x)) |
| 123 | if self.use_layer_norm: |
| 124 | x = x.transpose(1, 2) |
| 125 | x = self.pointwise_conv2(x) |
| 126 | # mask batch padding |
| 127 | if mask_pad.size(2) > 0: # time > 0 |
| 128 | x.masked_fill_(~mask_pad, 0.0) |
| 129 | |
| 130 | return x.transpose(1, 2), new_cache |
| 131 | |
| 132 |
nothing calls this directly
no outgoing calls
no test coverage detected