Introduction by Example
This page introduces SILVA through one complete path: create a tensor problem, choose an interaction field, solve the equilibrium, train a PyTorch model, and inspect the solver diagnostics.
SILVA models keep the state equation visible:
In code, the equilibrium state is the output of a torch.nn.Module.
import torch
from silva_networks import SILVAGraphNetwork, SolverConfig
x = torch.randn(6, 4)
edge_index = torch.tensor(
[[0, 1, 2, 3, 4, 5],
[1, 2, 3, 4, 5, 0]],
dtype=torch.long,
)
model = SILVAGraphNetwork(
in_dim=4,
hidden_dims=[16, 16],
out_dim=3,
task="node",
local="graph",
global_term="mean",
config=SolverConfig(solver="picard", max_iter=12, alpha=0.5),
)
logits = model(x, edge_index=edge_index)
Data Handling
The tensor convention mirrors the graph-data style used by PyTorch Geometric:
node or entity features live in x, graph connectivity lives in a COO
edge_index tensor, edge features live in edge_attr, and graph membership
lives in batch. SILVA uses this convention without requiring a graph-library
runtime.
| Attribute | Shape | Meaning |
|---|---|---|
x |
(entities, features) |
input features for nodes, samples, atoms, pixels, or other entities |
edge_index |
(2, edges) |
source row followed by destination row |
edge_attr |
(edges, edge_features) or (edges,) |
optional relation, bond, or distance features |
batch |
(entities,) |
graph/set id for each entity in a packed batch |
y |
task-specific | labels or regression targets |
The package container is GraphTensorBatch:
from silva_networks import GraphTensorBatch
batch = GraphTensorBatch(x=x, edge_index=edge_index)
batch.validate()
batch.num_entities, batch.num_edges
The validation checks the parts that commonly break experiments: edge_index
shape, integer dtype, index range, edge_attr length, and batch length.
From Public Data to SILVA
For tabular data, each row can become one entity. First standardize the feature geometry,
then build a k-nearest-neighbor interaction graph:
The edge convention is source -> destination, so \(j\in\mathcal N_k(i)\)
produces edge \((j,i)\).
from silva_networks import load_tabular_dataset, tabular_to_silva_graph
dataset = load_tabular_dataset("wine", root="data", download=True, normalize=True)
graph = tabular_to_silva_graph(dataset, k=8, normalize=True, undirected=True)
graph.validate()
The same adapter works with a private matrix:
Mini-Batches
Packed graph batches concatenate node features and keep graph membership in
batch. For two graphs,
The batch vector records which rows belong to graph \(1\) and graph \(2\).
Global SILVA terms use it to compute graph-specific context:
from silva_networks import MeanFieldGlobal
global_term = MeanFieldGlobal(dim=16)
context = global_term(torch.randn(10, 16), batch=torch.tensor([0] * 4 + [1] * 6))
Learning Method
A SILVA graph network solves one or more equilibrium blocks, then applies a readout:
Training remains standard PyTorch:
target = graph.y
optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)
for step in range(10):
result = model(
graph.x,
edge_index=graph.edge_index,
batch=graph.batch,
return_results=True,
)
loss = torch.nn.functional.cross_entropy(result.output, target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
The solver diagnostics are available without changing the model:
Derivation-to-Code Map
| Equation piece | Package object | Code |
|---|---|---|
| \(S_\theta(x)\) | StimulusEncoder |
self.stimulus(x) |
| \(L_\theta(z,E)\) | GraphLocal, GraphAttentionLocal, TopKLocal, custom module |
local(z, edge_index=edge_index) |
| \(G_\theta(z,b)\) | MeanFieldGlobal, GatedMeanFieldGlobal, TopKGlobalAttention, custom module |
global_term(z, batch=batch) |
| \(z_{k+1}=(1-\alpha)z_k+\alpha f(z_k)\) | SolverConfig(alpha=...) |
fixed_point(f, z0, config) |
| \(\rho(J_f(z^\star))\) | Jacobian diagnostics | stability_report(f, z_star) |
The next pages make each of these pieces explicit and show how to adapt new datasets into the same engine.
References: PyTorch Geometric documentation, PyG introduction by example.
Where to Go Next
| Question | Page |
|---|---|
| How do tensors and batches enter the transition? | Data Objects and Batching |
| How does each equation become package code? | Derivations to Code |
| How is a complete SILVA layer assembled? | SILVA From Scratch |