graphspot
Graph anomaly detection for people who have to score things they have never seen before.
- Inductive by contract. Every detector's
decision_functionscores nodes absent at fit time. NeverNotImplementedError. - Installs without torch. The core is numpy/scipy/sklearn/pandas/xgboost. Deep detectors
live behind
pip install graphspot[deep]. - Honest baselines. Every evaluation can include a no-graph tabular baseline, and graphspot warns loudly when the graph model fails to beat it.
Status: pre-release, under active development. The v0 detector set is
NeighborAggregation (transform), XGBGraph, RFGraph, FlatBaseline, with
FlatUnsupervised, OddBall, Fraudar and BWGNN (behind [deep]) on the way.
import graphspot
from graphspot.detectors import XGBGraph, FlatBaseline
from graphspot.datasets import load_yelpchi
g = load_yelpchi()
det = XGBGraph(random_state=0).fit(g, y=g.node_labels)
flat = FlatBaseline(random_state=0).fit(g, y=g.node_labels)
print(graphspot.evaluate(
g.node_labels,
det.decision_scores_,
baseline_scores=flat.decision_scores_,
))
det.explain(k=5) # e.g. [("2hop_mean(f21)", 0.14), ("1hop_max(f3)", 0.11), ...]
list_detectors() reports what is usable in your environment, and any PyOD detector
runs through graphspot's graphs and benchmarks in one line:
import graphspot
graphspot.list_detectors()
from pyod.models.ecod import ECOD
det = graphspot.compat.from_pyod(ECOD()).fit(g) # ECOD over neighbor-aggregated features
Works directly on transaction dataframes:
g = graphspot.Graph.from_pandas(
tx, source="buyer_id", target="seller_id",
edge_features=["amount"], time="ts",
node_features=accounts.set_index("account_id"),
)
Benchmarks
Every number regenerates from one command: graphspot bench --quick. AUPRC x100,
mean over three seeded trials, on the four auto-download datasets, out-of-the-box
defaults, no torch installed. Tolokers and Questions use the split masks their
upstream ships; the flat baseline is the same XGBoost on raw features with no graph.
dataset XGBGraph RFGraph FlatBaseline
----------------------------------------------------
yelpchi 89.32±0.42* 76.76±0.41 83.45±0.51
amazon 93.75±0.57* 89.70±1.00 90.25±1.22
tolokers 57.34±1.34 58.18±1.35* 38.61±0.70
questions 22.05±1.30* 16.09±1.49 16.77±1.50
Read the losses too: on YelpChi and Amazon the plain random forest does not beat the no-graph baseline. Publishing where the graph does not help is the point.
macOS notes: xgboost needs Homebrew's libomp (brew install libomp). And torch
(the [deep] extra) cannot share a process with xgboost on macOS: each bundles its
own OpenMP runtime and the mix segfaults or deadlocks. graphspot guards this with a
clear error instead of a crash; run deep and tree detectors in separate processes
there. Linux is unaffected.
The acceptance test
Strict-inductive Elliptic, one command, on a laptop, no torch:
uv run python scripts/acceptance_elliptic.py fits on time steps 1-34 and scores
steps 35-49 as a disjoint graph the model has never seen. 203,769 nodes; fit 10.1s,
score 0.8s, peak rss 3.05GB. PyOD's graph detectors raise NotImplementedError on
decision_function; PyGOD's flagship OOMs on this graph on a 12 GB GPU.
Two honest findings the per-step table makes visible. The dark-market shutdown at step 43 collapses every model (AUPRC in the 90s drops to single digits), which is why the script refuses to print a single aggregate number. And on this dataset the graph model does not beat the flat baseline (mean per-step AUPRC 55.3 vs 56.4): Elliptic's feature matrix already contains 72 neighborhood-aggregate columns computed by the dataset authors, so the flat model is quietly graph-informed. The loud baseline exists precisely to surface results like this.
Support
- Versioning: pre-1.0, minor releases may change APIs; anything removed gets a
deprecation release first. Fitted-attribute names (
decision_scores_,labels_,threshold_) are stable and PyOD-compatible. - Scope: node and edge level anomaly detection on static graphs. Graph-level detection and streaming are out of scope for now.
- Every README number regenerates from one command (
scripts/kill_test.py,graphspot bench --quick), and a monthly CI job re-runs them. - Issues and PRs are welcome; small reproducible bug reports get priority.
License: BSD-3-Clause.
Metadata
Release files for graphspot 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| graphspot-0.1.0.tar.gz | 215.0 kB | With provenance | Details for graphspot-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| graphspot-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for graphspot-0.1.0-py3-none-any.whl |
Total release size: 249.9 kB
Release files / graphspot-0.1.0.tar.gz
| Download URL | graphspot-0.1.0.tar.gz |
|---|---|
| Size | 215.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
70a1cdfc503cc05eafe0d93cc5c027dc2883a905fe49a2d50979972080c9f933
|
|
BLAKE2b-256 checksum How to use checksums |
55af6ae1efa0390450bc980b186c6b0f1a6bcbf75c7008fd88bd3ae495597d0c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 15, 2026.
Transparency logRelease files / graphspot-0.1.0-py3-none-any.whl
| Download URL | graphspot-0.1.0-py3-none-any.whl |
|---|---|
| Size | 34.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
88629e5a11545f082287943104a7edb0bac77f601399f32810ad45b6168e2068
|
|
BLAKE2b-256 checksum How to use checksums |
3e6141851c1b46aebed67b0e601cb4c7a14127cc0519984a137bc89c05fd5511
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 15, 2026.
Transparency logSecurity for graphspot 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for graphspot-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 15, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.