def test_padded_tensor(self):
        x = torch.randn(3, 5, 7, 9, requires_grad=True)
        xs = torch.tensor([[1, 1], [3, 9], [7, 5]])
        layer = MaskImageFromSize(mask_value=-99)
        y = layer(PaddedTensor(x, xs))
        # Expected output
        expected_y = x.clone()
        expected_y[0, :, 1:, :] = -99
        expected_y[0, :, :, 1:] = -99
        expected_y[1, :, 3:, :] = -99
        expected_y[2, :, :, 5:] = -99
        # Check expected output
        torch.testing.assert_allclose(y.data, expected_y)

        # Test backward pass (mask with 0, so that we can sum without masking)
        layer = MaskImageFromSize(mask_value=0)
        y = layer(PaddedTensor(x, xs))
        dx, = torch.autograd.grad([torch.sum(y.data)], [x])
        # Expected output
        expected_dx = torch.ones(3, 5, 7, 9)
        expected_dx[0, :, 1:, :] = 0
        expected_dx[0, :, :, 1:] = 0
        expected_dx[1, :, 3:, :] = 0
        expected_dx[2, :, :, 5:] = 0
        # Check expected output
        torch.testing.assert_allclose(dx, expected_dx)
Beispiel #2
0
def test_padded_tensor_repr():
    sizes = torch.randint(3, size=(2, 3))
    t = PaddedTensor.build(torch.empty(2, 1, 5, 5), sizes)
    assert (
        repr(t) ==
        f"PaddedTensor(data.size()=[2, 1, 5, 5], sizes={sizes.tolist()}, device=cpu)"
    )
def test_backprop(dtype, device, kwargs):
    # Note: this only checks that the gradient w.r.t. all layers is different from zero.
    m = ConvBlock(**kwargs).to(device, dtype=dtype).train()
    # Convert batch input and batch sizes to appropriate type
    x = torch.randn(2,
                    kwargs["in_channels"],
                    17,
                    19,
                    device=device,
                    dtype=dtype)
    xs = torch.tensor([[13, 19], [17, 13]], device=device)

    # Check model for normal tensor inputs
    m.zero_grad()
    cost = m(x).sum()
    cost.backward()
    for n, p in m.named_parameters():
        assert p.grad is not None, f"Parameter {n} does not have a gradient"
        sp = torch.abs(p.grad).sum()
        assert not torch.allclose(
            sp, torch.tensor(0, dtype=dtype)
        ), f"Gradients for parameter {n} are close to 0 ({sp:g})"

    # Check model for padded tensor inputs
    m.zero_grad()
    cost = padded_cost_function(m(PaddedTensor(x, xs)))
    cost.backward()
    for n, p in m.named_parameters():
        assert p.grad is not None, f"Parameter {n} does not have a gradient"
        sp = torch.abs(p.grad).sum()
        assert not torch.allclose(
            sp, torch.tensor(0, dtype=dtype)
        ), f"Gradients for parameter {n} are close to 0 ({sp:g})"
 def test_output_size_padded_tensor(self):
     m = ConvBlock(4, 5, kernel_size=3, stride=1, dilation=1, poolsize=2)
     x = torch.randn(3, 4, 11, 13)
     y = m(PaddedTensor(x, torch.tensor([[11, 13], [10, 12], [3, 2]])))
     self.assertEqual(
         [[11 // 2, 13 // 2], [10 // 2, 12 // 2], [3 // 2, 2 // 2]],
         y.sizes.tolist())
 def test_output_size_dilation(self):
     # Note: padding should be added automatically to have the same output size
     m = ConvBlock(4, 5, dilation=3)
     x = torch.randn(1, 4, 11, 13)
     y = m(PaddedTensor(x, torch.tensor([[11, 13]])))
     self.assertEqual([[11, 13]], y.sizes.tolist())
     self.assertEqual([11, 13], list(y.data.size())[2:])
Beispiel #6
0
    def forward(self, x: Union[Tensor,
                               PaddedTensor]) -> Union[Tensor, PaddedTensor]:
        x, xs = (x.data, x.sizes) if isinstance(x, PaddedTensor) else (x, None)
        assert x.size(1) == self.in_channels, (
            f"Input image depth ({x.size(1)}) does not match the "
            f"expected ({self.in_channels})")

        if self.dropout and 0.0 < self.dropout < 1.0:
            x = F.dropout(x, p=self.dropout, training=self.training)

        x = self.conv(x)
        if self.use_masks:
            x = mask_image_from_size(x, batch_sizes=xs, mask_value=0)

        if self.batchnorm:
            x = self.batchnorm(x)

        if self.activation:
            x = self.activation(x)

        if self.use_masks:
            x = mask_image_from_size(x, batch_sizes=xs, mask_value=0)

        if self.pool:
            x = self.pool(x)

        return (x if xs is None else PaddedTensor.build(
            x, self.get_batch_output_size(xs)))
Beispiel #7
0
 def test_padded_tensor(self):
     x = torch.randn(4, 16, 48, 32, requires_grad=True)
     xs = torch.tensor([[30, 30], [40, 32], [10, 32], [48, 10]])
     x = PaddedTensor(x, xs)
     layer = ResnetConv2dBlock(16, 32)
     y = layer(x)
     self.assertEqual((4, 32, 48, 32), y.data.size())
     self.assertTrue(torch.equal(xs, y.sizes))
 def forward(self, x):
     x, xs = (x.data, x.sizes) if isinstance(x, PaddedTensor) else (x, None)
     y = self._func(batch_input=x,
                    output_sizes=self.output_sizes,
                    batch_sizes=xs)
     if xs is None or self._fixed_size:
         return y
     ys = xs.clone()
     dim = int(self.output_sizes[0] is None)
     ys[:, dim] = self.output_sizes[dim]
     return PaddedTensor.build(y, ys)
    def test_forward_padded_tensor(self, name, block, output_dim,
                                   extra_groups):
        del name  # not used
        options = resnet.ResnetOptions(
            block=block,
            input_channels=1,
            layers=(1, 1, 1, 1),  # Fewer layers/block to be faster.
            stride=(1, 2, 1, 1),
            width_per_group=4,  # Fewer units/group to be faster.
            norm_layer=None,  # No normalization to be faster.
        )
        net = resnet.ResnetConv(options)
        input_sizes = torch.tensor([[19, 37], [19, 17], [11, 9], [17, 37]],
                                   dtype=torch.int64)
        y = net(PaddedTensor(data=torch.randn(4, 1, 19, 37),
                             sizes=input_sizes))
        self.assertIsInstance(y, PaddedTensor)
        self.assertEqual(y.data.size(), (4, output_dim, 3, 5))
        expected_sizes = np.asarray([[3, 5], [3, 3], [2, 2], [3, 5]],
                                    dtype=np.int64)
        np.testing.assert_array_equal(y.sizes.numpy(), expected_sizes)

        options = resnet.ResnetOptions(
            block=block,
            input_channels=1,
            root_kernel=3,
            layers=(1, 2, 1, 1),  # Fewer layers/block to be faster.
            stride=(1, 1, 1, 1),
            width_per_group=4,  # Fewer units/group to be faster.
            zero_init_residual=True,
            groups=extra_groups,
            norm_layer=torch.nn.BatchNorm2d,
        )
        net = resnet.ResnetConv(options)
        input_sizes = torch.tensor([[17, 19], [5, 3], [17, 11]],
                                   dtype=torch.int32)
        y = net(PaddedTensor(data=torch.randn(3, 1, 17, 19),
                             sizes=input_sizes))
        self.assertEqual(y.data.size(), (3, extra_groups * output_dim, 5, 5))
        expected_sizes = np.asarray([[5, 5], [2, 1], [5, 3]], dtype=np.int32)
        np.testing.assert_array_equal(y.sizes.numpy(), expected_sizes)
 def forward(self, x):
     if isinstance(x, PaddedTensor):
         x, xs = x.data, x.sizes
         y = mask_image_from_size(
             batch_input=x,
             batch_sizes=xs,
             mask_value=self.mask_value,
             inplace=self.inplace,
         )
         return PaddedTensor(y, xs)
     else:
         return x
Beispiel #11
0
 def test_forward_with_size(self):
     x = torch.tensor(
         [[[[1, 2, 3], [4, 5, 6]]], [[[7, 8, 0], [10, 11, 0]]]],
         dtype=torch.float)
     xs = torch.tensor([[2, 3], [2, 2]])
     m = ImageToSequence(columnwise=True)
     y, ys = m(PaddedTensor(x, xs))
     expected_y = torch.tensor(
         [[[1, 4], [7, 10]], [[2, 5], [8, 11]], [[3, 6], [0, 0]]],
         dtype=torch.float)
     torch.testing.assert_allclose(y, expected_y)
     self.assertEqual(ys, [3, 2])
 def forward(self, x):
     # type: (Union[torch.Tensor, PaddedTensor]) -> torch.Tensor
     x, xs = (x.data, x.sizes) if isinstance(x, PaddedTensor) else (x, None)
     x = self.conv(x)
     if xs is not None:
         xs = size_after_conv(xs)
         x = PaddedTensor(x, xs)
     if self.tpp and self.spp:
         x = torch.cat((self.tpp(x), self.spp(x)), dim=1)
     else:
         x = self.tpp(x) if self.tpp else self.spp(x)
     return self.fc(x)
 def _feed(self, x):
     if isinstance(x, torch.Tensor):
         return x.requires_grad(self._requires_grad).to(self._device)
     elif isinstance(x, PaddedTensor):
         xs = x.sizes.to(self._device)
         x = x.data.requires_grad_(self._requires_grad).to(self._device)
         return PaddedTensor(x, xs)
     elif isinstance(x, PackedSequence):
         xs = x.batch_sizes.to(self._device)
         x = x.data.requires_grad_(self._requires_grad).to(self._device)
         return PackedSequence(x, xs)
     else:
         raise ValueError("Type {!r} is not supported".format(type(x)))
def test_padded_tensor(use_nnutils):
    x = torch.tensor(
        [
            [
                [
                    [1, 2, 3, 4, 5, 6, 7, 8],
                    [9, 10, 11, 12, 13, 14, 15, 16],
                    [17, 18, 19, 20, 21, 22, 23, 24],
                    [25, 26, 27, 28, 29, 30, 31, 32],
                ]
            ]
        ],
        dtype=torch.double,
        requires_grad=True,
    )
    xs = torch.tensor([[3, 4]])
    layer = PyramidMaxPool2d(levels=[1, 2], use_nnutils=use_nnutils)
    y = layer(PaddedTensor(x, xs))
    torch.testing.assert_allclose(
        y, torch.tensor([[20, 10, 12, 18, 20]], dtype=x.dtype)
    )
    torch.autograd.gradcheck(lambda x: layer(PaddedTensor(x, xs)), x)
Beispiel #15
0
 def forward(self, x):
     if isinstance(x, PaddedTensor):
         x, xs = x.data, x.sizes
     else:
         xs = None
     y = F.relu(self.bn1(self.conv1(x)))
     y = self.bn2(self.conv2(y))
     y += self.shortcut(x)
     y = F.relu(y)
     if xs is not None:
         ys = (xs + self.stride - 1) / self.stride
         y = PaddedTensor(y, ys)
     return y
    def _test(self):
        m = ImagePoolingSequencer(sequencer=f"{sequencer}-{poolsize}",
                                  columnwise=columnwise).to(x.device)
        x.requires_grad_()
        y = m(PaddedTensor(x, xs))
        (dx1, ) = torch.autograd.grad(y.data.sum(), (x, ))

        for i, (xk, xsk) in enumerate(zip(x, xs.tolist())):
            xk = xk[:, :xsk[0], :xsk[1]].unsqueeze(0).to(x.device)
            xk.requires_grad_()
            yk = fn(xk,
                    output_size=(poolsize, xsk[1]) if columnwise else
                    (xsk[0], poolsize))
            (dxk, ) = torch.autograd.grad(yk.sum(), (xk, ))
            torch.testing.assert_allclose(dxk, (dx1[i, :, :xsk[0], :xsk[1]]))
Beispiel #17
0
 def test_backward_with_size(self):
     x = torch.tensor(
         [[[[1, 2, 3], [4, 5, 6]]], [[[7, 8, 0], [10, 11, 0]]]],
         dtype=torch.float,
         requires_grad=True,
     )
     xs = torch.tensor([[2, 3], [2, 2]])
     m = ImageToSequence(columnwise=True)
     y, ys = m(PaddedTensor(x, xs))
     dx, = torch.autograd.grad(
         [y[0, :, :].sum() + y[1, :, :].sum() + y[2, 0, :].sum()], [x])
     expected_dx = torch.tensor(
         [[[[1, 1, 1], [1, 1, 1]]], [[[1, 1, 0], [1, 1, 0]]]],
         dtype=torch.float)
     torch.testing.assert_allclose(dx, expected_dx)
Beispiel #18
0
 def feed(self, x):
     if isinstance(x, PaddedTensor):
         x, xs = x.data, x.sizes
     elif isinstance(x, tuple) and len(x) == 2:
         # required because of: https://github.com/pytorch/pytorch/issues/44009
         # can be deleted when we no longer support torch<=1.6.0
         x, xs = x
     else:
         x, xs = x, None
     x = self.view_as_4d(x)  # N x C x H x W
     if xs is not None and self._keep_padded_tensors:
         if xs.size(1) == 3 and not self._keep_channels_in_size:
             xs = xs[:, 1:]
         return PaddedTensor.build(x, xs)
     return x
Beispiel #19
0
 def _feed(self, batch):
     batch = super(ImageFeeder, self)._feed(batch)
     # View image batch as a N-C-H-W
     batch = self._view_as_4d(
         batch.data if isinstance(batch, PaddedTensor) else batch)
     batch.requires_grad_(self._requires_grad)
     if isinstance(batch, PaddedTensor) and self._keep_padded_tensors:
         xs = batch.sizes
         # Ensure that the size tensor is the expected
         if xs.dim() != 2 or (xs.size(1) != 2 and xs.size(1) != 3):
             raise ValueError("Size tensor in PaddedTensor has not an "
                              "expected shape: {!r}".format(xs.size()))
         if xs.size(1) == 3 and not self._keep_channels_in_size:
             xs = xs[:, 1:]
         return PaddedTensor(batch, xs)
     return batch
 def _run_test_padded_tensor(self, use_nnutils):
     x = torch.tensor(
         [[[
             [1, 2, 3, 4, 5, 6, 7, 8],
             [9, 10, 11, 12, 13, 14, 15, 16],
             [17, 18, 19, 20, 21, 22, 23, 24],
             [25, 26, 27, 28, 29, 30, 31, 32],
         ]]],
         dtype=torch.float,
         requires_grad=True,
     )
     xs = torch.tensor([[3, 4]])
     layer = PyramidMaxPool2d(levels=[1, 2], use_nnutils=use_nnutils)
     y = layer(PaddedTensor(x, xs))
     torch.testing.assert_allclose(
         y, torch.tensor([[20, 10, 12, 18, 20]], dtype=torch.float))
Beispiel #21
0
    def _feed(self, x):
        x = super(ImageFeeder, self)._feed(x)
        # View image batch as a N-C-H-W
        x, xs = (x.data, x.sizes) if isinstance(x, PaddedTensor) else (x, None)
        x = self._view_as_4d(x)
        x.requires_grad_(self._requires_grad)

        if xs is not None and self._keep_padded_tensors:
            # Ensure that the size tensor is the expected
            if xs.dim() != 2 or (xs.size(1) != 2 and xs.size(1) != 3):
                raise ValueError(
                    "Size tensor in PaddedTensor has not an "
                    "expected shape: {!r}".format(xs.size())
                )
            if xs.size(1) == 3 and not self._keep_channels_in_size:
                xs = xs[:, 1:]
            return PaddedTensor(x, xs)
        else:
            return x
Beispiel #22
0
    def forward(self, x):
        x, xs = (x.data, x.sizes) if isinstance(x, PaddedTensor) else (x, None)
        assert x.size(1) == self._options.input_channels, (
            f"Input image depth ({x.size(1)}) does not match "
            f"the expected ({self._options.input_channels})")

        x = self.conv1(x)
        if self.bn1 is not None:
            x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)

        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        if xs is None:
            return x
        return PaddedTensor.build(x, self.get_output_batch_size(xs))
Beispiel #23
0
 def test_forward_backward_packed(self):
     x = torch.tensor(
         [[[[1, 2, 3], [4, 5, 6]]], [[[7, 8, 0], [10, 11, 0]]]],
         dtype=torch.float,
         requires_grad=True,
     )
     xs = torch.tensor([[2, 3], [2, 2]])
     m = ImageToSequence(columnwise=True, return_packed=True)
     # Test forward
     y = m(PaddedTensor(x, xs))
     expected_y = torch.tensor([[1, 4], [7, 10], [2, 5], [8, 11], [3, 6]],
                               dtype=torch.float)
     torch.testing.assert_allclose(y.data, expected_y)
     self.assertTrue(torch.equal(torch.tensor([2, 2, 1]), y.batch_sizes))
     # Test backward pass
     dx, = torch.autograd.grad([y.data.sum()], [x])
     expected_dx = torch.tensor(
         [[[[1, 1, 1], [1, 1, 1]]], [[[1, 1, 0], [1, 1, 0]]]],
         dtype=torch.float)
     torch.testing.assert_allclose(dx, expected_dx)
Beispiel #24
0
 def test_forward_padded_tensor(self):
     m = AdaptiveAvgPool2d(output_size=(1, 2))
     x = PaddedTensor(self.x, torch.tensor([[2, 2], [1, 3]]))
     y = m(x)
     expected_y = torch.tensor([
         # n = 0
         [
             # c = 0
             [[3 / 2, 1 / 2]],
             # c = 1
             [[9 / 2, 6 / 2]],
         ],
         # n = 1
         [
             # c = 0
             [[12 / 2, 7 / 2]],
             # c = 1
             [[2 / 2, 6 / 2]],
         ],
     ])
     torch.testing.assert_allclose(y, expected_y)
Beispiel #25
0
    def test_masking(self):
        m = ConvBlock(1, 1, activation=None, use_masks=True)
        # Reset parameters so that the operation does nothing
        for name, param in m.named_parameters():
            param.data.zero_()
            if name == "conv.weight":
                param[:, :, 1, 1] = 1

        x = torch.randn(3, 1, 11, 13)
        y = m(PaddedTensor(x, torch.tensor([[11, 13], [10, 12], [3, 2]]))).data

        # Check sample 1
        torch.testing.assert_allclose(x[0, :, :, :], y[0, :, :, :])
        # Check sample 2
        torch.testing.assert_allclose(x[1, :, :10, :12], y[1, :, :10, :12])
        torch.testing.assert_allclose(torch.zeros(1, 1, 13), y[1, :, 10:, :])
        torch.testing.assert_allclose(torch.zeros(1, 11, 1), y[1, :, :, 12:])
        # Check sample 3
        torch.testing.assert_allclose(x[2, :, :3, :2], y[2, :, :3, :2])
        torch.testing.assert_allclose(torch.zeros(1, 8, 13), y[2, :, 3:, :])
        torch.testing.assert_allclose(torch.zeros(1, 11, 11), y[2, :, :, 2:])
    def forward(self, x):
        # type: (Union[Tensor, PaddedTensor]) -> Union[Tensor, PaddedTensor]
        if isinstance(x, PaddedTensor):
            x, xs = x.data, x.sizes
            assert xs.dim() == 2, "PaddedTensor.sizes must be a matrix"
            assert xs.size(1) == 2, (
                "PaddedTensor.sizes must have 2 columns: Height and Width, "
                "{} columns given instead.".format(xs.size(1)))
            assert x.size(0) == xs.size(0), (
                "Number of batch sizes ({}) does not match the number of "
                "samples in the batch {}".format(xs.size(0), x.size(0)))
        else:
            xs = None
        assert x.size(1) == self.in_channels, (
            "Input image depth ({}) does not match the "
            "expected ({})".format(x.size(1), self.in_channels))

        if self.dropout and 0.0 < self.dropout < 1.0:
            x = F.dropout(x, p=self.dropout, training=self.training)

        x = self.conv(x)
        if self.use_masks:
            x = mask_image_from_size(x, batch_sizes=xs, mask_value=0)

        if self.batchnorm:
            x = self.batchnorm(x)

        if self.activation:
            x = self.activation(x)

        if self.use_masks:
            x = mask_image_from_size(x, batch_sizes=xs, mask_value=0)

        if self.pool:
            x = self.pool(x)

        return x if xs is None else PaddedTensor(
            x, self.get_output_batch_size(xs))
def test_padded_tensor(use_nnutils):
    x = torch.tensor(
        [[[
            [1, 2, 3, 4, 5, 6, 7, 8],
            [9, 10, 11, 12, 13, 14, 15, 16],
            [17, 18, 19, 20, 21, 22, 23, 24],
            [25, 26, 27, 28, 29, 30, 31, 32],
        ]]],
        requires_grad=True,
        dtype=torch.float,
    )
    layer = TemporalPyramidMaxPool2d(levels=[1, 2], use_nnutils=use_nnutils)
    y = layer(PaddedTensor(x, torch.tensor([[3, 4]])))
    (dx, ) = torch.autograd.grad([torch.sum(y)], [x])

    # Expected gradient w.r.t. inputs
    expected_dx = torch.zeros(1, 1, 4, 8)
    expected_dx[0, 0, 2, 3] = 2
    expected_dx[0, 0, 2, 1] = 1

    # Check output and gradient w.r.t input
    torch.testing.assert_allclose(y, torch.tensor([[20.0, 18.0, 20.0]]))
    torch.testing.assert_allclose(dx, expected_dx)
 def test_avgpool16(self):
     m = LaiaCRNN(
         3,
         30,
         cnn_num_features=[16, 32, 48, 64],
         cnn_kernel_size=[3, 3, 3, 3],
         cnn_stride=[1, 1, 1, 1],
         cnn_dilation=[1, 1, 1, 1],
         cnn_activation=[torch.nn.ReLU] * 4,
         cnn_poolsize=[2, 2, 2, 0],
         cnn_dropout=[0, 0, 0.2, 0.1],
         cnn_batchnorm=[False, False, True, True],
         image_sequencer="avgpool-16",
         rnn_units=128,
         rnn_layers=4,
         rnn_dropout=0.5,
         lin_dropout=0.5,
         rnn_type=torch.nn.LSTM,
     )
     x = torch.randn(5, 3, 150, 300, requires_grad=True)
     y = m(
         PaddedTensor(
             data=x,
             sizes=torch.tensor(
                 [[128, 300], [150, 290], [70, 200], [122, 200], [16, 20]]
             ),
         )
     )
     y, ys = pad_packed_sequence(y)
     # Check output size
     self.assertEqual(ys.tolist(), [300 // 8, 290 // 8, 200 // 8, 200 // 8, 20 // 8])
     # Check number of parameters
     self.assertEqual(2421982, sum(p.numel() for p in m.parameters()))
     # Check gradient
     dx, = torch.autograd.grad([y.sum()], [x])
     self.assertNotAlmostEqual(0.0, torch.sum(dx).item())
Beispiel #29
0
 def test_forward_padded_tensor(self):
     m = AdaptiveMaxPool2d(output_size=(1, 2))
     x = PaddedTensor(self.x, torch.tensor([[2, 2], [1, 3]]))
     y = m(x)
     expected_y = torch.tensor(
         [
             # n = 0
             [
                 # c = 0
                 [[2, 1]],
                 # c = 1
                 [[6, 5]],
             ],
             # n = 1
             [
                 # c = 0
                 [[8, 8]],
                 # c = 1
                 [[4, 4]],
             ],
         ],
         dtype=self.x.dtype,
     )
     torch.testing.assert_allclose(y, expected_y)
Beispiel #30
0
 def test_output_size_stride(self):
     m = ConvBlock(4, 5, stride=2)
     x = torch.randn(1, 4, 11, 13)
     y = m(PaddedTensor(x, torch.tensor([[11, 13]])))
     self.assertEqual([[11 // 2 + 1, 13 // 2 + 1]], y.sizes.tolist())
     self.assertEqual([11 // 2 + 1, 13 // 2 + 1], list(y.data.size())[2:])