def test_mask_conv_1d_out_lens(data, conv1d: torch.nn.Conv1d) -> None: """Ensures out_lens returns correct output sequence lengths.""" # PyTorch conv1d requires input size to be greater than effective kernel # size. Force this to be True. effective_ks = conv1d.dilation[0] * (conv1d.kernel_size[0] - 1) + 1 padding = data.draw(st.integers(0, effective_ks + 100)) seq_lens = data.draw( st.lists( elements=st.integers(max(0, effective_ks - padding), 256), min_size=0, max_size=32, )) exp = [] for seq_len in seq_lens: out = conv1d(torch.empty([1, conv1d.in_channels, seq_len + padding])) exp.append(out.size(2)) act = list( out_lens( seq_lens=torch.tensor(seq_lens), kernel_size=conv1d.kernel_size[0], stride=conv1d.stride[0], dilation=conv1d.dilation[0], padding=padding, )) assert exp == act
def test_mask_conv_output_size_and_seq_lens( mask_conv1d_input: Tuple[MaskConv1d, Tuple[torch.Tensor, torch.Tensor]] ) -> None: """Ensures the MaskConv1d output size and seq_len values are correct.""" mask_conv1d, inputs = mask_conv1d_input batch, channels, seq_len = inputs[0].size() out_tensor, out_seq_lens = mask_conv1d(inputs) out_batch, out_channels, out_seq_len = out_tensor.size() assert out_batch == len(out_seq_lens) == batch assert out_channels == mask_conv1d.out_channels # test out_seq_len dimension of tensor output and set padding value ready # for testing out_seq_lens if mask_conv1d._padding_mode == PaddingMode.NONE: padding = (0, 0) # out_lens function returns correct expected length if the tests pass exp_len = out_lens( seq_lens=torch.tensor(seq_len), kernel_size=mask_conv1d.kernel_size[0], stride=mask_conv1d.stride[0], dilation=mask_conv1d.dilation[0], padding=0, ).item() assert out_seq_len == exp_len elif mask_conv1d._padding_mode == PaddingMode.SAME: padding = pad_same( length=seq_len, kernel_size=mask_conv1d.kernel_size[0], stride=mask_conv1d.stride[0], dilation=mask_conv1d.dilation[0], ) # by definition of SAME padding assert out_seq_len == math.ceil(float(seq_len) / mask_conv1d.stride[0]) else: raise ValueError(f"unknown PaddingMode {mask_conv1d._padding_mode}") # test out_seq_lens exp_out_seq_lens = out_lens( seq_lens=inputs[1], kernel_size=mask_conv1d.kernel_size[0], stride=mask_conv1d.stride[0], dilation=mask_conv1d.dilation[0], padding=sum(padding), ) assert torch.all(out_seq_lens == exp_out_seq_lens)
def _build_cnn(conv_blocks, input_features: int, input_channels: int): act_dims = 4 # batch, channels, features, seq_len layers = [] for conv_block in conv_blocks: convnd_str = conv_block.WhichOneof("convnd") if convnd_str == "conv1d": if act_dims == 4: layers.append(Conv2dTo1d()) act_dims = 3 input_channels *= input_features input_features = 1 conv_cfg = conv_block.conv1d if conv_cfg.padding_mode == conv_layer_pb2.PADDING_MODE.NONE: padding_mode = PaddingMode.NONE elif conv_cfg.padding_mode == conv_layer_pb2.PADDING_MODE.SAME: padding_mode = PaddingMode.SAME layers.append( MaskConv1d( in_channels=input_channels, out_channels=conv_cfg.output_channels, kernel_size=conv_cfg.kernel_time, stride=conv_cfg.stride_time, padding_mode=padding_mode, bias=conv_cfg.bias, )) input_channels = conv_cfg.output_channels elif convnd_str == "conv2d": if act_dims == 3: layers.append(Conv1dTo2d()) act_dims = 4 input_features = input_channels input_channels = 1 conv_cfg = conv_block.conv2d if conv_cfg.padding_mode == conv_layer_pb2.PADDING_MODE.NONE: padding_mode = PaddingMode.NONE input_features = out_lens( torch.tensor([input_features]), kernel_size=conv_cfg.kernel_feature, stride=conv_cfg.stride_feature, dilation=1, padding=0, ).item() elif conv_cfg.padding_mode == conv_layer_pb2.PADDING_MODE.SAME: padding_mode = PaddingMode.SAME input_features = math.ceil(input_features / conv_cfg.stride_feature) layers.append( MaskConv2d( in_channels=input_channels, out_channels=conv_cfg.output_channels, kernel_size=[ conv_cfg.kernel_feature, conv_cfg.kernel_time, ], stride=[conv_cfg.stride_feature, conv_cfg.stride_time], padding_mode=padding_mode, bias=conv_cfg.bias, )) input_channels = conv_cfg.output_channels layers.append( SeqLenWrapper(build_activation(conv_block.activation), torch.nn.Identity())) if act_dims == 3: layers.append(Conv1dTo2d()) input_features = input_channels input_channels = 1 return torch.nn.Sequential(*layers), input_features * input_channels