Layers
A SILVA layer separates an equilibrium transition into stimulus, optional learned self interaction, local interaction, and global context:
The public package keeps each term replaceable while preserving the fixed-point solve.
The layer contract is defined by SILVA [1] and its equilibrium framing connects to DEQ [4]. Local and global choices use the appropriate GCN [15], GAT [16], MPNN [17], Deep Sets [18], or attention [29] lineage.
The solver supplies the default self-persistence term:
An optional learned self branch can be added inside \(f_\theta\):
Reduction Factories
The same layer grammar can be specialized into familiar implicit models:
| Factory | Active branches | Equation |
|---|---|---|
silva_generalized_layer |
user-selected \(H,L,G\) | \(z^\star=\Psi(S+H+L+G)\) |
silva_deq_reduction_layer |
stimulus plus linear self | \(z^\star=\tanh(W_xx+W_zz^\star+b)\) |
silva_message_passing_reduction_layer |
stimulus plus local graph operator | \(z^\star=\Psi(S+L)\) |
from silva_networks import SolverConfig, silva_deq_reduction_layer
layer = silva_deq_reduction_layer(
in_dim=8,
hidden_dim=32,
config=SolverConfig(solver="anderson", max_iter=20, alpha=0.6),
)
Tensor Shapes
Entity and graph layers use
| Symbol | Shape | Meaning |
|---|---|---|
| \(x\) | (entities, in_dim) |
Input features |
| \(z\) | (entities, hidden_dim) |
Equilibrium state |
edge_index |
(2, edges) |
Source and destination indices |
batch |
(entities,) |
Graph/set id for each entity |
Image layers use
| Symbol | Shape | Meaning |
|---|---|---|
| \(x\) | (batch, channels, height, width) |
Image tensor |
| \(z\) | (batch, hidden_channels, height, width) |
Equilibrium feature map |
Stimulus Branch
The default stimulus branch is affine:
Graph Local Branch
For directed edges \(i\to j\), define the incoming neighborhood
GraphLocal first computes messages
Then it averages incoming messages:
Top-K Local Branch
TopKLocal builds a dynamic neighborhood from the current state:
Then
Mean-Field Global Branch
For one graph or set,
Broadcasting a learned projection gives
When batch is provided, this computation is performed independently for each
graph id.
Operator Choices
Use the literal string "none" to remove a branch. In the generic constructors,
Python None means "use the constructor default" for local/global branches, while
self_term=None is the SILVA default \(H_\theta=0\). The table below uses the
explicit string values that make ablation experiments reproducible.
| Argument | Value | Implemented class | Computation |
|---|---|---|---|
local |
"graph" |
GraphLocal |
Degree-normalized edge aggregation |
local |
"gat" or "graph_attention" |
GraphAttentionLocal |
GAT-style learned edge attention |
local |
"topk" |
TopKLocal |
Dynamic nearest-neighbor aggregation in feature space |
local |
"channel_knn" or "vision_knn" |
DynamicChannelLocal |
Hidden-channel kNN used by vector vision models |
local |
"none" |
ZeroTerm |
Removes local interaction |
global_term |
"mean" |
MeanFieldGlobal |
Mean-field broadcast |
global_term |
"simple" or "gated_mean" |
GatedMeanFieldGlobal |
Scalar-gated mean-field broadcast |
global_term |
"static" |
StaticMeanFieldGlobal |
Non-gated mean-field broadcast |
global_term |
"topk" or "topk_attention" |
TopKGlobalAttention |
Bounded node-to-node global attention |
global_term |
"channel_attention" |
ChannelSelfAttentionGlobal |
Per-sample hidden-channel attention |
global_term |
"multi_head_channel_attention" |
MultiHeadChannelAttentionGlobal |
Multi-head channel-attention variant |
global_term |
"static_channel" |
StaticChannelGlobal |
Learned dense channel matrix |
global_term |
"none" |
ZeroTerm |
Removes global interaction |
self_term |
"linear" |
SelfInteraction |
Learned node-wise/channel-wise self map |
self_term |
"identity" |
IdentityTerm |
Adds the current recurrent signal |
self_term |
"none" |
ZeroTerm |
SILVA default; solver damping still supplies self-persistence |
Gated Mean Field
The gated global branch first computes
The scalar gate is
Every node receives
With a batch vector, each graph in the minibatch has its own \(g\), gate
\(\beta\), and broadcast.
Bounded Global Attention
The top-k global branch computes query-key scores
For each receiver \(i\), keep the \(k\) highest-scoring sources:
The output is
This mode restores differentiated node-to-node global context while bounding the softmax support.
Custom Branches
Any torch.nn.Module can replace the local or global branch if it returns a
tensor with the same shape as \(z\). The wrapper passes available context by
keyword: x, edge_index, edge_attr, and batch when the module accepts
those names.
import torch
from silva_networks import SILVALayer, SolverConfig
class MyLocal(torch.nn.Module):
def __init__(self, dim):
super().__init__()
self.weight = torch.nn.Linear(dim, dim, bias=False)
def forward(self, z, edge_index=None):
return torch.sin(self.weight(z))
layer = SILVALayer(
in_dim=5,
hidden_dim=32,
local=MyLocal(32),
global_term="simple",
self_term="linear",
config=SolverConfig(solver="anderson", max_iter=12, alpha=0.4),
)
Composable SILVA interaction layers.
The layer primitives in this module implement the stimulus/local/global/self operator vocabulary used throughout the package. The graph-attention branch follows the GAT mechanism of Velickovic et al. (2018), the channel-attention branches use scaled dot-product attention in the style of Vaswani et al. (2017), and the dynamic hidden-channel kNN branch follows the state-dependent neighborhood idea used in the SILVA vision experiments.
ChannelSelfAttentionGlobal
Bases: Module
Per-sample dense channel self-attention used by vision SILVA models.
This branch uses scaled dot-product attention (Vaswani et al., 2017) over the hidden channels of each sample independently. It never pools across the batch dimension.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
Number of hidden channels. |
required |
bias
|
bool
|
Whether to include bias in query and key projections. |
True
|
Inputs
z: Tensor with shape (batch, channels).
Output
Tensor: Tensor with shape (batch, channels).
Source code in src/silva_networks/layers.py
DEQLayer
Bases: Module
Wrap a transition f(z, *args, **kwargs) as a fixed-point layer.
Source code in src/silva_networks/layers.py
DynamicChannelLocal
Bases: Module
Hidden-channel k-nearest-neighbor local branch for vector vision models.
The entities are channels inside one sample's hidden vector. The branch builds a kNN graph from current recurrent channel values and averages over that dynamic graph, matching the vector-vision SILVA experiments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
Number of hidden channels. |
required |
k
|
int
|
Number of channel neighbors. |
4
|
bias
|
bool
|
Whether to include bias in the channel projection. |
True
|
Inputs
z: Tensor with shape (batch, channels).
Output
Tensor: Tensor with shape (batch, channels).
Source code in src/silva_networks/layers.py
GatedMeanFieldGlobal
Bases: Module
Scalar-gated mean-field broadcast for graph-scale SILVA layers.
For one graph, this module computes
g = mean_i z_i,
beta = sigmoid(<W_q g, W_k g> / sqrt(dim)), and
G_i = beta W_g g for every node i. When batch is supplied,
the same computation is performed independently inside each graph.
This branch implements the O(N) global term used by the SILVA node-classification and graph-benchmark experiments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
State dimension. |
required |
bias
|
bool
|
Whether to include bias in the query, key, and value projections. |
True
|
Inputs
z: Tensor with shape (entities, dim).
batch: Optional graph id tensor with shape (entities,).
Output
Tensor: Tensor with the same shape as z.
Source code in src/silva_networks/layers.py
GraphAttentionLocal
Bases: Module
Pure PyTorch graph-attention local branch.
The module follows the GAT receiver/source scoring pattern over an
edge_index tensor without requiring a graph-library runtime. Edges are
interpreted as source -> destination.
Reference: Velickovic et al., "Graph Attention Networks", ICLR 2018.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
State dimension. |
required |
heads
|
int
|
Number of attention heads. |
4
|
edge_dim
|
int | None
|
Optional edge-attribute dimension for bond-aware attention. |
None
|
concat
|
bool
|
If true, concatenate heads to recover |
True
|
leaky_relu_slope
|
float
|
Negative slope used in the attention score. |
0.2
|
add_self_loops
|
bool
|
Whether to add self-loop edges internally. |
False
|
bias
|
bool
|
Whether the output projection has bias when |
False
|
Inputs
z: Tensor with shape (nodes, dim).
edge_index: Tensor with shape (2, edges).
edge_attr: Optional tensor with shape (edges, edge_dim).
Output
Tensor: Tensor with shape (nodes, dim).
Source code in src/silva_networks/layers.py
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 | |
GraphLocal
Bases: Module
Mean aggregation over edge_index followed by a learnable channel map.
This is the non-attentive message-passing baseline related to GCN/message passing networks (Kipf and Welling, 2017; Gilmer et al., 2017).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
State dimension. |
required |
bias
|
bool
|
Whether to include bias in the channel map. |
False
|
self_loop_when_empty
|
bool
|
If true and |
True
|
Inputs
z: Tensor with shape (nodes, dim).
edge_index: Optional tensor with shape (2, edges), source row first.
Output
Tensor: Tensor with shape (nodes, dim).
Source code in src/silva_networks/layers.py
IdentityTerm
Bases: Module
Return the incoming state unchanged.
Inputs
z: Any tensor.
Output
Tensor: The same tensor object passed as z.
Source code in src/silva_networks/layers.py
MeanFieldGlobal
Bases: Module
Permutation-invariant mean-field branch for entity states.
The module computes one mean state per graph or set and broadcasts a learned channel projection back to all entities in that graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
State dimension. |
required |
bias
|
bool
|
Whether to include bias in the projection. |
True
|
Inputs
z: Tensor with shape (entities, dim).
batch: Optional graph id tensor with shape (entities,).
Output
Tensor: Tensor with the same shape as z.
Source code in src/silva_networks/layers.py
MultiHeadChannelAttentionGlobal
Bases: Module
Multi-head channel-attention matrix variant from the vision sweeps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
Number of hidden channels. |
required |
heads
|
int
|
Number of attention heads. |
4
|
bias
|
bool
|
Whether to include bias in the projections. |
True
|
Inputs
z: Tensor with shape (batch, channels).
Output
Tensor: Tensor with shape (batch, channels).
Source code in src/silva_networks/layers.py
SILVAGraphLayer
Bases: SILVALayer
SILVA layer specialized to graph node states.
Source code in src/silva_networks/layers.py
SILVAImageLayer
Bases: Module
SILVA-style equilibrium over image feature maps.
Source code in src/silva_networks/layers.py
SILVALayer
Bases: Module
Generic stimulus/local/global/self SILVA layer for entity states.
The implemented transition is
optionally followed by normalization. Here activation is the state
preactivation \(a\), and output_activation is the outer nonlinearity
\(\Psi\). Setting local="none", global_term="none",
self_term="linear", activation=torch.nn.Identity(),
output_activation=torch.tanh, and normalize=False recovers the compact
affine-tanh DEQ transition.
Source code in src/silva_networks/layers.py
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 | |
SelfInteraction
Bases: Module
Optional learned self-interaction branch.
The SILVA study's default self term is the damped solver persistence
(1 - alpha) z_k. This module is for extensions where a user also wants
a learned node-wise or channel-wise self map inside f_theta itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
State dimension. |
required |
bias
|
bool
|
Whether the self projection includes bias. |
False
|
Inputs
z: Tensor with final dimension dim.
Output
Tensor: Tensor with the same shape as z.
Source code in src/silva_networks/layers.py
StaticChannelGlobal
Bases: Module
Learned dense channel matrix used by the MNIST diagnostic path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
Number of hidden channels. |
required |
orientation
|
Literal['left', 'right']
|
Matrix multiplication convention, either |
'left'
|
Inputs
z: Tensor with shape (batch, channels).
Output
Tensor: Tensor with shape (batch, channels).
Source code in src/silva_networks/layers.py
StaticMeanFieldGlobal
Bases: MeanFieldGlobal
Non-gated mean-field broadcast used by static global ablations.
This is the SILVA study's static global-context alternative: it keeps the graph/set mean and removes the learned scalar gate.
Source code in src/silva_networks/layers.py
StimulusEncoder
Bases: Module
Map external input into the recurrent SILVA state dimension.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
in_dim
|
int
|
Number of input features per entity. |
required |
hidden_dim
|
int
|
Number of recurrent state features per entity. |
required |
normalize
|
bool
|
If true, apply |
False
|
Inputs
x: Tensor with shape (entities, in_dim).
Output
Tensor: Tensor with shape (entities, hidden_dim).
Source code in src/silva_networks/layers.py
TinySILVALayer
Bases: SILVAGraphLayer
Backward-compatible educational SILVA layer used by the tutorials.
Source code in src/silva_networks/layers.py
TopKGlobalAttention
Bases: Module
Bounded node-to-node global attention.
Each receiver attends to its k largest query-key scores inside the same
graph. This is the bounded global-attention variant used in the SILVA study's
node-classification ablations.
The attention score is the scaled dot product introduced by Vaswani et al. (2017), restricted to a top-k source set for each receiver.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
State dimension. |
required |
k
|
int
|
Maximum number of attended source entities per receiver. |
16
|
bias
|
bool
|
Whether to include bias in the query, key, and value projections. |
True
|
Inputs
z: Tensor with shape (entities, dim).
batch: Optional graph id tensor with shape (entities,).
Output
Tensor: Tensor with the same shape as z.
Source code in src/silva_networks/layers.py
TopKLocal
Bases: Module
Dynamic k-nearest-neighbor local branch for entity states.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
State dimension. |
required |
k
|
int
|
Number of nearest neighbors per entity. |
4
|
bias
|
bool
|
Whether to include bias in the projection. |
False
|
Inputs
z: Tensor with shape (entities, dim).
Output
Tensor: Tensor with shape (entities, dim).
Source code in src/silva_networks/layers.py
ZeroTerm
Bases: Module
Return a zero contribution with the same shape, device, and dtype.
Inputs
z: Any tensor.
Output
Tensor: torch.zeros_like(z).
Source code in src/silva_networks/layers.py
make_global_operator
Create a built-in global operator for a SILVA layer.
Source code in src/silva_networks/layers.py
make_local_operator
Create a built-in local operator for a SILVA layer.
Source code in src/silva_networks/layers.py
make_self_operator
Create a built-in self operator for a SILVA layer.
Source code in src/silva_networks/layers.py
silva_deq_reduction_layer
Create the compact DEQ reduction inside the SILVA operator grammar.
The returned layer computes
by disabling the local and global branches and keeping a learned linear self branch. This is the direct reduction to the affine-tanh DEQ transition used in the package tutorials.
Source code in src/silva_networks/layers.py
silva_generalized_layer
silva_generalized_layer(in_dim, hidden_dim, *, local='graph', global_term='mean', self_term=None, config=None, activation=torch.tanh, output_activation=torch.tanh, normalize=True, local_kwargs=None, global_kwargs=None, self_kwargs=None)
Create a fully configurable SILVA equilibrium layer.
This factory is the most direct package entry point for the generalized
SILVA form. Built-in strings choose local, global, and self operators;
custom torch.nn.Module instances can be supplied for any branch.
Source code in src/silva_networks/layers.py
silva_message_passing_reduction_layer
silva_message_passing_reduction_layer(in_dim, hidden_dim, *, config=None, local='graph', normalize=True, local_kwargs=None)
Create a graph/message-passing DEQ reduction.
The returned layer keeps the stimulus and local graph branch and disables the global and learned self branches:
Passing local="gat" gives a GAT-style local operator; passing
local="graph" gives mean message passing.
Source code in src/silva_networks/layers.py
Where to Go Next
| Question | Page |
|---|---|
| How is a SILVA layer assembled from first principles? | SILVA From Scratch |
| Where is the graph layer executed? | Graph SILVA Example |
| How are several layers organized? | Architectures API |