torch-geopooling 1.0.0rc3__cp39-cp39-macosx_11_0_arm64.whl → 1.1.0__cp39-cp39-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of torch-geopooling might be problematic. Click here for more details.

Binary file
@@ -11,14 +11,17 @@ namespace torch_geopooling {
11
11
 
12
12
  PYBIND11_MODULE(TORCH_EXTENSION_NAME, m)
13
13
  {
14
- m.def("quad_pool2d", &quad_pool2d);
15
- m.def("quad_pool2d_backward", &quad_pool2d_backward);
14
+ m.def("avg_quad_pool2d", &avg_quad_pool2d);
15
+ m.def("avg_quad_pool2d_backward", &avg_quad_pool2d_backward);
16
16
 
17
17
  m.def("max_quad_pool2d", &max_quad_pool2d);
18
18
  m.def("max_quad_pool2d_backward", &max_quad_pool2d_backward);
19
19
 
20
- m.def("avg_quad_pool2d", &avg_quad_pool2d);
21
- m.def("avg_quad_pool2d_backward", &avg_quad_pool2d_backward);
20
+ m.def("quad_pool2d", &quad_pool2d);
21
+ m.def("quad_pool2d_backward", &quad_pool2d_backward);
22
+
23
+ m.def("embedding2d", &embedding2d);
24
+ m.def("embedding2d_backward", &embedding2d_backward);
22
25
  }
23
26
 
24
27
 
@@ -0,0 +1,3 @@
1
+ from typing import Final
2
+
3
+ __version__: Final[str] = "1.1.0"
@@ -0,0 +1,2 @@
1
+ from torch_geopooling.functional.embedding import * # noqa
2
+ from torch_geopooling.functional.pooling import * # noqa
@@ -0,0 +1,85 @@
1
+ # Copyright (C) 2024, Yakau Bubnou
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ from typing import Optional, Tuple
17
+
18
+ from torch import Tensor, autograd
19
+ from torch.autograd.function import FunctionCtx
20
+
21
+ import torch_geopooling._C as _C
22
+ from torch_geopooling.tiling import ExteriorTuple
23
+
24
+
25
+ __all__ = ["embedding2d"]
26
+
27
+
28
+ class Function(autograd.Function):
29
+ @staticmethod
30
+ def forward(
31
+ input: Tensor,
32
+ weight: Tensor,
33
+ padding: Tuple[int, int],
34
+ exterior: ExteriorTuple,
35
+ ) -> Tensor:
36
+ return _C.embedding2d(input, weight, padding, exterior)
37
+
38
+ @staticmethod
39
+ def setup_context(ctx: FunctionCtx, inputs: Tuple, outputs: Tuple) -> None:
40
+ input, weight, padding, exterior = inputs
41
+
42
+ ctx.save_for_backward(input, weight)
43
+ ctx.padding = padding
44
+ ctx.exterior = exterior
45
+
46
+ @staticmethod
47
+ def backward(ctx: FunctionCtx, grad: Tensor) -> Tuple[Optional[Tensor], ...]:
48
+ input, weight = ctx.saved_tensors
49
+ grad_weight = _C.embedding2d_backward(grad, input, weight, ctx.padding, ctx.exterior)
50
+ return None, grad_weight, None, None
51
+
52
+
53
+ def embedding2d(
54
+ input: Tensor,
55
+ weight: Tensor,
56
+ *,
57
+ padding: Tuple[int, int] = (0, 0),
58
+ exterior: ExteriorTuple,
59
+ ) -> Tensor:
60
+ """
61
+ Retrieves spatial embeddings from a fixed-size lookup table based on 2D coordinates.
62
+
63
+ This function accepts a list of (x, y) coordinates and retrieves the corresponding
64
+ spatial embeddings from a provided embedding matrix. The embeddings are selected
65
+ based on the input coordinates, with an optional padding to include neighboring cells.
66
+ See :class:`torch_geopooling.nn.Embedding2d` for more details.
67
+
68
+ Args:
69
+ input: A list of 2D coordinates where each coordinate is represented as a tuple (x, y),
70
+ where x is the longitude and y is the latitude.
71
+ weight: A 3D tensor representing the embedding matrix. The first dimension corresponds to
72
+ the maximum possible bucket for the x coordinate, the second dimension corresponds to
73
+ the maximum possible bucket for the y coordinate, and the third dimension corresponds
74
+ to the embedding size.
75
+ padding: The size of the neighborhood to query. Default is 0, meaning only the embedding
76
+ for the exact input coordinate is retrieved.
77
+ exterior: The geometric boundary of the learning space, specified as a tuple (X, Y, W, H),
78
+ where X and Y represent the origin, and W and H represent the width and height of the
79
+ space, respectively.
80
+
81
+ Returns:
82
+ Tensor: The retrieved spatial embeddings corresponding to the input coordinates.
83
+ """
84
+
85
+ return Function.apply(input, weight, padding, exterior)
@@ -0,0 +1,31 @@
1
+ # Copyright (C) 2024, Yakau Bubnou
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ import torch
17
+ from torch_geopooling.functional.embedding import embedding2d
18
+
19
+
20
+ def test_embedding2d() -> None:
21
+ input = torch.rand((100, 2), dtype=torch.float64) * 10.0
22
+ weight = torch.rand((1024, 1024, 3), dtype=torch.float64)
23
+
24
+ result = embedding2d(
25
+ input,
26
+ weight,
27
+ padding=(3, 2),
28
+ exterior=(-10.0, -10.0, 20.0, 20.0),
29
+ )
30
+
31
+ assert result.size() == torch.Size([100, 7, 5, 3])
@@ -271,10 +271,12 @@ class AdaptiveFunction(autograd.Function):
271
271
  weight, input = ctx.saved_tensors
272
272
  tiles, w = cls.sparse_ravel(weight)
273
273
 
274
- grad_weight_out = cls.backward_impl(grad_values, tiles, w, input, ctx.exterior, *ctx.params) # type: ignore
275
- grad_weight_out = cls.sparse_unravel(tiles, grad_weight_out, size=weight.size())
274
+ grad_weight_dense = cls.backward_impl(
275
+ grad_values, tiles, w, input, ctx.exterior, *ctx.params
276
+ ) # type: ignore
277
+ grad_weight_sparse = cls.sparse_unravel(tiles, grad_weight_dense, size=weight.size())
276
278
 
277
- return grad_weight_out.coalesce(), None, None, None, None
279
+ return grad_weight_sparse.coalesce(), None, None, None, None
278
280
 
279
281
  @classmethod
280
282
  def func(
@@ -16,7 +16,8 @@
16
16
  import pytest
17
17
  import torch
18
18
 
19
- from torch_geopooling.functional import (
19
+ from torch_geopooling.functional.pooling import (
20
+ AdaptiveFunction,
20
21
  adaptive_quad_pool2d,
21
22
  adaptive_avg_quad_pool2d,
22
23
  adaptive_max_quad_pool2d,
@@ -26,6 +27,20 @@ from torch_geopooling.functional import (
26
27
  )
27
28
 
28
29
 
30
+ def test_adaptive_function_ravel() -> None:
31
+ size = (2, 2, 2, 1)
32
+ tiles = torch.tensor([[0, 0, 0], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]], dtype=torch.int64)
33
+
34
+ weight = torch.tensor([[1.0], [2.0], [3.0], [4.0], [5.0]], dtype=torch.float64)
35
+
36
+ sparse = AdaptiveFunction.sparse_unravel(tiles, weight, size=size)
37
+ torch.testing.assert_close(sparse.to_dense().to_sparse_coo(), sparse)
38
+
39
+ tiles_out, weight_out = AdaptiveFunction.sparse_ravel(sparse)
40
+ torch.testing.assert_close(tiles_out, tiles)
41
+ torch.testing.assert_close(weight_out, weight)
42
+
43
+
29
44
  @pytest.mark.parametrize(
30
45
  "function",
31
46
  [
@@ -0,0 +1,2 @@
1
+ from torch_geopooling.nn.embedding import * # noqa
2
+ from torch_geopooling.nn.pooling import * # noqa
@@ -0,0 +1,89 @@
1
+ # Copyright (C) 2024, Yakau Bubnou
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ from typing import Union, Tuple, cast
17
+
18
+ import torch
19
+ from torch import Tensor, nn
20
+
21
+ from torch_geopooling import functional as F
22
+ from torch_geopooling.tiling import Exterior, ExteriorTuple
23
+
24
+
25
+ __all__ = [
26
+ "Embedding2d",
27
+ ]
28
+
29
+
30
+ _Exterior = Union[Exterior, ExteriorTuple]
31
+
32
+
33
+ class Embedding2d(nn.Module):
34
+ """
35
+ Retrieves spatial embeddings from a fixed-size lookup table based on 2D coordinates.
36
+
37
+ This module accepts a tensor of (x, y) coordinates and retrieves the corresponding
38
+ spatial embeddings from a provided embedding matrix. The embeddings are selected
39
+ based on the input coordinates, with an optional padding to include neighboring cells.
40
+
41
+ Args:
42
+ manifold: The size of the 2-dimensional embedding in a form (W, H, N), where
43
+ W is a width, H is a height, and N is a feature dimension of the embedding.
44
+ padding: The size of the neighborhood to query. Default is 0, meaning only the embedding
45
+ for the exact input coordinate is retrieved.
46
+ exterior: The geometric boundary of the learning space, specified as a tuple (X, Y, W, H),
47
+ where X and Y represent the origin, and W and H represent the width and height of the
48
+ space, respectively.
49
+
50
+ Shape:
51
+ - Input: :math:`(*, 2)`, where 2 comprises x and y coordinates.
52
+ - Output: :math:`(*, X_{out}, Y_{out}, N)`, where * is the input shape, \
53
+ :math:`N = \\text{manifold[2]}`, and
54
+
55
+ :math:`X_{out} = \\text{padding}[0] \\times 2 + 1`
56
+
57
+ :math:`Y_{out} = \\text{padding}[1] \\times 2 + 1`
58
+
59
+ Examples:
60
+
61
+ >>> # Create an embedding of EPSG:4326 rectangle into 1024x1024 embedding
62
+ >>> # with 3 features in each cell.
63
+ >>> embedding = nn.Embedding2d(
64
+ ... (1024, 1024, 3),
65
+ ... exterior=(-180.0, -90.0, 360.0, 180.0),
66
+ ... padding=(2, 2),
67
+ ... )
68
+ >>> input = torch.rand((100, 2), dtype=torch.float64) * 60.0
69
+ >>> output = embedding(input)
70
+ """
71
+
72
+ def __init__(
73
+ self,
74
+ manifold: Tuple[int, int, int],
75
+ exterior: _Exterior,
76
+ padding: Tuple[int, int] = (0, 0),
77
+ ) -> None:
78
+ super().__init__()
79
+ self.exterior = cast(ExteriorTuple, tuple(map(float, exterior)))
80
+ self.padding = padding
81
+
82
+ self.weight = nn.Parameter(torch.empty(manifold, dtype=torch.float64))
83
+ nn.init.zeros_(self.weight)
84
+
85
+ def extra_repr(self) -> str:
86
+ return "{manifold}, exterior={exterior}, padding={padding}".format(**self.__dict__)
87
+
88
+ def forward(self, input: Tensor) -> Tensor:
89
+ return F.embedding2d(input, self.weight, exterior=self.exterior, padding=self.padding)
@@ -0,0 +1,48 @@
1
+ # Copyright (C) 2024, Yakau Bubnou
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ import pytest
17
+ import torch
18
+ from torch import nn
19
+ from torch.optim import SGD
20
+
21
+ from torch_geopooling.nn.embedding import Embedding2d
22
+
23
+
24
+ def test_embedding2d_optimize() -> None:
25
+ embedding = Embedding2d(
26
+ (2, 2, 1),
27
+ padding=(0, 0),
28
+ exterior=(-180.0, -90.0, 360.0, 180.0),
29
+ )
30
+
31
+ x_true = torch.tensor(
32
+ [[90.0, 45.0], [90.0, -45.0], [-90.0, -45.0], [-90.0, 45.0]], dtype=torch.float64
33
+ )
34
+ y_true = torch.tensor([[10.0], [20.0], [30.0], [40.0]], dtype=torch.float64)
35
+
36
+ optim = SGD(embedding.parameters(), lr=0.1)
37
+ loss_fn = nn.L1Loss()
38
+
39
+ for i in range(10000):
40
+ optim.zero_grad()
41
+
42
+ y_pred = embedding(x_true)
43
+ loss = loss_fn(y_pred[:, 0, 0, :], y_true)
44
+ loss.backward()
45
+
46
+ optim.step()
47
+
48
+ assert pytest.approx(0.0, abs=1e-1) == loss.detach().item()
@@ -91,7 +91,12 @@ class _AdaptiveQuadPool(nn.Module):
91
91
  def initialize_parameters(self) -> None:
92
92
  # The weight for adaptive operation should be sparse, since training operation
93
93
  # results in a dynamic change of the underlying quadtree.
94
- weight_size = (self.max_depth, 1 << self.max_depth, 1 << self.max_depth, self.feature_dim)
94
+ weight_size = (
95
+ self.max_depth + 1,
96
+ 1 << self.max_depth,
97
+ 1 << self.max_depth,
98
+ self.feature_dim,
99
+ )
95
100
  self.weight = nn.Parameter(torch.sparse_coo_tensor(size=weight_size, dtype=torch.float64))
96
101
 
97
102
  @property
@@ -0,0 +1,158 @@
1
+ # Copyright (C) 2024, Yakau Bubnou
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ from typing import Type
17
+
18
+ import pytest
19
+ import torch
20
+ from shapely.geometry import Polygon
21
+ from torch import nn
22
+ from torch.optim import SGD
23
+ from torch.nn import L1Loss
24
+
25
+ from torch_geopooling.nn.pooling import (
26
+ AdaptiveAvgQuadPool2d,
27
+ AdaptiveMaxQuadPool2d,
28
+ AdaptiveQuadPool2d,
29
+ AvgQuadPool2d,
30
+ MaxQuadPool2d,
31
+ QuadPool2d,
32
+ )
33
+
34
+
35
+ @pytest.mark.parametrize(
36
+ "module_class",
37
+ [
38
+ AdaptiveQuadPool2d,
39
+ AdaptiveMaxQuadPool2d,
40
+ AdaptiveAvgQuadPool2d,
41
+ ],
42
+ ids=["id", "max", "avg"],
43
+ )
44
+ def test_adaptive_quad_pool2d_gradient(module_class: Type[nn.Module]) -> None:
45
+ pool = module_class(5, (-180, -90, 360, 180))
46
+
47
+ input = torch.rand((100, 2), dtype=torch.float64) * 90
48
+ y = pool(input)
49
+
50
+ assert pool.weight.grad is None
51
+
52
+ loss_fn = L1Loss()
53
+ loss = loss_fn(y, torch.ones_like(y))
54
+ loss.backward()
55
+
56
+ assert pool.weight.grad is not None
57
+ assert pool.weight.grad.sum().item() == pytest.approx(-1)
58
+
59
+
60
+ def test_adaptive_quad_pool2d_optimize() -> None:
61
+ pool = AdaptiveQuadPool2d(1, (-180, -90, 360, 180), max_depth=1)
62
+
63
+ # Input coordinates are simply centers of the level-1 quads.
64
+ x_true = torch.tensor(
65
+ [[90.0, 45.0], [90.0, -45.0], [-90.0, -45.0], [-90.0, 45.0]], dtype=torch.float64
66
+ )
67
+ y_true = torch.tensor([[10.0], [20.0], [30.0], [40.0]], dtype=torch.float64)
68
+ y_tile = [[1, 1, 1], [1, 1, 0], [1, 0, 0], [1, 0, 1]]
69
+
70
+ optim = SGD(pool.parameters(), lr=0.01)
71
+ loss_fn = nn.L1Loss()
72
+
73
+ for i in range(20000):
74
+ optim.zero_grad()
75
+
76
+ y_pred = pool(x_true)
77
+ loss = loss_fn(y_pred, y_true)
78
+ loss.backward()
79
+
80
+ optim.step()
81
+
82
+ # Ensure that model converged with a small loss.
83
+ assert pytest.approx(0.0, abs=1e-1) == loss.detach().item()
84
+
85
+ # Ensure that weights that pooling operation learned are the same as in the
86
+ # target matrix (y_true).
87
+ weight = pool.weight.to_dense()
88
+
89
+ for i, tile in enumerate(y_tile):
90
+ z, x, y = tile
91
+ expect_weight = y_true[i].item()
92
+ actual_weight = weight[z, x, y].detach().item()
93
+
94
+ assert pytest.approx(expect_weight, abs=1e-1) == actual_weight, f"tile {tile} is wrong"
95
+
96
+
97
+ @pytest.mark.parametrize(
98
+ "module_class",
99
+ [
100
+ QuadPool2d,
101
+ MaxQuadPool2d,
102
+ AvgQuadPool2d,
103
+ ],
104
+ ids=["id", "max", "avg"],
105
+ )
106
+ def test_quad_pool2d_gradient(module_class: Type[nn.Module]) -> None:
107
+ poly = Polygon([(0.0, 0.0), (1.0, 0.0), (1.0, 1.1), (0.0, 1.0)])
108
+ exterior = (0.0, 0.0, 1.0, 1.0)
109
+
110
+ pool = module_class(4, poly, exterior, max_depth=5)
111
+ assert pool.weight.size() == torch.Size([pool.tiles.size(0), 4])
112
+
113
+ input = torch.rand((100, 2), dtype=torch.float64)
114
+ y = pool(input)
115
+
116
+ assert pool.weight.grad is None
117
+
118
+ loss_fn = L1Loss()
119
+ loss = loss_fn(y, torch.ones_like(y))
120
+ loss.backward()
121
+
122
+ assert pool.weight.grad is not None
123
+ assert pool.weight.grad.sum().item() == pytest.approx(-1)
124
+
125
+
126
+ def test_quad_pool2d_optimize() -> None:
127
+ poly = Polygon([(-180, -90), (-180, 90), (180, 90), (180, -90)])
128
+ pool = QuadPool2d(1, poly, (-180, -90, 360, 180), max_depth=1)
129
+
130
+ x_true = torch.tensor(
131
+ [[90.0, 45.0], [90.0, -45.0], [-90.0, -45.0], [-90.0, 45.0]], dtype=torch.float64
132
+ )
133
+ y_true = torch.tensor([[10.0], [20.0], [30.0], [40.0]], dtype=torch.float64)
134
+ y_tile = [(1, 1, 1), (1, 1, 0), (1, 0, 0), (1, 0, 1)]
135
+
136
+ optim = SGD(pool.parameters(), lr=0.01)
137
+ loss_fn = nn.L1Loss()
138
+
139
+ for i in range(20000):
140
+ optim.zero_grad()
141
+
142
+ y_pred = pool(x_true)
143
+ loss = loss_fn(y_pred, y_true)
144
+ loss.backward()
145
+
146
+ optim.step()
147
+
148
+ # Ensure that model converged with a small loss.
149
+ assert pytest.approx(0.0, abs=1e-1) == loss.detach().item()
150
+
151
+ actual_tiles = {}
152
+ for i in range(pool.tiles.size(0)):
153
+ tile = tuple(pool.tiles[i].detach().tolist())
154
+ actual_tiles[tile] = pool.weight[i, 0].detach().item()
155
+
156
+ for tile, expect_weight in zip(y_tile, y_true[:, 0].tolist()):
157
+ actual_weight = actual_tiles[tile]
158
+ assert pytest.approx(expect_weight, abs=1e-1) == actual_weight, f"tile {tile} is wrong"
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: torch-geopooling
3
- Version: 1.0.0rc3
3
+ Version: 1.1.0
4
4
  Summary: The geospatial pooling modules for neural networks in PyTorch
5
5
  Author-email: Yakau Bubnou <girokompass@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -680,7 +680,7 @@ License: GNU GENERAL PUBLIC LICENSE
680
680
 
681
681
  Project-URL: homepage, https://github.com/ybubnov/torch_geopooling
682
682
  Project-URL: source, https://github.com/ybubnov/torch_geopooling
683
- Classifier: Development Status :: 4 - Beta
683
+ Classifier: Development Status :: 5 - Production/Stable
684
684
  Classifier: Intended Audience :: Developers
685
685
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
686
686
  Classifier: Topic :: Scientific/Engineering
@@ -699,17 +699,21 @@ Classifier: Operating System :: MacOS
699
699
  Requires-Python: >=3.9
700
700
  Description-Content-Type: text/markdown
701
701
  License-File: LICENSE
702
- Requires-Dist: shapely >=2.0.0
703
- Requires-Dist: torch <2.3.0,>=2.2.0
702
+ Requires-Dist: shapely>=2.0.0
703
+ Requires-Dist: torch<2.4.0,>=2.3.0
704
704
  Provides-Extra: test
705
- Requires-Dist: pytest >=8.0.0 ; extra == 'test'
706
- Requires-Dist: numpy >=1.4.0 ; extra == 'test'
705
+ Requires-Dist: pytest>=8.0.0; extra == "test"
706
+ Requires-Dist: numpy<2.0.0,>=1.4.0; extra == "test"
707
707
 
708
708
  # Torch Geopooling - The geospatial pooling library for PyTorch
709
709
 
710
710
  The Torch Geopooling library is an extension for PyTorch library that provide extra layers for
711
711
  building geospatial neural networks.
712
712
 
713
+ Here is an example of how you can use modules from Torch Geopooling library to train neural
714
+ networks predicting geospatial features:
715
+ ![example](docs/index.png)
716
+
713
717
  ## Installation
714
718
 
715
719
  The library is distributed as PyPI package, to install that package, execute the following
@@ -0,0 +1,24 @@
1
+ torch_geopooling/_C.cpython-39-darwin.so,sha256=7shxNV1Ja1RaYhY9zASNfM6zQaSMNaGgNJPCjtR60E8,562520
2
+ torch_geopooling/__init__.py,sha256=0o5Lnb5ZcEIRNY9AljwW1ESEmQid79rcbBsDBoMT8aM,60
3
+ torch_geopooling/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ torch_geopooling/return_types.py,sha256=QhIKf_qxpppzuZzUrT-VacfbvZ6zKmSRu-WZOqL8wuE,898
5
+ torch_geopooling/tiling.py,sha256=f1g0Gf__5zIOafZzDkwO62t9OqMDMBEYVtM2HXB5X0Y,2553
6
+ torch_geopooling/transforms.py,sha256=NHPBgx1L4-1745xNO_PvLuvbMH6DWi2rs1ViuRyBQAY,3635
7
+ torch_geopooling/transforms_test.py,sha256=Cqp4VVObBVrc8HQ7uxkpe1EsQ5NxXrCI77BiUqngLXw,1196
8
+ torch_geopooling/__bind__/python_module.cc,sha256=LLI363riung_4LI5ugN7Pm93iuoHDRF7n4Y4RlkzLYk,675
9
+ torch_geopooling/functional/__init__.py,sha256=BCcS22yPWITm37M-EPD-PK6WrS7grikDR8uZdoO8sZ4,118
10
+ torch_geopooling/functional/embedding.py,sha256=ER0KB-G7SoCsWJuNEqXRC_XcLdhqaCpn5OJPpUF9pLc,3337
11
+ torch_geopooling/functional/embedding_test.py,sha256=B5a1MP0rynX01a1RmmTJHZxMi4Y68cQoblw-kQawHJM,1094
12
+ torch_geopooling/functional/pooling.py,sha256=MuJfPW_RC4slgzWBO2ngQIBTzlZXeW7DBqV3ooIOSw4,12060
13
+ torch_geopooling/functional/pooling_test.py,sha256=qBT_WVbwyANolwg7-rE7KimF-bAEDB44guBl4OQuQhE,3005
14
+ torch_geopooling/nn/__init__.py,sha256=fWrhfQu0_KzW7VUesk31Sy3n3Om2c5g5dGA3vrLcCg4,102
15
+ torch_geopooling/nn/embedding.py,sha256=u0H1e_sqFG8ALmnfLpbFwKr_yw-z7MNExmB9-uE0SF0,3317
16
+ torch_geopooling/nn/embedding_test.py,sha256=msUeidL9Xkf3AKCPGQH9SJAhfkS7dyqYRzsH88Pt1uY,1505
17
+ torch_geopooling/nn/pooling.py,sha256=_NnGB45dWTZy4MQokFfmJL3as-EPVU3liwOuAmWbv1Y,14219
18
+ torch_geopooling/nn/pooling_test.py,sha256=AqnkpaQ6LcQxh5bWkuDuBAJ2XiBc-C2zVuUp5hynzBM,4794
19
+ torch_geopooling-1.1.0.dist-info/LICENSE,sha256=jLc4eyvG8hqxH4AdKAjK2DwXoP68qjHiGfq8eP5ubBI,35069
20
+ torch_geopooling-1.1.0.dist-info/METADATA,sha256=SnR-sEl9o7dGaskBb2gk0CNU6AydBsta4ZcxFSpuFu8,44371
21
+ torch_geopooling-1.1.0.dist-info/WHEEL,sha256=_exXVVrX7A7i2-EOwk1kG5BcIkGQg9kfHel4XXV7Pbs,108
22
+ torch_geopooling-1.1.0.dist-info/dependency_links.txt,sha256=JqLDcYHtEaQB51V72n3gAJvRd36bpoPk9qgTbot-Lx4,37
23
+ torch_geopooling-1.1.0.dist-info/top_level.txt,sha256=3geTL2nsLvybdtr1psWIE6h63B1LuyIIyWWv0rDafTk,17
24
+ torch_geopooling-1.1.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: bdist_wheel (0.44.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp39-cp39-macosx_11_0_arm64
5
5
 
@@ -1,85 +0,0 @@
1
- # Copyright (C) 2024, Yakau Bubnou
2
- #
3
- # This program is free software: you can redistribute it and/or modify
4
- # it under the terms of the GNU General Public License as published by
5
- # the Free Software Foundation, either version 3 of the License, or
6
- # (at your option) any later version.
7
- #
8
- # This program is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- # GNU General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU General Public License
14
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
-
16
- from typing import Type
17
-
18
- import pytest
19
- import torch
20
- from shapely.geometry import Polygon
21
- from torch import nn
22
- from torch.nn import L1Loss
23
-
24
- from torch_geopooling.nn import (
25
- AdaptiveAvgQuadPool2d,
26
- AdaptiveMaxQuadPool2d,
27
- AdaptiveQuadPool2d,
28
- AvgQuadPool2d,
29
- MaxQuadPool2d,
30
- QuadPool2d,
31
- )
32
-
33
-
34
- @pytest.mark.parametrize(
35
- "module_class",
36
- [
37
- AdaptiveQuadPool2d,
38
- AdaptiveMaxQuadPool2d,
39
- AdaptiveAvgQuadPool2d,
40
- ],
41
- ids=["id", "max", "avg"],
42
- )
43
- def test_adaptive_quad_pool2d_gradient(module_class: Type[nn.Module]) -> None:
44
- pool = module_class(5, (-180, -90, 360, 180))
45
-
46
- input = torch.rand((100, 2), dtype=torch.float64) * 90
47
- y = pool(input)
48
-
49
- assert pool.weight.grad is None
50
-
51
- loss_fn = L1Loss()
52
- loss = loss_fn(y, torch.ones_like(y))
53
- loss.backward()
54
-
55
- assert pool.weight.grad is not None
56
- assert pool.weight.grad.sum().item() == pytest.approx(-1)
57
-
58
-
59
- @pytest.mark.parametrize(
60
- "module_class",
61
- [
62
- QuadPool2d,
63
- MaxQuadPool2d,
64
- AvgQuadPool2d,
65
- ],
66
- ids=["id", "max", "avg"],
67
- )
68
- def test_quad_pool2d_gradient(module_class: Type[nn.Module]) -> None:
69
- poly = Polygon([(0.0, 0.0), (1.0, 0.0), (1.0, 1.1), (0.0, 1.0)])
70
- exterior = (0.0, 0.0, 1.0, 1.0)
71
-
72
- pool = module_class(4, poly, exterior, max_depth=5)
73
- assert pool.weight.size() == torch.Size([pool.tiles.size(0), 4])
74
-
75
- input = torch.rand((100, 2), dtype=torch.float64)
76
- y = pool(input)
77
-
78
- assert pool.weight.grad is None
79
-
80
- loss_fn = L1Loss()
81
- loss = loss_fn(y, torch.ones_like(y))
82
- loss.backward()
83
-
84
- assert pool.weight.grad is not None
85
- assert pool.weight.grad.sum().item() == pytest.approx(-1)
@@ -1,17 +0,0 @@
1
- torch_geopooling/_C.cpython-39-darwin.so,sha256=oGqtH-KLCmOKFnPLATY_SaZIPlB5l7O3hPpuBlflZV8,518632
2
- torch_geopooling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- torch_geopooling/functional.py,sha256=rZrh30K4IlxG3lGQ1_C8wrL7MKS9yIT-NSEkcM21A_k,12028
4
- torch_geopooling/functional_test.py,sha256=WZ7GePj1f8jp8cxNrnrDoHXnJeEeBUNVnFySPgEDl2I,2406
5
- torch_geopooling/nn.py,sha256=A_pozkqIfjhmOL7BDvTV2bJBv7nXD3Wi8nAlbl_rSEs,14156
6
- torch_geopooling/nn_test.py,sha256=4Aj3CcI8KG0parOyruAHZCCnC51CvSacTZ0AxTs16Gc,2359
7
- torch_geopooling/return_types.py,sha256=QhIKf_qxpppzuZzUrT-VacfbvZ6zKmSRu-WZOqL8wuE,898
8
- torch_geopooling/tiling.py,sha256=f1g0Gf__5zIOafZzDkwO62t9OqMDMBEYVtM2HXB5X0Y,2553
9
- torch_geopooling/transforms.py,sha256=NHPBgx1L4-1745xNO_PvLuvbMH6DWi2rs1ViuRyBQAY,3635
10
- torch_geopooling/transforms_test.py,sha256=Cqp4VVObBVrc8HQ7uxkpe1EsQ5NxXrCI77BiUqngLXw,1196
11
- torch_geopooling/__bind__/python_module.cc,sha256=5K04tRT62XTVsZhY2EE4r4bBTz4mA4IwEkw5adPzo58,576
12
- torch_geopooling-1.0.0rc3.dist-info/LICENSE,sha256=jLc4eyvG8hqxH4AdKAjK2DwXoP68qjHiGfq8eP5ubBI,35069
13
- torch_geopooling-1.0.0rc3.dist-info/METADATA,sha256=e81OTHBrYbB3X4ZdjIKovz-ch5tEywdIMf4_oNNq8co,44199
14
- torch_geopooling-1.0.0rc3.dist-info/WHEEL,sha256=t3aNIuHimB-eyeerOmc50nLML0b4_R6yjydcdcJkGHg,108
15
- torch_geopooling-1.0.0rc3.dist-info/dependency_links.txt,sha256=JqLDcYHtEaQB51V72n3gAJvRd36bpoPk9qgTbot-Lx4,37
16
- torch_geopooling-1.0.0rc3.dist-info/top_level.txt,sha256=3geTL2nsLvybdtr1psWIE6h63B1LuyIIyWWv0rDafTk,17
17
- torch_geopooling-1.0.0rc3.dist-info/RECORD,,