This repository contains a cleaned, reproducible version of the LouvainNE-with-attributes experiments for node classification on multiple attributed graph benchmarks.
It is based on LouvainNE:
- upstream reference: https://github.com/maxdan94/LouvainNE
- paper: "LouvainNE: Hierarchical Louvain Method for High Quality and Scalable Network Embedding" (WSDM 2020)
-
prepare_datasets.pyThe supported dataset bootstrap script. It createsdata/and fetches onlyCora,CiteSeer,PubMed, andBlogCatalog. -
run_louvainne_experiments.pyMain Cora experiment runner. This reproduces the tuned baseline vs improved pipeline on the original Cora setup, using data prepared byprepare_datasets.py. -
benchmark_datasets.pyMulti-dataset benchmark runner forCora,CiteSeer,PubMed, andBlogCatalog. It writes one subfolder per dataset underresults/. -
summay.mdAnalysis of what was implemented in the original repo, what was changed, and the measured results. -
results/louvainne_results.jsonSaved output from the reproducible Cora experiment run. -
results/louvainne_comparison.pngAccuracy plus runtime-split comparison plot for the best reproducible Cora baseline vs the improved pipeline. -
results/benchmark_summary.json -
results/benchmark_summary.md -
results/benchmark_summary.pngAggregated multi-dataset results acrossCora,CiteSeer,PubMed, andBlogCatalog, including one-time setup time and repeated per-seed evaluation time. -
results/<Dataset>/comparison_results.json -
results/<Dataset>/comparison_plot.pngPer-dataset result artifacts written bybenchmark_datasets.py. -
data/Generated dataset cache created byprepare_datasets.py. This folder is not the source of truth for the repo; it is regenerated state. -
LouvainNE/Patched LouvainNE source code used by the runner.
Legacy notebooks, stale generated text files, and old compiled binaries were removed from the main workflow because they were either redundant, not reproducible, or superseded by the runner above.
Create the conda environment:
conda env create --name <envname> --file=environment.yml
conda activate <envname>Both runners rebuild the needed LouvainNE binaries automatically under build/louvainne/.
Run this first:
python prepare_datasets.pyThis creates data/ and prepares exactly these datasets:
CoraCiteSeerPubMedBlogCatalog
Quick smoke test:
python run_louvainne_experiments.py --tune-runs 1 --eval-runs 1 --output-json /tmp/louvainne_smoke.jsonFull reproducible run:
python run_louvainne_experiments.py \
--tune-runs 2 \
--eval-runs 5 \
--output-json results/louvainne_results.json \
--plot-path results/louvainne_comparison.pngRun all maintained datasets:
python benchmark_datasets.py --datasets Cora CiteSeer PubMed BlogCatalogRun only one dataset:
python benchmark_datasets.py --datasets CiteSeerThis writes:
results/Cora/results/CiteSeer/results/PubMed/results/BlogCatalog/results/benchmark_summary.jsonresults/benchmark_summary.mdresults/benchmark_summary.png
Use this as the minimal check after any code change:
- Prepare the datasets:
python prepare_datasets.py- Run the Cora smoke test:
python run_louvainne_experiments.py --tune-runs 1 --eval-runs 1 --output-json /tmp/louvainne_smoke.json --plot-path /tmp/louvainne_smoke.png- Run the full Cora benchmark:
python run_louvainne_experiments.py --tune-runs 2 --eval-runs 5 --output-json results/louvainne_results.json --plot-path results/louvainne_comparison.png- Run the multi-dataset benchmark:
python benchmark_datasets.py --datasets Cora CiteSeer PubMed BlogCatalog- Verify the key outputs exist:
ls \
data/manifest.json \
results/louvainne_results.json \
results/louvainne_comparison.png \
results/benchmark_summary.json \
results/benchmark_summary.md \
results/benchmark_summary.png \
results/Cora/comparison_results.json \
results/CiteSeer/comparison_results.json \
results/PubMed/comparison_results.json \
results/BlogCatalog/comparison_results.json \
summay.md- Inspect the saved Cora metrics quickly:
python - <<'PY'
import json
from pathlib import Path
payload = json.loads(Path('results/louvainne_results.json').read_text())
for key in ['baseline', 'improved']:
item = payload['final_results'][key]
print(
key,
'micro', round(item['test_micro_f1_mean'], 4),
'macro', round(item['test_macro_f1_mean'], 4),
'setup_s', round(item['setup_time_seconds'], 2),
'per_seed_s', round(item['per_seed_eval_time_seconds_mean'], 2),
)
PY- Inspect the multi-dataset summary quickly:
sed -n '1,120p' results/benchmark_summary.mdFrom the latest saved Cora run:
- best reproducible repo-style baseline: micro-F1
0.7356 ± 0.0038, macro-F10.7291 ± 0.0039 - improved pipeline: micro-F1
0.7722 ± 0.0026, macro-F10.7623 ± 0.0021 - baseline setup time:
0.15seconds - improved setup time:
1.13seconds - baseline per-seed evaluation time:
2.22 ± 0.10seconds - improved per-seed evaluation time:
0.88 ± 0.12seconds
From results/benchmark_summary.md:
Cora: baseline0.5916 ± 0.0031, improved0.7226 ± 0.0053, setup0.53svs0.32s, per-seed3.30svs1.06sCiteSeer: baseline0.4958 ± 0.0125, improved0.6638 ± 0.0047, setup0.53svs0.36s, per-seed3.43svs1.23sPubMed: baseline0.5830 ± 0.0167, improved0.7246 ± 0.0031, setup2.52svs1.52s, per-seed8.53svs6.87sBlogCatalog: baseline0.7517 ± 0.0080, improved0.9143 ± 0.0066, setup1.30svs0.90s, per-seed6.72svs4.21s
See summay.md for the repo analysis, results/louvainne_comparison.png for the Cora comparison, and results/benchmark_summary.png for the cross-dataset comparison.