Skip to main content

kpnn2

ci codecov PyPI pypi since Python PyPI - License PyPI - Downloads

Turn a named edgelist into sparsely connected PyTorch layers you assemble yourself.

Overview

A fully connected neural network (NN), in which every node in one layer connects to every node in the next, is easy to implement in PyTorch.

A sparsely connected NN with skip edges is not. Only some pairs of nodes are linked, and some edges skip layers. That is the gap kpnn2 (Knowledge Primed Neural Networks) fills: the same PyTorch workflow, with that connectivity. Figure 1 shows a dense NN next to a sparse NN with skip edges.

Fully connected versus sparse

Figure 1. (a) Dense adjacent layers, the usual PyTorch case. (b) A sparsely connected DAG with skip edges (dashed), the same graph as on the Skip edges page. kpnn2 turns (b) into ordinary MaskedLinear hops, one per layer, with the skip edges inside those masks.

An edgelist is a table of directed connections: each row links a source node to a target node. For example:

source target
A H
B H
H C

parse_layered() layers that table into a LayeredSpec. You write a normal torch.nn.Module, train with standard PyTorch, and can map attributions back onto the named nodes. That parser needs a DAG; a graph with feedback loops goes through parse_adjacency() instead, which puts every node into one state vector with packed edge indices (see the Recurrent example).

Sparse connectivity is often used for speed or memory, without needing control over which nodes are linked. A newer line of work instead builds the NN so its wiring is a real network, for example a biological or chemical graph. Attributions on the NN nodes then map onto the nodes of that network, which gives the model a direct form of interpretability.

In biology this is an active research area, including pathway-based models (Fortelny and Bock, 2020) and ontology-based models (Elmarakeby et al., 2021). The Getting started notebook walks through a biological example.

kpnn2 is a set of (domain-agnostic) primitives, not a graph compiler. There is no ready-made model object. Training loops, losses, optimizers, activations, and heads stay yours.

As a further note, "graph" here means the architecture specification, not a graph neural network, which cannot be implemented using kpnn2 in PyTorch.

Core workflow

  1. Define a model architecture as an edgelist with named source and target nodes.
  2. Parse it with parse_layered() to a LayeredSpec. For a graph with feedback loops, use parse_adjacency() and an AdjacencySpec instead.
  3. Write an nn.Module with one MaskedLinear per spec.hops, feeding each one gather_hop_inputs(saved, hop). Skip edges are already inside those masks, so there is nothing extra to call.
  4. Align named input tables with align_inputs().
  5. Train with ordinary PyTorch.
  6. Optionally run Captum (or another method) yourself, then label a layer tensor with map_node_attributions() (returns xarray).
  7. A checkpoint is spec.to_dict() plus state_dict, not weights alone.

The snippet below is a minimal run of steps 1–4, using the edgelist from the table above. Column order in the input table does not matter: align_inputs() matches names. Skip edges are omitted here; see Skip edges. A full walkthrough, including training and attribution, is in Getting started.

import pandas as pd
import torch.nn.functional as F
from torch import nn

import kpnn2

edgelist = pd.DataFrame(
    {
        "source": ["A", "B", "H"],
        "target": ["H", "H", "C"],
    }
)
spec = kpnn2.parse_layered(edgelist)


class Net(nn.Module):
    def __init__(self, spec: kpnn2.LayeredSpec):
        super().__init__()
        self.lin0 = kpnn2.MaskedLinear(spec.hops[0].mask)
        self.lin1 = kpnn2.MaskedLinear(spec.hops[1].mask)

    def forward(self, x):
        h = F.relu(self.lin0(x))
        return self.lin1(h)


model = Net(spec)
x = kpnn2.align_inputs(
    pd.DataFrame({"B": [0.2, 0.4], "A": [0.1, 0.3]}),
    spec,
)
y = model(x)
# Continue training with ordinary PyTorch.

API

The documented public names are:

  • parse_layered()
  • parse_adjacency()
  • LayeredSpec
  • Hop
  • Skip
  • AdjacencySpec
  • MaskedLinear
  • PackedLinear
  • gather_hop_inputs()
  • align_inputs()
  • map_node_attributions()

LayeredSpec.hops holds one Hop per layer after the first, and a hop's mask carries every edge entering that layer, skip edges included. LayeredSpec.skips lists which edges span layers, as metadata. An AdjacencySpec has no layers and no skips: it carries packed source_index / target_index over all nodes, plus input_index and output_index into that state vector. to_mask() densifies for MaskedLinear on small graphs.

See the API reference for details, and Skip edges for a worked example.

Package philosophy

kpnn2 is intentionally minimally opinionated.

It owns edgelist parsing, mask tensors, hop input assembly, named input alignment, and attribution column names. It does not impose broader modeling choices such as:

  • activation functions
  • output heads
  • dropout
  • loss functions
  • optimizers
  • training loops

Those remain part of the normal PyTorch workflow:

  • kpnn2 turns the edgelist into structure you can execute
  • PyTorch handles forward(), training, and customization
  • you map trained tensors back to named nodes when you want interpretation

Installation

Requires Python 3.10 or later.

pip install kpnn2

Start here

If you are new to the package, start with a tutorial:

  • Installation for package setup
  • Getting started for a full end-to-end feedforward example
  • Recurrent example for parse_adjacency() and a shared MaskedLinear over one state vector when the graph has feedback loops (parse_layered still requires a DAG)

The other pages explain a design choice; they are not second examples:

Citation

If you use kpnn2 in research, please cite the software. Citation metadata is available in CITATION.cff.

License

This project is licensed under the MIT License. See the LICENSE file on GitHub for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kpnn2-0.1.0.tar.gz (48.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kpnn2-0.1.0-py3-none-any.whl (49.0 kB view details)

Uploaded Python 3

File details

Details for the file kpnn2-0.1.0.tar.gz.

File metadata

  • Download URL: kpnn2-0.1.0.tar.gz
  • Upload date:
  • Size: 48.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for kpnn2-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d4f923526c1fefd3f4cf9d9659db5294c4fa7431b9d9fc5e46e5cf0d6950cd6e
MD5 f470b0d6b70e987ffeea03c530a81ca1
BLAKE2b-256 e05cc06860028568ac2f53ea8a77cc15ab524e1a22303f5dfe499d659b6b701d

See more details on using hashes here.

Provenance

The following attestation bundles were made for kpnn2-0.1.0.tar.gz:

Publisher: release.yml on Thomas-Rauter/kpnn2

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kpnn2-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: kpnn2-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 49.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for kpnn2-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4f4d043ac05986253f7cedf23b2eddec7c528a236495200afe287739b393e9a3
MD5 0ae4d2f856a35afcb9de31f1e3adfae8
BLAKE2b-256 885ff3a090156083256b5996eaf7e09ac202789f19762eefe4724a361269be42

See more details on using hashes here.

Provenance

The following attestation bundles were made for kpnn2-0.1.0-py3-none-any.whl:

Publisher: release.yml on Thomas-Rauter/kpnn2

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page