def test_intersection_with_broadcasting() -> None: box1 = BoxTensor( torch.tensor([[[1, 1], [3, 5]], [[1, 1], [3, 3]]]).float() ) # box_shape (2,2) box2 = BoxTensor(torch.tensor([[2, 0], [6, 2]]).float()) # box_shape (2,) res = BoxTensor(torch.tensor([[[2, 1], [3, 2]], [[2, 1], [3, 2]]]).float()) assert res == hard_intersection(box1, box2) assert res == hard_intersection(box2, box1)
def test_intersection() -> None: box1 = BoxTensor( torch.tensor([[[1, 1], [3, 5]], [[1, 1], [3, 3]]]).float() ) box2 = BoxTensor( torch.tensor([[[2, 0], [6, 2]], [[3, 2], [4, 4]]]).float() ) res = BoxTensor(torch.tensor([[[2, 1], [3, 2]], [[3, 2], [3, 3]]]).float()) assert res == hard_intersection(box1, box2)
def test_shape_validation_during_creation(): tensor = torch.tensor(np.random.rand(3)) with pytest.raises(ValueError): box_tensor = BoxTensor(tensor) tensor = torch.tensor(np.random.rand(3, 11)) with pytest.raises(ValueError): box_tensor = BoxTensor(tensor) tensor = torch.tensor(np.random.rand(3, 3, 3)) with pytest.raises(ValueError): box_tensor = BoxTensor(tensor)
def test_volume(self, inp1: np.ndarray, inp2: np.ndarray, beta: float, log_scale: bool) -> None: inp1[..., 1] = (np.absolute(inp1[..., 1]) + inp1[..., 0]) # make sure Z >z inp2[..., 1] = (np.absolute(inp2[..., 1]) + inp2[..., 0]) # make sure Z >z box1 = BoxTensor(torch.tensor(inp1)) box2 = BoxTensor(torch.tensor(inp2)) hard_volume1 = HardVolume(log_scale=log_scale, beta=beta)(box1) soft_volume1 = SoftVolume(log_scale=log_scale, beta=beta)(box1)
def test_reshape(sample): target_shape, input_data_shape, self_shape, expected = sample box = BoxTensor(torch.tensor(np.random.rand(*input_data_shape))) assert box.box_shape == self_shape if expected == RuntimeError: with pytest.raises(expected): box.box_reshape(target_shape) else: new = box.box_reshape(target_shape) assert new.box_shape == expected
def test_simple_creation() -> None: tensor = torch.tensor(np.random.rand(3, 2, 3)) box_tensor = BoxTensor(tensor) assert ( tensor.data.numpy() == box_tensor.data.numpy()).all() # type: ignore assert isinstance(box_tensor, BoxTensor) tensor = torch.tensor(np.random.rand(2, 10)) box_tensor = BoxTensor(tensor) assert ( tensor.data.numpy() == box_tensor.data.numpy()).all() # type: ignore assert isinstance(box_tensor, BoxTensor)
def test_volume() -> None: box1 = BoxTensor( torch.tensor([[[1, 1], [3, 5]], [[1, 1], [3, 3]]]).float() ) box2 = BoxTensor( torch.tensor([[[2, 0], [6, 2]], [[3, 2], [4, 4]]]).float() ) volume_layer = BesselApproxVolume(log_scale=False) expected1 = torch.tensor([3.490526, 1.4467278]).float() expected2 = torch.tensor([3.490526, 0.7444129]).float() res1 = volume_layer(box1) res2 = volume_layer(box2) assert torch.allclose(res1, expected1, rtol=1e-4) assert torch.allclose(res2, expected2, rtol=1e-4)
def test_log_volume() -> None: box1 = BoxTensor( torch.tensor([[[1, 1], [3, 5]], [[1, 1], [3, 3]]]).float() ) box2 = BoxTensor( torch.tensor([[[2, 0], [6, 2]], [[3, 2], [4, 4]]]).float() ) volume_layer = BesselApproxVolume(log_scale=True) expected1 = torch.tensor([1.25004, 0.36924]).float() expected2 = torch.tensor([1.25004, -0.29517]).float() res1 = volume_layer(box1) res2 = volume_layer(box2) assert torch.allclose(res1, expected1, rtol=1e-4) assert torch.allclose(res2, expected2, rtol=1e-4)
def test_volume() -> None: box1 = BoxTensor( torch.tensor([[[1, 1], [3, 5]], [[1, 1], [3, 3]]]).float() ) box2 = BoxTensor( torch.tensor([[[2, 0], [6, 2]], [[3, 2], [4, 4]]]).float() ) volume_layer = HardVolume(log_scale=False) expected1 = torch.tensor([8, 4]).float() expected2 = torch.tensor([8, 2]).float() res1 = volume_layer(box1) res2 = volume_layer(box2) assert torch.allclose(res1, expected1) assert torch.allclose(res2, expected2)
def test_log_volume() -> None: box1 = BoxTensor( torch.tensor([[[1, 1], [3, 5]], [[1, 1], [3, 3]]]).float() ) box2 = BoxTensor( torch.tensor([[[2, 0], [6, 2]], [[3, 2], [4, 4]]]).float() ) volume_layer = HardVolume(log_scale=True) expected1 = torch.tensor([2.07944, 1.3862]).float() expected2 = torch.tensor([2.07944, 0.69314]).float() res1 = volume_layer(box1) res2 = volume_layer(box2) assert torch.allclose(res1, expected1, rtol=1e-4) assert torch.allclose(res2, expected2, rtol=1e-4)
def test_creation_from_zZ(): shape = (3, 1, 5) z = torch.tensor(np.random.rand(*shape)) Z = z + torch.tensor(np.random.rand(*shape)) box = BoxTensor.from_zZ(z, Z) assert box.z.shape == (3, 1, 5) assert box.data is None
def test_creation_from_vector(): shape = (3, 1, 5) z = torch.tensor(np.random.rand(*shape)) delta = torch.tensor(np.random.rand(*shape)) v = torch.cat((z, z + delta.abs()), dim=-1) box = BoxTensor.from_vector(v) assert box.Z.shape == (3, 1, 5)
def test_intersection_with_broadcasting_module2() -> None: box1 = BoxTensor( torch.tensor([[[[1, 1], [4, 4]], [[2, 2], [5, 5]]]]).float() ) # box_shape (1, 2,2) assert box1.box_shape == (1, 2, 2) box2 = BoxTensor( torch.tensor([[[[3, 3], [7, 6]]], [[[1, 3], [3, 4]]]]).float() ) assert box2.box_shape == (2, 1, 2) expected = BoxTensor( torch.tensor( [ [[[3, 3], [4, 4]], [[3, 3], [5, 5]]], [[[1, 3], [3, 4]], [[2, 3], [3, 4]]], ] ).float() ) assert expected == HardIntersection()(box1, box2) box1 = BoxTensor( torch.tensor([[[[1, 1], [4, 4]], [[2, 2], [5, 5]]]]).float() ) # box_shape (1, 2,2) assert box1.box_shape == (1, 2, 2) box2 = BoxTensor( torch.tensor([[[[3, 3], [7, 6]]], [[[1, 3], [3, 4]]]]).float() ) assert box2.box_shape == (2, 1, 2) expected = BoxTensor( torch.tensor( [ [[[3, 3], [4, 4]], [[3, 3], [5, 5]]], [[[1, 3], [3, 4]], [[2, 3], [3, 4]]], ] ).float() ) assert expected == HardIntersection()(box2, box1)
def hard_intersection_pooler( boxes: BoxTensor, mask: torch.BoolTensor = None, dim: int = 0, keepdim: bool = False, ) -> BoxTensor: box_z = boxes.z box_Z = boxes.Z if mask is not None: box_z[mask] -= float("inf") box_Z[mask] += float("inf") z = torch.max(box_z, dim=dim, keepdim=keepdim)[0] Z = torch.min(box_Z, dim=dim, keepdim=keepdim)[0] return boxes.like_this_from_zZ(z, Z)
def test_broadcasting(sample): target_shape, input_data_shape, self_shape, expected = sample box = BoxTensor(torch.tensor(np.random.rand(*input_data_shape))) assert box.box_shape == self_shape if isinstance(expected, tuple): box.broadcast(target_shape) assert box.box_shape == expected else: with pytest.raises(expected): box.broadcast(target_shape)
def gumbel_intersection_pooler( boxes: BoxTensor, beta: float = 1e-4, mask: torch.BoolTensor = None, dim: int = 0, keepdim: bool = False, ) -> BoxTensor: box_z = boxes.z box_Z = boxes.Z if mask is not None: box_z[mask] -= float("inf") box_Z[mask] += float("inf") z = beta * torch.logsumexp(box_z / beta, dim=dim, keepdim=keepdim) Z = -beta * torch.logsumexp(-box_Z / beta, dim=dim, keepdim=keepdim) return BoxTensor.from_zZ(z, Z)
def bag_of_boxes_pooler( boxes: BoxTensor, mask: Optional[torch.BoolTensor] = None, weights: Optional[torch.Tensor] = None, dim: int = 0, keepdim: bool = False, ) -> BoxTensor: box_z = boxes.z box_Z = boxes.Z if weights is None: weights = torch.ones_like(box_z) if mask is not None: weights = weights * mask denominator = torch.sum(weights, dim=dim, keepdim=keepdim) z = torch.sum(box_z * weights, dim=dim, keepdim=keepdim) / (denominator + 1e-14) Z = torch.sum(box_Z * weights, dim=dim, keepdim=keepdim) / (denominator + 1e-14) return boxes.like_this_from_zZ(z, Z)
def test_creation_from_center(): c = torch.tensor([[0.1, 0.2], [0.2, 0.1]]) delta = 0.1 box = BoxTensor.from_center_vector(c, delta=delta) assert torch.allclose(box.z, c - delta / 2.0) assert torch.allclose(box.Z, c + delta / 2.0)
from box_embeddings.modules.pooling.bag_of_boxes import BagOfBoxesBoxPooler from box_embeddings.parameterizations.box_tensor import BoxTensor import hypothesis from hypothesis.strategies import sampled_from, just import torch import pytest @hypothesis.given( others=sampled_from([ { "box": BoxTensor( torch.tensor([[[1, 1], [3, 5]], [[2, 0], [6, 2]]]).float()), "weights": None, "mask": None, "keepdim": True, "dim": 0, "expected": BoxTensor( torch.tensor([[3.0 / 2.0, 1.0 / 2.0], [9.0 / 2.0, 7.0 / 2.0]])), }, { "box": BoxTensor( torch.tensor([[[1, 1], [3, 5]], [[2, 0], [6, 2]]]).float()),