Skip to content

Commit ef516c1

Browse files
authored
Merge branch 'main' into processing/asinh
2 parents b0fa1b8 + 82f9125 commit ef516c1

10 files changed

Lines changed: 88 additions & 69 deletions

File tree

‎sdm/models/kumo/timeseries/anomaly/block.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from torch.nn import Conv1d, LayerNorm, Linear, TransformerEncoderLayer
1010

1111

12-
class ResidualBlock(torch.nn.Module):
12+
class DiffusionBlock(torch.nn.Module):
1313
"""Kumo-Anomaly temporal/feature attention with gated residual outputs.
1414
1515
Time and feature axes of length one bypass their attention and subsequent

‎sdm/models/kumo/timeseries/anomaly/denoiser.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from torch import Tensor
1111
from torch.nn import Embedding, LayerNorm, Linear, ModuleList
1212

13-
from sdm.models.kumo.timeseries.anomaly.block import ResidualBlock
13+
from sdm.models.kumo.timeseries.anomaly.block import DiffusionBlock
1414
from sdm.models.kumo.timeseries.anomaly.embedding import DiffusionEmbedding
1515

1616

@@ -48,7 +48,7 @@ def __init__(
4848
)
4949
self.residual_layers = ModuleList(
5050
[
51-
ResidualBlock(
51+
DiffusionBlock(
5252
channels=channels,
5353
side_channels=side_channels,
5454
embedding_channels=embedding_channels,

‎sdm/models/timesfm3/block.py‎

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,17 @@
1515
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1616
# SPDX-License-Identifier: Apache-2.0
1717

18-
# ruff: noqa: D101, D102
18+
# ruff: noqa: D101
1919

2020
import math
2121
from typing import Any
2222

2323
import torch
24-
from torch import Tensor
2524
from torch.nn import Linear, ReLU, Sequential
2625

2726
from sdm.nn import RMSNorm, RotaryEmbedding, SoftplusScale, TransformerBlock
2827

2928

30-
class ResidualBlock(torch.nn.Module):
31-
def __init__(
32-
self,
33-
in_channels: int,
34-
out_channels: int,
35-
device: torch.device | str | None = None,
36-
dtype: torch.dtype | None = None,
37-
) -> None:
38-
super().__init__()
39-
factory_kwargs: dict[str, Any] = {"device": device, "dtype": dtype}
40-
41-
self.mlp = Sequential(
42-
Linear(in_channels, out_channels, bias=False, **factory_kwargs),
43-
ReLU(),
44-
Linear(out_channels, out_channels, bias=False, **factory_kwargs),
45-
)
46-
self.res = Linear(in_channels, out_channels, False, **factory_kwargs)
47-
48-
def forward(self, x: Tensor) -> Tensor:
49-
return self.mlp(x) + self.res(x)
50-
51-
5229
class TimesFM3TransformerBlock(TransformerBlock):
5330
def __init__(
5431
self,

‎sdm/models/timesfm3/model.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,20 @@
2525

2626
import torch
2727
from torch import Tensor
28+
from torch.nn import ReLU
2829

2930
from sdm import Recipe, RelatedTables, Stype, TableTensor, Task
3031
from sdm.cache import Cache
3132
from sdm.models._huggingface import download_checkpoint
3233
from sdm.models.base import ICLModel
33-
from sdm.models.timesfm3.block import ResidualBlock
3434
from sdm.models.timesfm3.ckpt import remap_ckpt
3535
from sdm.models.timesfm3.icl import ICLBlock
3636
from sdm.models.timesfm3.recipe import default_recipe
3737
from sdm.models.timesfm3.util import (
3838
crossfade_patches,
3939
gather_future_patches,
4040
)
41-
from sdm.nn import RevIN
41+
from sdm.nn import ResidualMLP, RevIN
4242
from sdm.tensor.table import TableSchema
4343

4444

@@ -229,9 +229,12 @@ def __init__(
229229
self.refinement = refinement
230230

231231
self.revin = RevIN(eps=0, **factory_kwargs)
232-
self.patch_embedding = ResidualBlock(
232+
self.patch_embedding = ResidualMLP(
233233
in_channels=2 * (input_patch_size + output_patch_size),
234+
hidden_channels=channels,
234235
out_channels=channels,
236+
activation=ReLU(),
237+
bias=False,
235238
**factory_kwargs,
236239
)
237240
self.icl_block = ICLBlock(

‎sdm/models/timestral/block.py‎

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,11 @@
1212
import torch
1313
import torch.nn.functional as F
1414
from torch import Tensor
15-
from torch.nn import Linear, Sequential, Sigmoid, SiLU
15+
from torch.nn import Linear, Sequential, Sigmoid
1616

1717
from sdm.nn import RMSNorm, RotaryEmbedding, SwiGLU, TransformerBlock
1818

1919

20-
class ResidualBlock(torch.nn.Module):
21-
def __init__(
22-
self,
23-
in_channels: int,
24-
hidden_channels: int,
25-
out_channels: int,
26-
bias: bool = True,
27-
device: torch.device | str | None = None,
28-
dtype: torch.dtype | None = None,
29-
) -> None:
30-
super().__init__()
31-
factory_kwargs: dict[str, Any] = {"device": device, "dtype": dtype}
32-
33-
self.mlp = Sequential(
34-
Linear(in_channels, hidden_channels, bias, **factory_kwargs),
35-
SiLU(),
36-
Linear(hidden_channels, out_channels, bias, **factory_kwargs),
37-
)
38-
self.res = Linear(in_channels, out_channels, bias, **factory_kwargs)
39-
40-
def forward(self, x: Tensor) -> Tensor:
41-
return self.mlp(x) + self.res(x)
42-
43-
4420
class MonotoneQuantiles(torch.nn.Module):
4521
width: Tensor
4622

‎sdm/nn/__init__.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from sdm.nn.rope import RotaryEmbedding
77
from sdm.nn.sinusoidal import SinusoidalEmbedding
8+
from sdm.nn.mlp import ResidualMLP
89
from sdm.nn.glu import SwiGLU
910
from sdm.nn.softplus import SoftplusScale
1011
from sdm.nn.rms_norm import RMSNorm
@@ -17,6 +18,7 @@
1718
__all__ = [
1819
"RotaryEmbedding",
1920
"SinusoidalEmbedding",
21+
"ResidualMLP",
2022
"SwiGLU",
2123
"SoftplusScale",
2224
"RMSNorm",

‎sdm/nn/glu.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ def __init__(
6767
hidden_channels, channels, bias=bias, **factory_kwargs
6868
)
6969

70-
def forward(self, tensor: Tensor) -> Tensor:
70+
def forward(self, x: Tensor) -> Tensor:
7171
r"""The forward pass.
7272
7373
Args:
74-
tensor: The tensor.
74+
x: The tensor.
7575
"""
76-
value = self.up_lin(tensor)
77-
gate = F.silu(self.gate_lin(tensor))
76+
value = self.up_lin(x)
77+
gate = F.silu(self.gate_lin(x))
7878
return self.down_lin(gate * value)

‎sdm/nn/mlp.py‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
from typing import Any
5+
6+
import torch
7+
from torch import Tensor
8+
from torch.nn import Linear, Sequential
9+
10+
11+
class ResidualMLP(torch.nn.Module):
12+
r"""Two-layer MLP with a learned linear residual projection.
13+
14+
.. math::
15+
16+
\operatorname{MLP}_2(x) + \operatorname{Linear}(x)
17+
18+
Args:
19+
in_channels: The number of input channels.
20+
hidden_channels: The number of hidden channels in the MLP.
21+
out_channels: The number of output channels.
22+
activation: The activation in the MLP.
23+
bias: Whether to learn additive biases.
24+
device: The device.
25+
dtype: The dtype.
26+
"""
27+
28+
def __init__(
29+
self,
30+
in_channels: int,
31+
hidden_channels: int,
32+
out_channels: int,
33+
activation: torch.nn.Module,
34+
bias: bool = True,
35+
device: torch.device | str | None = None,
36+
dtype: torch.dtype | None = None,
37+
) -> None:
38+
super().__init__()
39+
factory_kwargs: dict[str, Any] = {
40+
"bias": bias,
41+
"device": device,
42+
"dtype": dtype,
43+
}
44+
self.mlp = Sequential(
45+
Linear(in_channels, hidden_channels, **factory_kwargs),
46+
activation,
47+
Linear(hidden_channels, out_channels, **factory_kwargs),
48+
)
49+
self.res = Linear(in_channels, out_channels, **factory_kwargs)
50+
51+
def forward(self, x: Tensor) -> Tensor:
52+
r"""The forward pass.
53+
54+
Args:
55+
x: The tensor.
56+
"""
57+
return self.mlp(x) + self.res(x)

‎test/models/kumo/timeseries/anomaly/test_block.py‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import torch.nn.functional as F
1010
from torch import Tensor
1111

12-
from sdm.models.kumo.timeseries.anomaly.block import ResidualBlock
12+
from sdm.models.kumo.timeseries.anomaly.block import DiffusionBlock
1313
from sdm.testing import withCUDA
1414

1515

@@ -34,7 +34,7 @@ def reference_attention(
3434

3535

3636
def reference_block(
37-
block: ResidualBlock,
37+
block: DiffusionBlock,
3838
x: Tensor,
3939
side_info: Tensor,
4040
diffusion_embedding: Tensor,
@@ -79,15 +79,15 @@ def reference_block(
7979
(3, 5, 1, 2, True),
8080
],
8181
)
82-
def test_residual_block(
82+
def test_diffusion_block(
8383
device: torch.device,
8484
features: int,
8585
length: int,
8686
diffusion_batch: int,
8787
strategy_batch: int,
8888
training: bool,
8989
) -> None:
90-
block = ResidualBlock(
90+
block = DiffusionBlock(
9191
channels=8,
9292
side_channels=6,
9393
embedding_channels=12,
@@ -110,8 +110,8 @@ def test_residual_block(
110110

111111

112112
@withCUDA
113-
def test_residual_block_grad_and_state_dict(device: torch.device) -> None:
114-
block = ResidualBlock(
113+
def test_diffusion_block_grad_and_state_dict(device: torch.device) -> None:
114+
block = DiffusionBlock(
115115
channels=8,
116116
side_channels=6,
117117
embedding_channels=12,
@@ -135,7 +135,7 @@ def test_residual_block_grad_and_state_dict(device: torch.device) -> None:
135135
assert value.grad is not None
136136
assert value.grad.abs().sum() > 0
137137

138-
restored = ResidualBlock(
138+
restored = DiffusionBlock(
139139
channels=8,
140140
side_channels=6,
141141
embedding_channels=12,
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@
33

44

55
import torch
6+
from torch.nn import ReLU
67

7-
from sdm.models.timesfm3.block import ResidualBlock
8+
from sdm.nn import ResidualMLP
89
from sdm.testing import withCUDA
910

1011

1112
@withCUDA
12-
def test_residual_block(device: torch.device) -> None:
13-
block = ResidualBlock(
13+
def test_residual_mlp(device: torch.device) -> None:
14+
block = ResidualMLP(
1415
in_channels=3,
16+
hidden_channels=2,
1517
out_channels=2,
18+
activation=ReLU(),
19+
bias=False,
1620
device=device,
1721
)
1822

0 commit comments

Comments
 (0)