Reference
Initialization¶
How frozen weights get their values: topology initializers for the square recurrent matrix, input/feedback initializers for the rectangular ones, the registries behind both, and the resolvers that accept names, tuples, callables, or configured objects interchangeably.
topology
¶
Topology Initialization System¶
This module provides the interface between structure generators — NetworkX graphs or direct matrix builders — and PyTorch tensor initialization for reservoir recurrent weights.
| CLASS | DESCRIPTION |
|---|---|
TopologyInitializer |
Abstract base class for topology initializers. |
GraphTopology |
Concrete implementation using NetworkX graphs. |
MatrixTopology |
Concrete implementation wrapping any matrix-building callable. |
| FUNCTION | DESCRIPTION |
|---|---|
get_topology |
Get a pre-configured topology by name. |
show_topologies |
List available topologies or get details. |
register_graph_topology |
Decorator to register graph-based topologies. |
register_matrix_topology |
Decorator to register matrix-builder topologies. |
scale_to_spectral_radius |
Rescale a square matrix to a target spectral radius. |
estimate_spectral_radius |
Estimate a matrix's largest absolute eigenvalue (power iteration / sparse
|
Examples:
Using pre-registered topologies:
>>> from resdag.init.topology import get_topology
>>> topology = get_topology("erdos_renyi", p=0.1, seed=42)
>>> weight = torch.empty(100, 100)
>>> topology.initialize(weight, spectral_radius=0.9)
Any function that builds a matrix is a topology:
>>> def block_diagonal(n, blocks=4):
... ... # return an (n, n) tensor
>>> reservoir = ESNLayer(500, feedback_size=3, topology=block_diagonal)
Registering custom topologies:
>>> from resdag.init.topology import register_graph_topology, register_matrix_topology
>>> @register_graph_topology("custom", param=1.0)
... def my_custom_graph(n, param=1.0, seed=None):
... G = nx.DiGraph()
... # ... graph generation logic
... return G
>>> @register_matrix_topology("block_diagonal", blocks=4)
... def block_diagonal(n, blocks=4, seed=None):
... # ... matrix construction logic
... return w
See Also
resdag.init.graphs : Graph generation functions. resdag.init.matrices : Direct matrix-construction functions. resdag.layers.ESNLayer : Uses topologies for weight initialization.
TopologyInitializer
¶
Bases: ABC
Abstract base class for topology-based weight initialization.
Topology initializers convert graph structures into PyTorch weight tensors for reservoir layers. They extract the required size from the tensor shape, generate a graph, convert it to an adjacency matrix, and optionally apply spectral radius scaling.
Subclasses must implement the :meth:initialize method.
| ATTRIBUTE | DESCRIPTION |
|---|---|
prescaled |
Whether the topology bakes its own spectral structure into the
recurrent matrix (graded radii, unit singular values, an analytically
fixed spectral radius, ...). When
TYPE:
|
See Also
GraphTopology : Concrete implementation using NetworkX graphs. resdag.layers.ESNLayer : Uses topology initializers.
initialize
abstractmethod
¶
Initialize a weight tensor using graph topology.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
The weight tensor to initialize, shape
TYPE:
|
spectral_radius
|
Target spectral radius for scaling. If None, no scaling is applied.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
The initialized weight tensor (same as input, modified in-place). |
Source code in src/resdag/init/topology/base.py
GraphTopology
¶
GraphTopology(graph_func: Callable, graph_kwargs: dict[str, Any] | None = None, prescaled: bool = False)
Bases: TopologyInitializer
Topology initializer based on NetworkX graph functions.
This class wraps a graph generation function and converts it into a weight
initializer. The graph function must accept n (number of nodes) as its
first argument.
| PARAMETER | DESCRIPTION |
|---|---|
graph_func
|
A function with signature
TYPE:
|
graph_kwargs
|
Keyword arguments to pass to the graph function.
TYPE:
|
prescaled
|
If
TYPE:
|
| ATTRIBUTE | DESCRIPTION |
|---|---|
graph_func |
The graph generation function.
TYPE:
|
graph_kwargs |
Keyword arguments for the graph function.
TYPE:
|
prescaled |
Whether the outer spectral-radius rescale is suppressed (see above).
TYPE:
|
Examples:
Using a registered graph function:
>>> from resdag.init.graphs import erdos_renyi_graph
>>> import torch
>>>
>>> topology = GraphTopology(erdos_renyi_graph, {"p": 0.1, "directed": True})
>>> weight = torch.empty(100, 100)
>>> topology.initialize(weight, spectral_radius=0.9)
With the registry helper:
>>> from resdag.init.topology import get_topology
>>> topology = get_topology("erdos_renyi", p=0.15)
>>> topology.initialize(weight, spectral_radius=0.95)
See Also
resdag.init.graphs : Available graph generation functions. get_topology : Get pre-configured topology by name.
Source code in src/resdag/init/topology/base.py
initialize
¶
Initialize weight tensor from graph topology.
Generates a graph using the stored function, converts it to an adjacency matrix, and optionally scales to the target spectral radius.
When this topology is :attr:prescaled, the outer spectral-radius
rescale is skipped (the builder's own spectral structure is kept) and a
warning is emitted if spectral_radius is not None.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Square tensor to initialize, shape
TYPE:
|
spectral_radius
|
Target spectral radius for the weight matrix. Ignored (with a
warning) when the topology is :attr:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor (modified in-place). |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If weight is not 2D or not square. |
Source code in src/resdag/init/topology/base.py
MatrixTopology
¶
MatrixTopology(matrix_func: Callable, matrix_kwargs: dict[str, Any] | None = None, prescaled: bool = False, seed: int | None = None)
Bases: TopologyInitializer
Topology initializer wrapping any matrix-building callable.
This is the general-purpose escape hatch of the topology system: any
function with logic for constructing a recurrent weight matrix becomes a
topology, with full access to spectral-radius scaling, the registry, and
the ESNLayer(topology=...) shorthand. No graph required.
Two calling conventions are supported, tried in order:
- Build style —
fn(n, **kwargs)returning an(n, n)array-like: atorch.Tensor, anumpy.ndarray, or even anetworkxgraph (converted to its adjacency matrix). - In-place style —
fn(tensor, **kwargs)mutating a tensor in place, e.g. anytorch.nn.init.*_function.
| PARAMETER | DESCRIPTION |
|---|---|
matrix_func
|
The matrix-building function (build style or in-place style).
TYPE:
|
matrix_kwargs
|
Keyword arguments bound to the function.
TYPE:
|
prescaled
|
If
TYPE:
|
seed
|
Reproducibility seed for in-place builders that take a
TYPE:
|
Examples:
A plain function as a topology:
>>> import torch
>>> def block_diagonal(n, blocks=4):
... w = torch.zeros(n, n)
... size = n // blocks
... for b in range(blocks):
... s = b * size
... w[s : s + size, s : s + size] = torch.randn(size, size)
... return w
>>> topology = MatrixTopology(block_diagonal, {"blocks": 5})
>>> weight = torch.empty(100, 100)
>>> topology.initialize(weight, spectral_radius=0.9)
Bare callables passed to ESNLayer are wrapped automatically:
>>> from resdag.layers import ESNLayer
>>> layer = ESNLayer(100, feedback_size=3, topology=block_diagonal)
>>> layer = ESNLayer(100, feedback_size=3, topology=(block_diagonal, {"blocks": 2}))
torch.nn.init functions work directly (in-place style):
See Also
GraphTopology : Graph-based topologies. resdag.init.topology.register_matrix_topology : Register by name.
Source code in src/resdag/init/topology/base.py
initialize
¶
Initialize a square weight tensor from the wrapped callable.
When this topology is :attr:prescaled, the outer spectral-radius
rescale is skipped (the builder's own spectral structure is kept) and a
warning is emitted if spectral_radius is not None.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Square tensor to initialize, shape
TYPE:
|
spectral_radius
|
Target spectral radius. If None, no scaling is applied. Ignored
(with a warning) when the topology is :attr:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor (modified in-place). |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If |
Source code in src/resdag/init/topology/base.py
get_topology
¶
get_topology(name: str, **override_kwargs: Any) -> TopologyInitializer
Get a pre-configured topology initializer by name.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Name of the topology (e.g.,
TYPE:
|
**override_kwargs
|
Keyword arguments to override default graph parameters.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
TopologyInitializer
|
Configured topology initializer (:class: |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If topology name is not registered. |
Examples:
Basic usage:
>>> topology = get_topology("erdos_renyi", p=0.15, seed=42)
>>> weight = torch.empty(100, 100)
>>> topology.initialize(weight, spectral_radius=0.9)
With ESNLayer:
>>> from resdag.layers import ESNLayer
>>> reservoir = ESNLayer(
... reservoir_size=500,
... feedback_size=10,
... topology=get_topology("watts_strogatz", k=4, p=0.3),
... spectral_radius=0.95,
... )
See Also
show_topologies : List available topologies. register_graph_topology : Register new topologies.
Source code in src/resdag/init/topology/registry.py
register_graph_topology
¶
register_graph_topology(name: str, prescaled: bool = False, **default_kwargs: Any) -> Callable[[Callable], Callable]
Decorator to register a graph function as a topology.
Registers a graph generation function in the topology registry at
definition time, making it available for use with
:class:~resdag.layers.ESNLayer.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Unique name for the topology.
TYPE:
|
prescaled
|
Mark the topology as already carrying its own spectral structure (e.g.
TYPE:
|
**default_kwargs
|
Default keyword arguments for the graph function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
callable
|
Decorator function that registers and returns the graph function. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If a topology with the same name is already registered. |
Examples:
>>> @register_graph_topology("my_graph", p=0.1, directed=True)
... def my_graph(n, p=0.1, directed=False, seed=None):
... G = nx.DiGraph() if directed else nx.Graph()
... # ... graph generation logic
... return G
Notes
- Graph functions must accept
n(number of nodes) as first parameter. - Graph functions must return
nx.Graphornx.DiGraphwith weighted edges. - Registered topologies can be accessed via :func:
get_topology.
Source code in src/resdag/init/topology/registry.py
register_matrix_topology
¶
register_matrix_topology(name: str, prescaled: bool = False, **default_kwargs: Any) -> Callable[[Callable], Callable]
Decorator to register a matrix-building function as a topology.
The complement of :func:register_graph_topology for builders that
construct the recurrent weight matrix directly — no graph involved.
Any logic that produces a square matrix qualifies.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Unique name for the topology.
TYPE:
|
prescaled
|
Mark the topology as already fixing its own spectral structure (e.g.
TYPE:
|
**default_kwargs
|
Default keyword arguments for the matrix function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
callable
|
Decorator function that registers and returns the matrix function. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If a topology with the same name is already registered. |
Examples:
>>> @register_matrix_topology("block_diagonal", blocks=4)
... def block_diagonal(n, blocks=4, seed=None):
... w = torch.zeros(n, n)
... size = n // blocks
... for b in range(blocks):
... s = b * size
... w[s : s + size, s : s + size] = torch.randn(size, size)
... return w
Notes
- Matrix functions must accept
n(matrix size) as first parameter and return an(n, n)torch.Tensorornumpy.ndarray. - Registered topologies are accessed via :func:
get_topologyor by name inESNLayer(topology="..."), identically to graph topologies.
Source code in src/resdag/init/topology/registry.py
scale_to_spectral_radius
¶
Rescale a square matrix so its spectral radius equals target_radius.
The current spectral radius is obtained from
:func:estimate_spectral_radius, which picks the exact dense eigvals
(small N), scipy eigs (large N, sparse or dense), or a power-iteration
fallback automatically. Returns the matrix unchanged when its current
spectral radius is (numerically) zero — e.g. the zero topology or a
nilpotent matrix.
This is the single shared rescale implementation used by both
:class:GraphTopology/:class:MatrixTopology and
:class:resdag.layers.cells.esn_cell.ESNCell.
| PARAMETER | DESCRIPTION |
|---|---|
matrix
|
Square matrix to rescale.
TYPE:
|
target_radius
|
Desired largest absolute eigenvalue.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
The rescaled matrix (new tensor). |
Source code in src/resdag/init/topology/base.py
show_topologies
¶
Show available topologies or details for a specific topology.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Name of topology to inspect. If None, prints all registered topology names and returns them as a list.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list of str or None
|
When |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If the specified topology name is not registered. |
Source code in src/resdag/init/topology/registry.py
input_feedback
¶
Input/Feedback Weight Initialization¶
This module contains initializers for rectangular weight matrices used in reservoir input and feedback connections.
For reservoirs:
- Feedback weights: (reservoir_size, feedback_size)
- Input weights: (reservoir_size, input_size)
| CLASS | DESCRIPTION |
|---|---|
InputFeedbackInitializer |
Abstract base class for all initializers. |
RandomInputInitializer |
Uniform random in [-1, 1] (baseline). |
RandomBinaryInitializer |
Binary {-1, +1} values. |
NormalInputInitializer |
Gaussian |
UniformInputInitializer |
Bounded |
BernoulliInputInitializer |
Bernoulli |
PseudoDiagonalInitializer |
Structured block-diagonal pattern. |
ChebyshevInitializer |
Deterministic chaotic initialization. |
LogisticMappingInitializer |
Deterministic logistic-map initialization (RC.jl |
MinimalInputInitializer |
Rodan & Tiňo minimal-complexity dense input (RC.jl |
WeightedInputInitializer |
Block-diagonal random input (RC.jl |
WeightedMinimalInitializer |
Block-diagonal constant-magnitude input (RC.jl |
InformedInputInitializer |
State/model split for hybrid ESNs (RC.jl |
ChessboardInitializer |
Alternating {-1, +1} pattern. |
BinaryBalancedInitializer |
Hadamard-based balanced initialization. |
OppositeAnchorsInitializer |
Opposite anchor points on ring. |
DendrocycleInputInitializer |
Specific to dendrocycle topology. |
ChainOfNeuronsInputInitializer |
Specific to chain-of-neurons topology. |
RingWindowInputInitializer |
Windowed inputs on ring topology. |
ZeroInitializer |
Sets all weights to zero. |
FunctionInitializer |
Wraps any matrix-building callable as an initializer (the input/feedback analog of a matrix-builder topology). |
| FUNCTION | DESCRIPTION |
|---|---|
get_input_feedback |
Get an initializer by name. |
show_input_initializers |
List available initializers or get details. |
register_input_feedback |
Decorator to register new initializers. |
Examples:
Using pre-registered initializers:
>>> from resdag.init.input_feedback import get_input_feedback
>>> initializer = get_input_feedback("random", input_scaling=0.5)
>>> weight = torch.empty(100, 10)
>>> initializer.initialize(weight)
Registering custom initializers:
>>> from resdag.init.input_feedback import register_input_feedback
>>> @register_input_feedback("my_init", scaling=0.5)
... class MyInitializer(InputFeedbackInitializer):
... def __init__(self, scaling=0.5):
... self.scaling = scaling
... def initialize(self, weight, **kwargs):
... torch.nn.init.uniform_(weight, -self.scaling, self.scaling)
... return weight
See Also
resdag.layers.ESNLayer : Uses these initializers for weight matrices. resdag.init.topology : Topology initializers for recurrent weights.
InputFeedbackInitializer
¶
InputFeedbackInitializer(input_scaling: float | None = None, connectivity: float | None = None, seed: SeedLike = None)
Bases: ABC
Abstract base class for input/feedback weight initialization.
All input/feedback weight initializers inherit from this class, implement
:meth:initialize, and honor the shared scaling contract owned here.
These initializers create weight matrices for:
- Input connections: shape
(reservoir_size, input_size) - Feedback connections: shape
(reservoir_size, feedback_size)
The scaling contract
input_scaling is the single uniform magnitude knob:
None— no scaling; the natural-range matrix is returned as-is.s(finite float) — multiply the whole matrix bysas the documented final transform, so the matrix's magnitude statistic (max|W|for elementwise initializers, per-channel L2 norm for the structured ring initializers) scales linearly withs.
connectivity is an optional density knob in (0, 1]: the fraction of
nonzero entries kept per column. None leaves the produced sparsity
untouched.
Per-call overrides
The contract parameters are bound at construction, but :meth:initialize
(and the :meth:__call__ alias) accept per-call keyword overrides for
the recognized contract parameters — input_scaling and connectivity.
A recognized keyword passed to initialize takes precedence over the
bound attribute for that call only, and is validated identically::
init = RandomInputInitializer(input_scaling=2.0)
init.initialize(weight) # uses input_scaling=2.0
init.initialize(weight, input_scaling=0.001) # honored: uses 0.001
init.input_scaling # still 2.0 (unchanged)
This is the same contract :class:FunctionInitializer honors (per-call
kwargs merged over the bound ones), so a given call shape behaves
identically for class-based and function-wrapped initializers. Subclasses
cooperate simply by threading their **kwargs into the contract helpers,
which read the override from **kwargs and fall back to the bound
attribute; unrecognized keys are ignored.
Subclasses must implement :meth:initialize, which builds the weight
tensor and returns it (modified in-place). They opt into the contract via
:meth:_apply_scaling (and optionally :meth:_apply_connectivity),
forwarding the per-call **kwargs so recognized overrides are honored.
| PARAMETER | DESCRIPTION |
|---|---|
input_scaling
|
Uniform multiplicative scaling applied as the final transform.
TYPE:
|
connectivity
|
Fraction of nonzero entries to keep per column, in
TYPE:
|
seed
|
Reproducibility seed for any subclass randomness (the uniform/binary
draws of the random initializers) and the connectivity mask. Accepts a
plain
TYPE:
|
Examples:
Creating a custom initializer that honors the contract:
>>> class MyInitializer(InputFeedbackInitializer):
... def initialize(self, weight, **kwargs):
... values = torch.empty_like(weight).uniform_(-1, 1)
... # Forward **kwargs so a per-call ``input_scaling`` override wins.
... values = self._apply_scaling(values, **kwargs)
... with torch.no_grad():
... weight.copy_(values)
... return weight
>>>
>>> initializer = MyInitializer(input_scaling=0.5)
>>> weight = torch.empty(100, 10)
>>> initializer(weight)
Using with ESNLayer:
>>> from resdag.layers import ESNLayer
>>> reservoir = ESNLayer(
... reservoir_size=100,
... feedback_size=10,
... feedback_initializer=MyInitializer(input_scaling=0.5),
... )
See Also
resdag.init.input_feedback.registry : Get initializers by name. resdag.layers.ESNLayer : Uses these initializers.
Source code in src/resdag/init/input_feedback/base.py
initialize
abstractmethod
¶
Initialize a weight tensor.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
2D tensor of shape
TYPE:
|
**kwargs
|
Per-call keyword overrides. The recognized contract parameters —
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
The initialized weight tensor (same as input, modified in-place). |
Source code in src/resdag/init/input_feedback/base.py
FunctionInitializer
¶
Bases: InputFeedbackInitializer
Input/feedback initializer wrapping any matrix-building callable.
Lets plain functions act as initializers for the rectangular input and feedback weight matrices, without subclassing. Two calling conventions are supported, tried in order:
- Build style —
fn(rows, cols, **kwargs)returning a(rows, cols)array-like (torch.Tensorornumpy.ndarray). - In-place style —
fn(tensor, **kwargs)mutating a tensor in place, e.g. anytorch.nn.init.*_function.
| PARAMETER | DESCRIPTION |
|---|---|
fn
|
The matrix-building function (build style or in-place style).
TYPE:
|
**kwargs
|
Keyword arguments bound to the function.
TYPE:
|
Examples:
A plain function as an initializer:
>>> import torch
>>> def first_neuron_only(rows, cols, scale=1.0):
... w = torch.zeros(rows, cols)
... w[0, :] = scale
... return w
>>> init = FunctionInitializer(first_neuron_only, scale=0.5)
>>> weight = torch.empty(100, 3)
>>> init.initialize(weight)
Bare callables passed to ESNLayer are wrapped automatically:
>>> from resdag.layers import ESNLayer
>>> layer = ESNLayer(100, feedback_size=3, feedback_initializer=first_neuron_only)
>>> layer = ESNLayer(
... 100,
... feedback_size=3,
... feedback_initializer=(first_neuron_only, {"scale": 0.1}),
... )
torch.nn.init functions work directly (in-place style):
See Also
InputFeedbackInitializer : Base class for class-based initializers. resdag.init.input_feedback.register_input_feedback : Register by name.
Source code in src/resdag/init/input_feedback/function.py
initialize
¶
Initialize a rectangular weight tensor from the wrapped callable.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
2D tensor of shape
TYPE:
|
**kwargs
|
Per-call overrides merged over the bound keyword arguments (a
recognized key wins for this call only). This is the same per-call
contract the class-based initializers honor — see the Per-call
overrides section of
:class:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
The initialized weight tensor (same as input, modified in-place). |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If |
Source code in src/resdag/init/input_feedback/function.py
BernoulliInputInitializer
¶
BernoulliInputInitializer(p: float = 0.5, connectivity: float | None = None, input_scaling: float | None = None, seed: SeedLike = None)
Bases: InputFeedbackInitializer
Bernoulli sign initializer for input/feedback weight matrices.
Each entry is +1 with probability p and -1 otherwise — the
canonical sparse-sign input matrix of the reservoir-computing literature.
Combined with connectivity (the single most common input-matrix recipe:
a fixed density of random ±1 signs per channel) and the shared
input_scaling magnitude knob.
This is the migration target for reservoirpy's
:func:reservoirpy.mat_gen.bernoulli: p matches its p (the
probability of drawing +1), and connectivity matches its
connectivity density argument.
| PARAMETER | DESCRIPTION |
|---|---|
p
|
Probability that an entry is
TYPE:
|
connectivity
|
Density knob from the shared scaling contract (see
:class:
TYPE:
|
input_scaling
|
Uniform magnitude knob from the shared scaling contract.
TYPE:
|
seed
|
Reproducibility seed for the Bernoulli draw and the connectivity mask.
Accepts a plain
TYPE:
|
Notes
The produced matrix is a pure function of (p, connectivity, input_scaling,
seed, shape, device): repeated calls on the same instance with equal
shapes on the same device yield identical matrices. Pass seed=None for a
draw tied to torch's global RNG (reproducible under torch.manual_seed).
Examples:
>>> from resdag.init.input_feedback import BernoulliInputInitializer
>>>
>>> # 10%-sparse balanced ±1 input matrix (a classic sparse input recipe).
>>> init = BernoulliInputInitializer(connectivity=0.1, seed=42)
>>> weight = torch.empty(100, 10) # (reservoir_size, feedback_size)
>>> init.initialize(weight)
>>>
>>> # Use in ESNLayer.
>>> from resdag.layers import ESNLayer
>>> reservoir = ESNLayer(
... reservoir_size=100,
... feedback_size=10,
... feedback_initializer=init,
... )
Source code in src/resdag/init/input_feedback/bernoulli.py
initialize
¶
Initialize weight with Bernoulli ±1 entries.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape
TYPE:
|
**kwargs
|
Per-call keyword overrides. Recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
The initialized weight tensor (same object, modified in-place). |
Source code in src/resdag/init/input_feedback/bernoulli.py
BinaryBalancedInitializer
¶
BinaryBalancedInitializer(input_scaling: float | None = None, balance_global: bool = True, step: int | None = None, seed: int | None = None)
Bases: InputFeedbackInitializer
Deterministic binary balanced initializer using Walsh-Hadamard structure.
Generates a dense input matrix with entries in {-1, +1}, column-wise balance (sum close to zero), and low inter-column correlation via truncated Walsh-Hadamard structure.
The matrix is built without randomness (deterministic) and is suitable for ESN/RC setups where each column (reservoir unit) should receive a balanced mix of positive/negative signs from the input channels, and columns should be nearly orthogonal.
| PARAMETER | DESCRIPTION |
|---|---|
input_scaling
|
Uniform magnitude knob from the shared scaling contract (see
:class:
TYPE:
|
balance_global
|
When rows is odd, enforce near-equal global count of +1 vs -1 column-sums by flipping full columns.
TYPE:
|
step
|
Preferred column selection step. If None or not coprime with L, the initializer will choose the smallest odd step that is coprime with L.
TYPE:
|
seed
|
Unused (kept for API compatibility). The initializer is fully deterministic.
TYPE:
|
Notes
- Column-wise balance: sum over rows per column is exactly 0 if rows even, else ±1.
- Low correlation: columns originate from orthogonal Hadamard columns.
- Deterministic: no RNG is used; the output is reproducible given the shape.
Examples:
>>> from resdag.init.input_feedback import BinaryBalancedInitializer
>>>
>>> init = BinaryBalancedInitializer(input_scaling=0.5, balance_global=True)
>>> weight = torch.empty(100, 10) # (reservoir_size, input_dim)
>>> init.initialize(weight)
>>>
>>> # Each column will have sum close to 0 (balanced)
>>> column_sums = weight.sum(dim=0)
>>> print(column_sums) # Close to zero
Source code in src/resdag/init/input_feedback/binary_balanced.py
initialize
¶
Initialize weight tensor with binary balanced structure.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor |
Source code in src/resdag/init/input_feedback/binary_balanced.py
ChainOfNeuronsInputInitializer
¶
Bases: InputFeedbackInitializer
Input initializer for chain-of-neurons reservoirs.
For reservoirs organized as multiple parallel chains, this initializer connects each input to the first neuron of its corresponding chain.
| PARAMETER | DESCRIPTION |
|---|---|
features
|
Number of chains. Must equal the number of inputs (the weight's
TYPE:
|
weights
|
Either a single float (same weight for all input→chain pairs) or a sequence of floats (one weight per input/chain). |
Examples:
>>> from resdag.init.input_feedback import ChainOfNeuronsInputInitializer
>>>
>>> # Infer the number of chains from the weight (3 columns -> 3 chains)
>>> init = ChainOfNeuronsInputInitializer(weights=1.0)
>>> weight = torch.empty(150, 3) # (reservoir_size, num_inputs)
>>> init.initialize(weight)
>>>
>>> # Or pin it explicitly (validated against the weight shape)
>>> init = ChainOfNeuronsInputInitializer(features=3, weights=1.0)
>>>
>>> # Each input connects only to the first neuron of its chain
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If |
Source code in src/resdag/init/input_feedback/chain_of_neurons_input.py
initialize
¶
Initialize weight tensor for chain-of-neurons topology.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features)
out_features = reservoir_size (units)
in_features = num_inputs (must equal features; when
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If an explicit |
Source code in src/resdag/init/input_feedback/chain_of_neurons_input.py
ChebyshevInitializer
¶
ChebyshevInitializer(p: float = 0.3, q: float = 5.9, k: float = 3.8, input_scaling: float | None = None)
Bases: InputFeedbackInitializer
Chebyshev mapping initializer for deterministic chaotic initialization.
This initializer constructs a weight matrix based on the Chebyshev polynomial map, ensuring structured, chaotic initialization while maintaining a controlled range.
The Chebyshev polynomial recurrence exhibits deterministic chaos, making it a structured alternative to purely random weight initialization. This enhances the richness of how the input signal is connected to the reservoir neurons.
The Chebyshev map is applied column-wise: - First column: W[:, 0] = p * sin((i / (rows+1)) * (π / q)) - Subsequent columns: W[:, j] = cos(k * arccos(W[:, j-1]))
where k controls chaotic behavior (optimal range: 2 < k < 4).
The seed column (column 0) lives on the small amplitude [-p, p] while the
chaotic columns span [-1, 1], so the raw map systematically de-weights the
first feedback dimension (its max|W| is ~p against ~1 elsewhere).
To honor the shared scaling contract — whose magnitude statistic is max|W|
per column for this elementwise initializer — each column is normalized to unit
peak amplitude (divided by its own max|W|) before input_scaling applies.
Every column then peaks at the same input_scaling (or 1 when
input_scaling is None), and the 1D-feedback matrix peaks at input_scaling
rather than the unscaled seed amplitude p.
| PARAMETER | DESCRIPTION |
|---|---|
p
|
Scaling factor for the initial sinusoidal weights. Should be in (0, 1).
TYPE:
|
q
|
Parameter controlling the initial sinusoidal distribution.
TYPE:
|
k
|
Control parameter of the Chebyshev map. Must be in (2, 4) for chaotic behavior.
TYPE:
|
input_scaling
|
Uniform magnitude knob from the shared scaling contract (see
:class:
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If k is not in the valid range (2, 4). |
References
M. Xie, Q. Wang, and S. Yu, "Time Series Prediction of ESN Based on Chebyshev Mapping and Strongly Connected Topology," Neural Process Lett, vol. 56, no. 1, p. 30, Feb. 2024.
Examples:
>>> from resdag.init.input_feedback import ChebyshevInitializer
>>>
>>> init = ChebyshevInitializer(p=0.3, k=3.5, input_scaling=0.8)
>>> weight = torch.empty(100, 10)
>>> init.initialize(weight)
Source code in src/resdag/init/input_feedback/chebyshev.py
initialize
¶
Initialize weight tensor using Chebyshev mapping.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor with Chebyshev structure |
Source code in src/resdag/init/input_feedback/chebyshev.py
ChessboardInitializer
¶
ChessboardInitializer(input_scaling: float | None = None)
Bases: InputFeedbackInitializer
Chessboard pattern initializer with alternating {-1, +1} values.
Creates a deterministic checkerboard pattern where adjacent elements alternate in sign. This creates a structured, high-frequency pattern that can be useful for certain reservoir dynamics.
The pattern is: W[i, j] = (-1)^(i+j)
| PARAMETER | DESCRIPTION |
|---|---|
input_scaling
|
Uniform magnitude knob from the shared scaling contract (see
:class:
TYPE:
|
Examples:
>>> from resdag.init.input_feedback import ChessboardInitializer
>>>
>>> init = ChessboardInitializer(input_scaling=0.5)
>>> weight = torch.empty(5, 10)
>>> init.initialize(weight)
>>>
>>> # Creates alternating pattern:
>>> # [[ 0.5, -0.5, 0.5, -0.5, ...],
>>> # [-0.5, 0.5, -0.5, 0.5, ...],
>>> # [ 0.5, -0.5, 0.5, -0.5, ...],
>>> # ...]
Source code in src/resdag/init/input_feedback/chessboard.py
initialize
¶
Initialize weight tensor with chessboard pattern.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor with chessboard pattern |
Source code in src/resdag/init/input_feedback/chessboard.py
DendrocycleInputInitializer
¶
DendrocycleInputInitializer(c: float | None = None, C: int | None = None, draw_width: float = 1.0, input_scaling: float | None = None, connectivity: float | None = None, seed: int | None = None)
Bases: InputFeedbackInitializer
Input initializer for dendro-cycle reservoirs.
Generates a matrix where only the core (cycle) nodes receive input connections. All other entries are zero. This is specific to dendrocycle topologies where inputs should only connect to the core ring.
Each active connection draws a weight from U[-draw_width, draw_width] and
is then scaled by the shared input_scaling contract. draw_width is the
draw half-width (the spread of the raw distribution); input_scaling is the
uniform final magnitude knob shared by every initializer. With
input_scaling=0.5 every drawn weight is halved, so max|W| scales
linearly with input_scaling (max|W| <= draw_width * input_scaling).
.. note::
Prior to the unified scaling contract, input_scaling here meant the
draw half-width (defaulting to 1.0). That role is now draw_width;
input_scaling is the uniform multiplicative transform shared with every
other initializer and defaults to None (no scaling). To reproduce the
old DendrocycleInputInitializer(input_scaling=s) draw, pass
draw_width=s.
| PARAMETER | DESCRIPTION |
|---|---|
c
|
Fraction of nodes forming the cycle (0 < c <= 1). Provide either c or C.
TYPE:
|
C
|
Number of cycle (core) nodes. If provided, c is ignored.
TYPE:
|
draw_width
|
Half-width of the uniform draw
TYPE:
|
input_scaling
|
Uniform multiplicative scaling applied as the final transform.
TYPE:
|
connectivity
|
Unused by this initializer: dendrocycle defines its own (core-only)
connectivity pattern, so this knob is accepted for API uniformity but
ignored. Always
TYPE:
|
seed
|
Random seed for reproducibility.
TYPE:
|
Examples:
>>> from resdag.init.input_feedback import DendrocycleInputInitializer
>>>
>>> # Initialize for dendrocycle with 20% core nodes, weights in U[-0.5, 0.5]
>>> init = DendrocycleInputInitializer(c=0.2, draw_width=0.5, seed=42)
>>> weight = torch.empty(100, 8) # (reservoir_size, num_inputs)
>>> init.initialize(weight)
>>>
>>> # Only first 20 neurons (core) have non-zero weights
Source code in src/resdag/init/input_feedback/dendrocycle_input.py
initialize
¶
Initialize weight tensor for dendrocycle topology.
The RNG is constructed from self.seed on every call, so the produced
matrix is a pure function of (seed, shape). Repeated calls on the
same instance with equal shapes therefore yield identical matrices.
Pass seed=None for a fresh draw on each call.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features) out_features = reservoir_size (N) in_features = num_inputs (M)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor (only core nodes have non-zero weights) |
Source code in src/resdag/init/input_feedback/dendrocycle_input.py
NormalInputInitializer
¶
NormalInputInitializer(loc: float = 0.0, scale: float = 1.0, connectivity: float | None = None, input_scaling: float | None = None, seed: SeedLike = None)
Bases: InputFeedbackInitializer
Gaussian (normal) initializer for input/feedback weight matrices.
Draws every entry independently from Normal(loc, scale) — the
bread-and-butter dense Gaussian input matrix of the reservoir-computing
literature. Optionally sparsified per input channel via connectivity and
scaled uniformly via the shared input_scaling contract.
This is the migration target for reservoirpy's
:func:reservoirpy.mat_gen.normal (and the "normal" distribution of
:func:reservoirpy.mat_gen.random_sparse).
| PARAMETER | DESCRIPTION |
|---|---|
loc
|
Mean of the Gaussian draw. Defaults to
TYPE:
|
scale
|
Standard deviation of the Gaussian draw (must be non-negative). Defaults
to
TYPE:
|
connectivity
|
Density knob from the shared scaling contract (see
:class:
TYPE:
|
input_scaling
|
Uniform magnitude knob from the shared scaling contract.
TYPE:
|
seed
|
Reproducibility seed for the Gaussian draw and the connectivity mask.
Accepts a plain
TYPE:
|
Notes
The produced matrix is a pure function of (loc, scale, connectivity,
input_scaling, seed, shape, device): repeated calls on the same instance
with equal shapes on the same device yield identical matrices. Pass
seed=None for a draw tied to torch's global RNG (reproducible under
torch.manual_seed).
Examples:
>>> from resdag.init.input_feedback import NormalInputInitializer
>>>
>>> # 10%-sparse standard-normal input matrix.
>>> init = NormalInputInitializer(connectivity=0.1, seed=42)
>>> weight = torch.empty(100, 10) # (reservoir_size, feedback_size)
>>> init.initialize(weight)
>>>
>>> # Use in ESNLayer.
>>> from resdag.layers import ESNLayer
>>> reservoir = ESNLayer(
... reservoir_size=100,
... feedback_size=10,
... feedback_initializer=init,
... )
Source code in src/resdag/init/input_feedback/normal.py
initialize
¶
Initialize weight with Normal(loc, scale) entries.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape
TYPE:
|
**kwargs
|
Per-call keyword overrides. Recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
The initialized weight tensor (same object, modified in-place). |
Source code in src/resdag/init/input_feedback/normal.py
OppositeAnchorsInitializer
¶
Bases: InputFeedbackInitializer
Initializer that connects each input to two opposite anchors on an n-node ring.
Each input channel connects to two anchor nodes on opposite sides of the ring,
with equal-magnitude bipolar weights on both anchors (input_scaling normalized
by sqrt(2), so the per-channel L2 norm equals input_scaling). If the two
anchors coincide (n=1), all weight goes to that single node.
The first (positive) anchor of channel i is placed at round(i * n / m) % n,
spreading the m anchors evenly around the full ring; the second (negative)
anchor is the diametrically opposite node (anchor + n // 2) % n. Spreading over
the full ring (rather than a semicircle) keeps the columns distinct for any
in_features <= reservoir_size, so W_in/W_fb stays full column rank.
This is useful for ring/cycle topologies where you want inputs distributed evenly around the ring with bipolar activation patterns.
Scaling
For this structured initializer the magnitude statistic governed by the shared
contract is the per-channel L2 norm, which equals input_scaling. Hence
input_scaling=0.5 makes every channel's column have L2 norm 0.5 (and,
since each column is two equal-magnitude bipolar entries, max|W| = 0.5/sqrt(2)).
The per-channel L2 norm therefore scales linearly with input_scaling.
Capacity limit
The ring has only n = reservoir_size nodes, so at most n channels can be
assigned distinct anchors. initialize raises ValueError when
in_features > reservoir_size (more channels than nodes), since duplicate
columns would be unavoidable.
| PARAMETER | DESCRIPTION |
|---|---|
input_scaling
|
Per-channel L2 norm of each input column. Defaults to
TYPE:
|
gain
|
Deprecated alias for
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If the resolved scaling is not a positive finite float (at construction),
if both |
Examples:
>>> from resdag.init.input_feedback import OppositeAnchorsInitializer
>>>
>>> init = OppositeAnchorsInitializer(input_scaling=1.0)
>>> weight = torch.empty(100, 5) # (reservoir_size, num_inputs)
>>> init.initialize(weight)
>>>
>>> # Each input connects to two opposite points on the ring
Source code in src/resdag/init/input_feedback/opposite_anchors.py
initialize
¶
Initialize weight tensor with opposite anchor pattern.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features) out_features = number of ring nodes (n) in_features = number of input channels (m)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If |
Source code in src/resdag/init/input_feedback/opposite_anchors.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | |
PseudoDiagonalInitializer
¶
PseudoDiagonalInitializer(input_scaling: float | None = None, binarize: bool = False, seed: int | None = None)
Bases: InputFeedbackInitializer
Pseudo-diagonal initializer for structured input connections.
This initializer creates a structured input weight matrix where each input dimension connects to a contiguous block of reservoir neurons. This creates a "pseudo-diagonal" pattern that can improve input-to-reservoir mapping, especially when input dimensions have semantic meaning.
The connectivity pattern ensures:
- Each reservoir neuron receives input from exactly one input dimension
- Each input dimension connects to approximately N/D reservoir neurons (where N=reservoir size, D=input dimension)
- Connections form contiguous blocks (not random)
| PARAMETER | DESCRIPTION |
|---|---|
input_scaling
|
Uniform magnitude knob from the shared scaling contract (see
:class:
TYPE:
|
binarize
|
Whether to binarize weights to {-input_scaling, input_scaling} instead of uniform distribution.
TYPE:
|
seed
|
Random seed for reproducibility.
TYPE:
|
Examples:
>>> from resdag.init.input_feedback import PseudoDiagonalInitializer
>>>
>>> init = PseudoDiagonalInitializer(input_scaling=1.0, binarize=False, seed=42)
>>> weight = torch.empty(200, 5) # (reservoir_size, input_dim)
>>> init.initialize(weight)
>>>
>>> # Each of the 5 inputs connects to a contiguous block of ~40 neurons
Source code in src/resdag/init/input_feedback/pseudo_diagonal.py
initialize
¶
Initialize weight tensor with pseudo-diagonal structure.
The RNG is constructed from self.seed on every call, so the produced
matrix is a pure function of (seed, shape). Repeated calls on the
same instance with equal shapes therefore yield identical matrices.
Pass seed=None for a fresh draw on each call.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor with block structure |
Source code in src/resdag/init/input_feedback/pseudo_diagonal.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | |
RandomBinaryInitializer
¶
RandomBinaryInitializer(input_scaling: float | None = None, seed: SeedLike = None)
Bases: InputFeedbackInitializer
Binary random initializer for input/feedback weight matrices.
This initializer creates binary weight matrices with values in {-1, +1}. Each weight is randomly chosen to be either -1 or +1, optionally scaled.
Binary weights can be advantageous for: - Memory efficiency (can be stored as bits) - Computational efficiency (multiplication becomes addition/subtraction) - Improved robustness in some cases - Easier interpretation
| PARAMETER | DESCRIPTION |
|---|---|
input_scaling
|
Uniform magnitude knob from the shared scaling contract (see
:class:
TYPE:
|
seed
|
Reproducibility seed for the binary draw. Accepts a plain
TYPE:
|
Examples:
>>> from resdag.init.input_feedback import RandomBinaryInitializer
>>>
>>> # Create binary initializer
>>> init = RandomBinaryInitializer(input_scaling=0.5, seed=42)
>>>
>>> # Initialize weights
>>> weight = torch.empty(100, 10)
>>> init.initialize(weight)
>>>
>>> # All values will be either -0.5 or +0.5
>>> unique_values = torch.unique(weight)
>>> print(unique_values) # tensor([-0.5, 0.5])
Source code in src/resdag/init/input_feedback/random_binary.py
initialize
¶
Initialize weight tensor with binary random values.
The draw uses a :class:torch.Generator built from self.seed on the
target weight's device (no CPU build + copy), so the produced matrix
is a pure function of (seed, shape, device). Repeated calls on the
same instance with equal shapes on the same device therefore yield
identical matrices. Pass seed=None for a draw tied to torch's global
RNG (reproducible under torch.manual_seed).
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor with binary values |
Source code in src/resdag/init/input_feedback/random_binary.py
RandomInputInitializer
¶
RandomInputInitializer(input_scaling: float | None = None, seed: SeedLike = None)
Bases: InputFeedbackInitializer
Random initializer for feedback/input weight matrices.
This initializer creates random weight matrices connecting inputs (feedback or external) to reservoir neurons. Values are sampled uniformly from [-1, 1] and optionally scaled by an input scaling factor.
This is a simple, commonly used initializer for input connections. It provides random, unstructured connectivity from inputs to the reservoir.
| PARAMETER | DESCRIPTION |
|---|---|
input_scaling
|
Uniform magnitude knob from the shared scaling contract (see
:class:
TYPE:
|
seed
|
Reproducibility seed for the uniform draw. Accepts a plain
TYPE:
|
Notes
Input Scaling:
The input_scaling parameter controls how strongly input signals affect the reservoir: - Low scaling (0.1-0.5): Weak input influence, reservoir dynamics dominate - Moderate scaling (0.5-1.0): Balanced input and reservoir dynamics - High scaling (1.0-5.0): Strong input influence, input-driven dynamics
Usage:
This initializer is typically used for: - Feedback weights: How feedback signals enter the reservoir - Input weights: How external inputs enter the reservoir (if used)
Best Practices:
- Start with input_scaling=1.0 and tune based on performance
- Lower scaling often works better for chaotic systems
- Higher scaling can help when inputs are weak or noisy
- Use seed for reproducibility
Examples:
>>> from resdag.init.input_feedback import RandomInputInitializer
>>>
>>> # Create initializer
>>> init = RandomInputInitializer(input_scaling=1.0, seed=42)
>>>
>>> # Initialize a weight tensor
>>> weight = torch.empty(100, 10) # (reservoir_size, feedback_size)
>>> init.initialize(weight)
>>>
>>> # Use in ESNLayer
>>> reservoir = ESNLayer(
... reservoir_size=100,
... feedback_size=10,
... feedback_initializer=init
... )
Source code in src/resdag/init/input_feedback/random.py
initialize
¶
Initialize weight tensor with uniform random values.
The draw uses a :class:torch.Generator built from self.seed on the
target weight's device (no CPU build + copy), so the produced matrix
is a pure function of (seed, shape, device). Repeated calls on the
same instance with equal shapes on the same device therefore yield
identical matrices. Pass seed=None for a draw tied to torch's global
RNG (reproducible under torch.manual_seed).
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor |
Source code in src/resdag/init/input_feedback/random.py
RingWindowInputInitializer
¶
RingWindowInputInitializer(c: float, window: int | float, taper: str = 'flat', signed: str = 'allpos', input_scaling: float | None = None, gain: float | None = None)
Bases: InputFeedbackInitializer
Deterministic windowed input initializer for ring-based topologies.
Feeds each input channel into a contiguous window on the core ring of a dendrocycle(+chords) reservoir. Only the first C = round(c * n) columns (core) receive nonzeros.
Scaling
For this structured initializer the magnitude statistic governed by the shared
contract is the per-channel L2 norm, which equals input_scaling: each
channel's window vector is renormalized so its L2 norm is exactly
input_scaling. Hence input_scaling=0.5 makes every channel's column have
L2 norm 0.5; the per-channel L2 norm scales linearly with input_scaling.
| PARAMETER | DESCRIPTION |
|---|---|
c
|
Fraction of core ring nodes. First round(c*n) columns are core.
TYPE:
|
window
|
If int >= 1: number of core nodes per channel window. If float in (0, 1]: fraction of C per channel window (rounded >= 1). |
taper
|
Weight profile within a channel's window centered on its center index.
TYPE:
|
signed
|
Sign policy for weights.
TYPE:
|
input_scaling
|
Per-channel L2-norm after taper/sign are applied. Defaults to
TYPE:
|
gain
|
Deprecated alias for
TYPE:
|
Examples:
>>> from resdag.init.input_feedback import RingWindowInputInitializer
>>>
>>> init = RingWindowInputInitializer(
... c=0.5, window=10, taper="cosine", signed="alt_ring", input_scaling=1.0
... )
>>> weight = torch.empty(100, 5) # (reservoir_size, num_inputs)
>>> init.initialize(weight)
>>>
>>> # Each input connects to a windowed region of the core ring
Source code in src/resdag/init/input_feedback/ring_window.py
initialize
¶
Initialize weight tensor with ring window pattern.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape (out_features, in_features) out_features = reservoir_size (n) in_features = num_inputs (m)
TYPE:
|
**kwargs
|
Per-call keyword overrides. A recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Initialized weight tensor |
Source code in src/resdag/init/input_feedback/ring_window.py
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | |
UniformInputInitializer
¶
UniformInputInitializer(low: float = -1.0, high: float = 1.0, connectivity: float | None = None, input_scaling: float | None = None, seed: SeedLike = None)
Bases: InputFeedbackInitializer
Bounded uniform initializer for input/feedback weight matrices.
Draws every entry independently from Uniform(low, high). Unlike the
baseline random initializer (fixed [-1, 1]), the bounds are
configurable, so asymmetric or narrow ranges are expressible directly.
Optionally sparsified per input channel via connectivity and scaled
uniformly via the shared input_scaling contract.
This is the migration target for reservoirpy's
:func:reservoirpy.mat_gen.uniform (and the "uniform" distribution of
:func:reservoirpy.mat_gen.random_sparse).
| PARAMETER | DESCRIPTION |
|---|---|
low
|
Inclusive lower bound of the uniform draw. Defaults to
TYPE:
|
high
|
Exclusive upper bound of the uniform draw. Defaults to
TYPE:
|
connectivity
|
Density knob from the shared scaling contract (see
:class:
TYPE:
|
input_scaling
|
Uniform magnitude knob from the shared scaling contract.
TYPE:
|
seed
|
Reproducibility seed for the uniform draw and the connectivity mask.
Accepts a plain
TYPE:
|
Notes
The produced matrix is a pure function of (low, high, connectivity,
input_scaling, seed, shape, device): repeated calls on the same instance
with equal shapes on the same device yield identical matrices. Pass
seed=None for a draw tied to torch's global RNG (reproducible under
torch.manual_seed).
Examples:
>>> from resdag.init.input_feedback import UniformInputInitializer
>>>
>>> # A narrow, asymmetric uniform input matrix.
>>> init = UniformInputInitializer(low=0.0, high=0.5, seed=42)
>>> weight = torch.empty(100, 10) # (reservoir_size, feedback_size)
>>> init.initialize(weight)
>>>
>>> # Use in ESNLayer.
>>> from resdag.layers import ESNLayer
>>> reservoir = ESNLayer(
... reservoir_size=100,
... feedback_size=10,
... feedback_initializer=init,
... )
Source code in src/resdag/init/input_feedback/uniform.py
initialize
¶
Initialize weight with Uniform(low, high) entries.
| PARAMETER | DESCRIPTION |
|---|---|
weight
|
Weight tensor of shape
TYPE:
|
**kwargs
|
Per-call keyword overrides. Recognized
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
The initialized weight tensor (same object, modified in-place). |
Source code in src/resdag/init/input_feedback/uniform.py
ZeroInitializer
¶
Bases: InputFeedbackInitializer
Initializer that sets all weights to zero.
Source code in src/resdag/init/input_feedback/zero.py
initialize
¶
get_input_feedback
¶
get_input_feedback(name: str, **override_kwargs: Any) -> InputFeedbackInitializer
Get a pre-configured input/feedback initializer by name.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Name of the initializer (e.g., "random", "binary_balanced")
TYPE:
|
**override_kwargs
|
Keyword arguments to override default initializer parameters
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
InputFeedbackInitializer
|
Initializer instance |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If initializer name is not registered |
Examples:
>>> initializer = get_input_feedback("binary_balanced", input_scaling=0.5)
>>> weight = torch.empty(100, 10)
>>> initializer.initialize(weight)
Source code in src/resdag/init/input_feedback/registry.py
register_input_feedback
¶
Decorator to register an input/feedback initializer.
Registers either an :class:InputFeedbackInitializer subclass or a
plain matrix-building function in the registry at definition time,
making it available by name to ESNLayer and other components.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Name for the initializer (must be unique)
TYPE:
|
**default_kwargs
|
Default keyword arguments for the initializer constructor (classes) or for the function call (plain functions)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
callable
|
Decorator function |
Examples:
Registering a class:
>>> @register_input_feedback("my_init", scaling=0.5)
... class MyInitializer(InputFeedbackInitializer):
... def __init__(self, scaling=1.0):
... self.scaling = scaling
...
... def initialize(self, weight, **kwargs):
... # ... initialization logic
... return weight
Registering a plain function (build style — return the matrix):
>>> @register_input_feedback("first_neuron", scale=1.0)
... def first_neuron(rows, cols, scale=1.0):
... w = torch.zeros(rows, cols)
... w[0, :] = scale
... return w
Notes
- Classes must inherit from
InputFeedbackInitializerand implementinitialize(weight, **kwargs). - Functions follow the :class:
FunctionInitializerconventions:fn(rows, cols, **kwargs) -> matrixor in-placefn(tensor, **kwargs). - Registered initializers can be accessed via
get_input_feedback(name).
Source code in src/resdag/init/input_feedback/registry.py
show_input_initializers
¶
Show available input/feedback initializers or details for a specific one.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Name of initializer to inspect. If None, prints all initializers and returns them as a list.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list of str or None
|
When |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If the specified initializer name is not registered. |
Examples:
Source code in src/resdag/init/input_feedback/registry.py
matrices
¶
Matrix-Builder Topologies¶
Direct matrix-construction functions registered as topologies — the
non-graph counterpart of :mod:resdag.init.graphs. Each function takes the
matrix size n first, returns an (n, n) matrix, and is registered via
:func:~resdag.init.topology.register_matrix_topology, making it available
by name in ESNLayer(topology="...").
| FUNCTION | DESCRIPTION |
|---|---|
orthogonal_matrix |
Haar-random orthogonal matrix via QR decomposition ( |
antisymmetric_matrix |
Random antisymmetric (skew-symmetric) matrix |
fast_spectral_initialization |
Recurrent matrix built at a target spectral radius analytically, with no
eigendecomposition ( |
delay_line, delay_line_backward, simple_cycle, cycle_jumps, self_loop_cycle |
Deterministic-minimal (Rodan & Tiňo) reservoirs — a pure delay line, a
delay line with a backward connection, a unidirectional cycle, a cycle with
regular jumps, and a self-loop cycle ( |
toeplitz, band, block_diagonal |
Structured reservoirs — a Toeplitz (constant-per-diagonal) matrix, a banded
matrix, and a block-diagonal matrix ( |
See Also
resdag.init.graphs : Graph-based topology generators. resdag.init.topology : Registry and initializer classes.
orthogonal_matrix
¶
Build a random orthogonal matrix via QR decomposition.
Draws a standard Gaussian matrix, takes its QR decomposition, and fixes the signs so the result is drawn from the Haar (uniform) distribution over orthogonal matrices.
This topology is pre-scaled: an orthogonal matrix already has all its
singular values equal to gain (norm-preserving for gain=1), which is
the structural property it exists to provide. Because the layer-level
spectral-radius rescale would collapse every singular value to the target
radius and destroy that property, it is suppressed for this topology. A
layer spectral_radius passed alongside this topology is therefore
ignored (with a warning); control the scale through gain instead. The
singular-values-equal-1 / norm-preservation property holds only in this
regime (no outer rescale applied).
| PARAMETER | DESCRIPTION |
|---|---|
n
|
Matrix size (number of reservoir units).
TYPE:
|
gain
|
Scaling factor applied to the orthogonal matrix. With
TYPE:
|
seed
|
Seed for the Gaussian draw.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Orthogonal matrix of shape |
Examples:
>>> from resdag.layers import ESNLayer
>>> reservoir = ESNLayer(500, feedback_size=3, topology="orthogonal")
>>> reservoir = ESNLayer(
... 500, feedback_size=3, topology=("orthogonal", {"seed": 42})
... )
Source code in src/resdag/init/matrices/orthogonal.py
utils
¶
Initialization utility functions.
TopologySpec
module-attribute
¶
InitializerSpec
module-attribute
¶
InitializerSpec = None | str | Callable | tuple[str | Callable, dict[str, Any]] | InputFeedbackInitializer
resolve_topology
¶
resolve_topology(spec: TopologySpec, seed: SeedLike = None) -> TopologyInitializer | None
Resolve a topology specification to a TopologyInitializer object.
Accepts six formats:
None— returns None (use default random initialization)str— registry name, uses registered default parameterstuple[str, dict]— registry name with parameter overridescallable— any matrix builderfn(n, **kw) -> matrix | graphor in-placefn(tensor, **kw); wrapped in :class:MatrixTopologytuple[callable, dict]— matrix builder with bound parametersTopologyInitializer— already resolved, returned as-is
| PARAMETER | DESCRIPTION |
|---|---|
spec
|
Topology specification in one of the accepted formats.
TYPE:
|
seed
|
Seed forwarded to the underlying builder for reproducibility. It is
applied only to the |
| RETURNS | DESCRIPTION |
|---|---|
TopologyInitializer or None
|
Resolved topology object, or None if spec was None. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If spec is not one of the accepted types. |
Examples:
Source code in src/resdag/init/utils/resolve.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | |
resolve_initializer
¶
resolve_initializer(spec: InitializerSpec, seed: SeedLike = None) -> InputFeedbackInitializer | None
Resolve an initializer specification to an InputFeedbackInitializer object.
Accepts six formats:
None— returns None (use default random initialization)str— registry name, uses registered default parameterstuple[str, dict]— registry name with parameter overridescallable— any matrix builderfn(rows, cols, **kw) -> matrixor in-placefn(tensor, **kw); wrapped in :class:FunctionInitializertuple[callable, dict]— matrix builder with bound parametersInputFeedbackInitializer— already resolved, returned as-is
| PARAMETER | DESCRIPTION |
|---|---|
spec
|
Initializer specification in one of the accepted formats.
TYPE:
|
seed
|
Seed forwarded to the underlying initializer for reproducibility. It
is applied only to the |
| RETURNS | DESCRIPTION |
|---|---|
InputFeedbackInitializer or None
|
Resolved initializer object, or None if spec was None. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If spec is not one of the accepted types. |
Examples:
Source code in src/resdag/init/utils/resolve.py
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | |