Bases: BaseTransform
Applies Laplacian-eigenvector-modulated multiplicative noise to the
z-coordinate of each node.
This transform samples a linear combination of Laplacian eigenvectors,
rescales it to lie in the range [-max_noise, max_noise], and
multiplies each node's z-coordinate with this noise coefficient.
If the Laplacian positional encoding is missing or has fewer dimensions
than requested, it will be recomputed.
Parameters:
| Name |
Type |
Description |
Default |
max_noise
|
float
|
The maximum relative deviation applied to the
z-coordinate. A value of 0.15 means ±15% scaling.
|
required
|
n_eigenvectors
|
int
|
Number of Laplacian eigenvectors to
compute. Defaults to 20.
|
20
|
Example
transform = AddLaplacianZNoise(max_noise=0.1)
data = transform(data)
Source code in src/torch_structure/transforms/laplacian_z_noise.py
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 | class AddLaplacianZNoise(BaseTransform):
r"""
Applies Laplacian-eigenvector-modulated multiplicative noise to the
z-coordinate of each node.
This transform samples a linear combination of Laplacian eigenvectors,
rescales it to lie in the range ``[-max_noise, max_noise]``, and
multiplies each node's z-coordinate with this noise coefficient.
If the Laplacian positional encoding is missing or has fewer dimensions
than requested, it will be recomputed.
Args:
max_noise (float): The maximum relative deviation applied to the
z-coordinate. A value of 0.15 means ±15% scaling.
n_eigenvectors (int, optional): Number of Laplacian eigenvectors to
compute. Defaults to 20.
Example:
>>> transform = AddLaplacianZNoise(max_noise=0.1)
>>> data = transform(data)
"""
def __init__(self, max_noise, n_eigenvectors=20, keep_lpe=False):
super().__init__()
self.max_noise = max_noise
self.n_eigenvectors = n_eigenvectors
self.keep_lpe = keep_lpe
self._add_lpe = torch_geometric.transforms.AddLaplacianEigenvectorPE(
self.n_eigenvectors, attr_name="laplacian_pe", is_undirected=False
)
def forward(self, data):
"""Apply the Laplacian-eigenvector-modulated z-noise to ``data.coords`` in place."""
if not hasattr(data, "coords"):
raise AttributeError("Data object has no attribute 'coords'.")
device = data.coords.device
# Ensure data has the specified number of eigenvectors
compute_lpe = (
not hasattr(data, "laplacian_pe")
or data.laplacian_pe.size(1) < self.n_eigenvectors
)
if compute_lpe:
data = self._add_lpe(data).to(device=device)
coefficients = torch.randn(self.n_eigenvectors, device=device)
laplacian_sum = torch.matmul(
data.laplacian_pe[:, : self.n_eigenvectors], coefficients
)
noise = laplacian_sum * (self.max_noise / laplacian_sum.abs().max())
data.coords[:, 2] = (1 + noise) * data.coords[:, 2]
if not self.keep_lpe and compute_lpe:
del data.laplacian_pe
return data
def __repr__(self):
return (
f"{self.__class__.__name__}(max_noise={self.max_noise}, "
f"n_eigenvectors={self.n_eigenvectors})"
)
|
Apply the Laplacian-eigenvector-modulated z-noise to data.coords in place.
Source code in src/torch_structure/transforms/laplacian_z_noise.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 | def forward(self, data):
"""Apply the Laplacian-eigenvector-modulated z-noise to ``data.coords`` in place."""
if not hasattr(data, "coords"):
raise AttributeError("Data object has no attribute 'coords'.")
device = data.coords.device
# Ensure data has the specified number of eigenvectors
compute_lpe = (
not hasattr(data, "laplacian_pe")
or data.laplacian_pe.size(1) < self.n_eigenvectors
)
if compute_lpe:
data = self._add_lpe(data).to(device=device)
coefficients = torch.randn(self.n_eigenvectors, device=device)
laplacian_sum = torch.matmul(
data.laplacian_pe[:, : self.n_eigenvectors], coefficients
)
noise = laplacian_sum * (self.max_noise / laplacian_sum.abs().max())
data.coords[:, 2] = (1 + noise) * data.coords[:, 2]
if not self.keep_lpe and compute_lpe:
del data.laplacian_pe
return data
|