PositionalEmbedding
softssharp_module.PositionalEmbedding · inherits nnx.Module
Additive sinusoidal encoding over the token (variate) axis.
__call__(x, scale) returns x + scale * table[:, :x.shape[1]], matching NF PositionalEmbedding.forward. scale is a scalar (array or float) so the caller can pass a learnable parameter, a gated parameter, or a constant.
__init__(self, d_series: int, max_len: int = 5000)
| Parameter | Type | Default | Description |
|---|---|---|---|
| d_series | int | - | (undocumented) |
| max_len | int | 5000 | (undocumented) |
__call__(self, x: jnp.ndarray, scale=1.0) -> jnp.ndarray
x: [B, C, d_series] -> same shape. Requires C <= max_len.
| Parameter | Type | Default | Description |
|---|---|---|---|
| x | jnp.ndarray | - | (undocumented) |
| scale | Any | 1.0 | (undocumented) |
STADSharp
softssharp_module.STADSharp · inherits nnx.Module
STAD with stochastic variable-position encoding — the SOFTSSharp block.
Given per-series tokens input: [B, C, d_series] (d_series = hidden_size, C = number of variate tokens):
- Variable-position encoding (new vs SOFTS): add the sinusoidal table indexed by variate position, scaled by the learnable
pe_scale. Applied with probabilitype_keep_probin training (one Bernoulli per forward, shared across the batch); always applied at inference, scaled bype_keep_prob * pe_scale. The encoded tensor is what feeds both the set FFN and the later fusion concat, exactly as in NF. - Set FFN
h = gen2(dropout1(gelu(gen1(input))))->[B, C, d_core]. - Aggregate into a core (pool across the
Caxis into a single representation, then broadcast it back to allCseries): - train (deterministic=False): STOCHASTIC pooling — for each(batch, core-dim)sample one series index fromsoftmax(h)over theCaxis (NFtorch.multinomial) and gather that series' value. - eval (deterministic=True): the softmax-weighted mean over theCaxis (NF's inference branch). followed bydropout2on the dispatched core (new vs SOFTS). - Dispatch + fuse
output = gen4(dropout3(gelu(gen3([input, core]))))->[B, C, d_series](dropout3new vs SOFTS).
Cost stays O(C) in the number of series, versus O(C^2) for attention. The multinomial sample and the position-encoding Bernoulli both draw fresh keys from rngs each forward; under the training nnx.scan the key streams are threaded through the carry exactly like nnx.Dropout's, so successive steps sample independently.
__init__(self, *, hidden_size, d_core, dropout: float = 0.1, pe_keep_prob: float = 0.5, pe_max_len: int = 5000, rngs: nnx.Rngs)
| Parameter | Type | Default | Description |
|---|---|---|---|
| hidden_size | Any | - | (undocumented) |
| d_core | Any | - | (undocumented) |
| dropout | float | 0.1 | (undocumented) |
| pe_keep_prob | float | 0.5 | (undocumented) |
| pe_max_len | int | 5000 | (undocumented) |
| rngs | nnx.Rngs | - | (undocumented) |
add_positional_embedding(self, x: jnp.ndarray, deterministic: bool) -> jnp.ndarray
NF STADSharp.add_positional_embedding, as a branch-free JAX gate.
| Parameter | Type | Default | Description |
|---|---|---|---|
| x | jnp.ndarray | - | (undocumented) |
| deterministic | bool | - | (undocumented) |
__call__(self, x: jnp.ndarray, deterministic: bool) -> jnp.ndarray
x: [B, C, hidden] -> [B, C, hidden].
| Parameter | Type | Default | Description |
|---|---|---|---|
| x | jnp.ndarray | - | (undocumented) |
| deterministic | bool | - | (undocumented) |
RevIN
softssharp_module.RevIN · inherits nnx.Module
Reversible instance normalization (Kim et al. 2022), per-window.
Faithful to neuralforecast's SOFTSSharp use_norm block, which centers on the per-window MEAN (subtract_last=False), divides by sqrt(var + eps) with population variance (unbiased=False / ddof=0), and applies no learnable affine. Statistics are returned explicitly rather than cached, so the module is pure and vmap/scan-safe.
__init__(self, num_features: int, *, subtract_last: bool = False, affine: bool = False, eps: float = 1e-5, rngs: nnx.Rngs)
| Parameter | Type | Default | Description |
|---|---|---|---|
| num_features | int | - | (undocumented) |
| subtract_last | bool | False | (undocumented) |
| affine | bool | False | (undocumented) |
| eps | float | 1e-5 | (undocumented) |
| rngs | nnx.Rngs | - | (undocumented) |
norm(self, x: jnp.ndarray) -> tuple[jnp.ndarray, jnp.ndarray, jnp.ndarray]
x: [B, L, C] -> (z: [B, L, C], loc: [B, 1, C], scale: [B, 1, C]).
| Parameter | Type | Default | Description |
|---|---|---|---|
| x | jnp.ndarray | - | (undocumented) |
denorm(self, z: jnp.ndarray, loc: jnp.ndarray, scale: jnp.ndarray) -> jnp.ndarray
Invert norm. z: [B, T, C] with broadcastable loc/scale [B, 1, C].
| Parameter | Type | Default | Description |
|---|---|---|---|
| z | jnp.ndarray | - | (undocumented) |
| loc | jnp.ndarray | - | (undocumented) |
| scale | jnp.ndarray | - | (undocumented) |
DataEmbeddingInverted
softssharp_module.DataEmbeddingInverted · inherits nnx.Module
Inverted embedding: each variate's lookback becomes a token.
Mirrors NF DataEmbedding_inverted (SOFTSSharp imports SOFTS's verbatim): permute [B, L, N] -> [B, N, L] then Linear(input_size -> hidden_size) (the lookback length is the feature dim), followed by dropout. Exogenous/time marks are not supported (univariate, no covariates), so the x_mark concat path is omitted.
__init__(self, *, input_size, hidden_size, dropout, rngs: nnx.Rngs)
| Parameter | Type | Default | Description |
|---|---|---|---|
| input_size | Any | - | (undocumented) |
| hidden_size | Any | - | (undocumented) |
| dropout | Any | - | (undocumented) |
| rngs | nnx.Rngs | - | (undocumented) |
__call__(self, x: jnp.ndarray, deterministic: bool) -> jnp.ndarray
x: [B, L, N] -> tokens: [B, N, hidden_size].
| Parameter | Type | Default | Description |
|---|---|---|---|
| x | jnp.ndarray | - | (undocumented) |
| deterministic | bool | - | (undocumented) |
TransEncoderLayer
softssharp_module.TransEncoderLayer · inherits nnx.Module
One SOFTSSharp encoder layer (post-norm), STADSharp in place of attention.
NF TransEncoderLayer.forward (with STADSharp as the "attention")::
new_x, _ = STADSharp(x)
x = x + dropout(new_x)
y = x = norm1(x)
y = dropout(activation(conv1(y))) # conv1d kernel=1 == pointwise Linear
y = dropout(conv2(y))
return norm2(x + y)
The two Conv1d(kernel_size=1) layers are mathematically pointwise linear maps over the channel axis, so they are implemented as nnx.Linear (no transpose needed). activation is exact GELU (NF passes F.gelu). Note the residual adds the layer input BEFORE the position encoding — the encoding lives entirely inside STADSharp, as in NF.
__init__(self, *, hidden_size, d_core, d_ff, dropout, pe_keep_prob, pe_max_len=5000, activation="gelu", rngs: nnx.Rngs)
| Parameter | Type | Default | Description |
|---|---|---|---|
| hidden_size | Any | - | (undocumented) |
| d_core | Any | - | (undocumented) |
| d_ff | Any | - | (undocumented) |
| dropout | Any | - | (undocumented) |
| pe_keep_prob | Any | - | (undocumented) |
| pe_max_len | Any | 5000 | (undocumented) |
| activation | Any | "gelu" | (undocumented) |
| rngs | nnx.Rngs | - | (undocumented) |
__call__(self, x, deterministic: bool)
| Parameter | Type | Default | Description |
|---|---|---|---|
| x | Any | - | (undocumented) |
| deterministic | bool | - | (undocumented) |
TransEncoder
softssharp_module.TransEncoder · inherits nnx.Module
Stack of e_layers encoder layers. NO final LayerNorm — see below.
NF's common._modules.TransEncoder takes an OPTIONAL norm_layer and applies it only if self.norm is not None. SOFTSSharp (like SOFTS) builds the encoder positionally:
TransEncoder([TransEncoderLayer(STADSharp(...), ...) for l in range(e_layers)])
with no norm_layer argument, so the reference has no final normalization and the encoder output feeds projection directly.
The difference is subtler than it looks, and worth stating precisely: every layer already ENDS in norm2, so an extra final LayerNorm is near-identity at initialization (re-normalizing an already-normalized vector). What it is not is free — its scale and bias are learnable, so it would hand the port 2 * hidden_size trainable parameters the reference does not have, and a learned per-feature affine applied immediately before the projector. That is a real architectural divergence, so it is omitted.
__init__(self, *, e_layers, hidden_size, d_core, d_ff, dropout, pe_keep_prob, pe_max_len=5000, activation="gelu", rngs: nnx.Rngs)
| Parameter | Type | Default | Description |
|---|---|---|---|
| e_layers | Any | - | (undocumented) |
| hidden_size | Any | - | (undocumented) |
| d_core | Any | - | (undocumented) |
| d_ff | Any | - | (undocumented) |
| dropout | Any | - | (undocumented) |
| pe_keep_prob | Any | - | (undocumented) |
| pe_max_len | Any | 5000 | (undocumented) |
| activation | Any | "gelu" | (undocumented) |
| rngs | nnx.Rngs | - | (undocumented) |
__call__(self, x, deterministic: bool)
| Parameter | Type | Default | Description |
|---|---|---|---|
| x | Any | - | (undocumented) |
| deterministic | bool | - | (undocumented) |
SOFTSSharpNet
softssharp_module.SOFTSSharpNet · inherits nnx.Module
Full SOFTSSharp backbone: (RevIN) -> invert-embed -> encoder -> project -> (denorm).
I/O mirrors the other Chronax neural nets: __call__(x: [B, L, 1]) -> [B, h, 1]. Written N-generically: an [B, L, N] input yields [B, h, N], so a multivariate path can reuse it later; only the :class:SOFTSSharp wrapper fixes N = 1.
__init__(self, *, h, input_size, hidden_size, d_core, e_layers, d_ff, dropout, use_norm, pe_keep_prob=0.5, pe_max_len=5000, activation="gelu", rngs: nnx.Rngs)
| Parameter | Type | Default | Description |
|---|---|---|---|
| h | Any | - | (undocumented) |
| input_size | Any | - | (undocumented) |
| hidden_size | Any | - | (undocumented) |
| d_core | Any | - | (undocumented) |
| e_layers | Any | - | (undocumented) |
| d_ff | Any | - | (undocumented) |
| dropout | Any | - | (undocumented) |
| use_norm | Any | - | (undocumented) |
| pe_keep_prob | Any | 0.5 | (undocumented) |
| pe_max_len | Any | 5000 | (undocumented) |
| activation | Any | "gelu" | (undocumented) |
| rngs | nnx.Rngs | - | (undocumented) |
__call__(self, x: jnp.ndarray, deterministic: bool) -> jnp.ndarray
x: [B, L, N] -> [B, h, N].
| Parameter | Type | Default | Description |
|---|---|---|---|
| x | jnp.ndarray | - | (undocumented) |
| deterministic | bool | - | (undocumented) |