TGraphX Quickstart: From Install to First Working Experiment
This tutorial walks from installation to a complete, working graph learning experiment in under 30 minutes. It targets researchers and engineers who are new to TGraphX and want to get something running before reading deeper documentation.
By the end of this tutorial you will have:
- TGraphX installed and verified
- A synthetic tensor-valued graph constructed
- A GNN layer applied and shapes confirmed
- A full training loop running with reproducible seeding
- A basic understanding of what to read next
Prerequisites
- Python 3.10 or later
- PyTorch 1.13 or later (install separately if needed)
- No PyG, DGL, or other GNN libraries required
Step 1: Install TGraphX
pip install tgraphx
For CPU-only PyTorch (common for laptops or CI environments):
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
pip install tgraphx
To verify the installation, run the built-in doctor:
python -m tgraphx doctor
This checks that core modules import, that a minimal forward pass completes, and reports any missing optional extras. You should see no errors for the base installation.
Step 2: Verify the Installation in Python
import tgraphx as tgx
# Check version and public API
print(tgx.__version__)
print(tgx.api_status("Graph")) # → "stable"
print(tgx.api_status("workflow")) # → "beta"
Step 3: Create Your First Graph
TGraphX graphs carry tensor-valued node features. The simplest graph has vector features [N, D]:
import torch
from tgraphx import Graph
# 50 nodes, each with a 32-dimensional feature vector
x = torch.randn(50, 32)
# A random sparse edge list: [2, E] with dtype=torch.long
edge_index = torch.stack([
torch.randint(0, 50, (150,)),
torch.randint(0, 50, (150,)),
]).long()
# Node labels for classification (4 classes)
labels = torch.randint(0, 4, (50,))
g = Graph(node_features=x, edge_index=edge_index, node_labels=labels)
print(g.num_nodes) # 50
print(g.node_features.shape) # [50, 32]
print(g.edge_index.shape) # [2, 150]
For image-like features [N, C, H, W]:
N, C, H, W = 50, 16, 8, 8
x_spatial = torch.randn(N, C, H, W)
g_spatial = Graph(
node_features=x_spatial,
edge_index=edge_index,
node_labels=labels,
)
print(g_spatial.node_features.shape) # [50, 16, 8, 8]
Step 4: Apply a Message-Passing Layer
For vector features, use LinearMessagePassing or GCNConv:
from tgraphx import LinearMessagePassing
layer = LinearMessagePassing(in_shape=(32,), out_shape=(64,))
out = layer(g.node_features, g.edge_index)
print(out.shape) # [50, 64]
out.sum().backward() # gradients flow
For spatial [C, H, W] features, use ConvMessagePassing:
from tgraphx import ConvMessagePassing
layer_conv = ConvMessagePassing(in_shape=(C, H, W), out_shape=(32, H, W))
out_spatial = layer_conv(g_spatial.node_features, g_spatial.edge_index)
print(out_spatial.shape) # [50, 32, 8, 8] — spatial dims preserved
out_spatial.sum().backward()
Step 5: Set Up Reproducible Training
Always seed before constructing data, models, and dataloaders:
from tgraphx.reproducibility import set_seed
set_seed(42)
# Or use the context manager for a scoped reproducible block
import tgraphx as tgx
with tgx.reproducible(seed=42, deterministic=True):
result = tgx.easy.train_node_classifier(
g, model="tensor_gcn", epochs=5, seed=42
)
print(result.metrics)
Step 6: Full Training Loop with NeighborLoader
For scalable training on larger graphs, use NeighborLoader:
import torch.nn.functional as F
import torch.optim as optim
from tgraphx import Graph, NeighborLoader
from tgraphx import ConvMessagePassing
from tgraphx.reproducibility import set_seed
import torch.nn as nn
set_seed(42)
# Construct graph
N, C, H, W = 200, 8, 6, 6
x = torch.randn(N, C, H, W)
edge_index = torch.randint(0, N, (2, 800), dtype=torch.long)
labels = torch.randint(0, 4, (N,))
train_mask = torch.zeros(N, dtype=torch.bool)
train_mask[:120] = True
val_mask = torch.zeros(N, dtype=torch.bool)
val_mask[120:160] = True
g = Graph(
node_features=x,
edge_index=edge_index,
node_labels=labels,
train_mask=train_mask,
val_mask=val_mask,
)
# Simple two-layer model
class TwoLayerGNN(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = ConvMessagePassing(in_shape=(C, H, W), out_shape=(16, H, W))
self.conv2 = ConvMessagePassing(in_shape=(16, H, W), out_shape=(16, H, W))
self.classifier = nn.Linear(16 * H * W, 4)
def forward(self, x, edge_index):
x = F.relu(self.conv1(x, edge_index))
x = self.conv2(x, edge_index)
x = x.flatten(1)
return self.classifier(x)
model = TwoLayerGNN()
optimizer = optim.Adam(model.parameters(), lr=1e-3)
loader = NeighborLoader(g, fanouts=[10, 5], batch_size=32, seed=42)
# Training loop
for epoch in range(10):
model.train()
total_loss = 0.0
for batch in loader:
optimizer.zero_grad()
logits = model(batch.node_features, batch.edge_index)
# Only compute loss on seed nodes with train_mask
seed_logits = batch.seed_logits(logits)
seed_y = batch.seed_y
if seed_logits.numel() == 0:
continue
loss = F.cross_entropy(seed_logits, seed_y)
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch+1}: loss={total_loss:.4f}")
Step 7: Zero-Boilerplate Alternative (Easy Mode)
If you just want to test an idea quickly without writing a training loop:
import tgraphx as tgx
data = tgx.easy.synthetic_tensor_node_classification(
num_nodes=500, node_shape=(8, 6, 6), num_classes=4, seed=42
)
result = tgx.easy.train_node_classifier(
data, model="tensor_gcn", sampler="neighbor", epochs=10, seed=42
)
print(result.metrics) # val_accuracy, val_loss, ...
result.summary() # human-readable summary
# result.model — the trained PyTorch module
# result.graph — the Graph object
Easy mode wraps the standard training loop. All underlying objects are standard PyTorch, so you can inspect and modify them as needed.
Step 8: Save and Load Your Graph
# Save the graph (TGraphX's native .tgx format supports tensor features)
g.save("my_first_graph.tgx")
# Load it back
from tgraphx import Graph
g_loaded = Graph.load("my_first_graph.tgx")
print(g_loaded.node_features.shape)
GraphML cannot store rank-4 tensors, which is why TGraphX has its own .tgx format. For interop with NetworkX, use Graph.to_networkx() — note that tensor features are flattened during this conversion.
What to Read Next
This quickstart covered the minimal path to a working experiment. For deeper understanding:
| Topic | Article |
|---|---|
| Why tensor-valued nodes matter | Tensor-valued nodes in GNNs |
| Deep tutorial with multiple layers | Tensor-valued nodes deep tutorial |
| Reproducibility in full detail | GNN research reproducibility |
| Shape validation | Shape-aware validation |
| TGraphX vs PyTorch Geometric | Comparison article |
| Knowledge graphs | Knowledge graph embedding tutorial |
| Graph generation | Graph generation tutorial |
Limitations
No GPU steps in this tutorial. Call g = g.to("cuda") and model = model.to("cuda") to move everything to GPU. TGraphX follows PyTorch conventions — all operations are device-portable.
Synthetic data is not representative. The random graphs used here have no meaningful topology. Real experiments require real data loading; see tgx.load_dataset() for dataset adapters.
The "first experiment" here is not publication-ready. For a publication-quality experiment: add proper train/val/test splits, use multiple seeds, report variance, and consult the GNN research reproducibility guide.
Easy mode is for exploration, not production. tgx.easy.train_node_classifier makes assumptions about architecture and hyperparameters that may not match your task. It is a starting point, not a final solution.