Skip to main content

Intrinsic Green Learning

OpenSSF Scorecard

High-dimensional inputs — pixel grids, EEG channels, embedding vectors — almost never use all the dimensions they appear to. The handful that actually matter depends on the question you ask: a binary classifier may need only one or two latent axes, a regressor to a continuous target may need a few more, and a full reconstruction needs whatever dimension the data manifold genuinely has.

Intrinsic Green Learning (IGL) discovers that task-conditioned effective dimension while it fits the model. A learned encoder maps the ambient input to a low-dimensional latent space; a multi-scale Green's-function kernel computes a structured design matrix on that latent space; and Variable Projection with random Matryoshka truncation trains the encoder and reads off the smallest dimension that still solves the task. There's no separate "dimensionality reduction" step and no fixed bottleneck — the dimension you should use falls out of training.

The key difference from PCA, UMAP, t-SNE, or any other purely-geometric manifold-learning method: the effective dimension IGL reports is a property of (input, task), not of the input alone. The same dataset will resolve into different d_eff values for a classifier, a regressor, and an autoencoder — and the hierarchy $d_{\text{cls}} \le d_{\text{reg}} \le d_{\text{recon}}$ holds out of the box.

What ships:

  • scikit-learn-compatible estimators (IGLClassifier, IGLRegressor, IGLAutoencoder) for drop-in use in existing pipelines.
  • Bare PyTorch building blocks (IGLModule, GreenKernel, MatryoshkaTrainer, …) for custom training loops, novel kernels, and research extensions.
  • Spectral formulation (SpectralKernel + closed-form Fourier / Chebyshev / Legendre / Hermite / Laguerre bases, plus learned Laplace–Beltrami and user-supplied graph bases) with kernel-agnostic null-space augmentation for operators with non-trivial $\ker(L)$.
  • Riemannian / SPD extension (igl.spd) for covariance-valued data — EEG, fMRI-derived connectivity, financial covariances — with an AIRM-based loss plugged in through the same ExtraLoss seam used by every other training-time regulariser.

Note on the import name. The distribution is intrinsic-green-learning; the import name is igl. This collides with libigl; if you need both in the same env, install one of them under a different module name.

Why IGL?

For the same input data, a classifier usually needs fewer latent dimensions than a regressor, which in turn needs fewer than a full autoencoder. IGL discovers this hierarchy automatically:

$$ d_{\text{eff}}(\text{classification}) ;\le; d_{\text{eff}}(\text{regression}) ;\le; d_{\text{eff}}(\text{reconstruction}) $$

The library ships an examples/synthetic/moons_xor.py script that fits all three estimators on the same data and reports the discovered dimensions — the hierarchy holds out of the box.

Installation

pip install intrinsic-green-learning

Optional extras:

Extra Adds Use case
[viz] matplotlib Plot dimension curves via igl.viz.plot_dimension_curve.
[eeg] mne + moabb + pyriemann Future EEG / clinical loaders (placeholder for v0.2).
[nlp] transformers + datasets Future NLP loaders.
[elbow] kneed Alternative elbow detector.
[all] all of the above One-shot install for development.

Quickstart

The library exposes three sklearn-compatible estimators plus a SPD extension. All accept numpy arrays at the API boundary.

Classification

import numpy as np
import igl
from igl.data import embed_in_high_dim, make_moons

x_2d, y = make_moons(400, noise=0.1, seed=0)
x = embed_in_high_dim(x_2d, target_dim=16, seed=0).numpy()

clf = igl.IGLClassifier(max_dim=8, random_state=0).fit(x, y.numpy())
print(f"accuracy = {clf.score(x, y.numpy()):.3f}")
print(f"discovered d_eff = {clf.effective_dimension_}")  # ~ 1 on moons

Regression and reconstruction

from igl.data import make_swiss_roll

x, params = make_swiss_roll(800, seed=0)
x_np = x.numpy(); params_np = params.numpy()

reg = igl.IGLRegressor(max_dim=8, random_state=0).fit(x_np, params_np)
ae = igl.IGLAutoencoder(max_dim=8, random_state=0).fit(x_np)

print(reg.effective_dimension_)   # ~ 2 on swiss roll (intrinsic dim)
print(ae.effective_dimension_)    # ~ 2 on swiss roll

Cross-task hierarchy check

report = igl.compare_d_eff(
    cls=clf.dimension_curve_,
    reg=reg.dimension_curve_,
    recon=ae.dimension_curve_,
)
print(report.d_effs)            # {'cls': 1, 'reg': 2, 'recon': 2}
print(report.hierarchy_holds)   # True

SPD / Riemannian extension

For covariance-valued data (EEG, clinical signals, …), igl.spd ships an AIRM-based reconstruction classifier:

from igl.data import make_spd_dataset
from igl.spd import IGLReconSPDClassifier, LogEigVectorizer

spd, y = make_spd_dataset(400, d=8, n_classes=3, seed=0)
x = LogEigVectorizer().fit(spd.numpy()).transform(spd.numpy())

clf = IGLReconSPDClassifier(
    latent_dim=8, max_dim=12,
    orthogonality_weight=0.1,   # plug-in via the ExtraLoss seam
    random_state=0,
).fit(x, y.numpy())
print(clf.effective_dimension_)

For EEG (raw signals → covariances → AIRM), the make_igl_airm factory (in the [eeg] extra) composes Ledoit-Wolf vs sample-cov auto-selection with Tikhonov-preconditioned IGL-AIRM into a single sklearn pipeline:

import igl  # requires: pip install intrinsic-green-learning[eeg]

pipe = igl.make_igl_airm(latent_dim=22)
pipe.fit(X_raw, y)   # X_raw: [N, channels, time]

Tikhonov ε = 10⁻⁶ is applied to every input SPD by default — bit-near identical to no preconditioning at d ≤ 64 (with a BatchNorm encoder) and rescues torch.linalg.eigh from LAPACK error 8481 at d ≥ 128.

Custom training loop

If sklearn's surface is too high-level, use the bare PyTorch entry points directly:

import torch
import igl

module = igl.IGLModule(
    input_dim=16, max_dim=8, output_dim=2,
    config=igl.IGLConfig(
        encoder=igl.EncoderConfig(hidden=(128, 64)),  # pyramidal MLP
        kernel=igl.KernelConfig(n_anchors=64, operator=igl.OperatorName.GAUSSIAN),
    ),
)

trainer = igl.MatryoshkaTrainer(
    loss=igl.CrossEntropyLoss(n_classes=2),
    config=igl.MatryoshkaConfig(epochs=500),
)
history = trainer.fit(module, x_train_t, y_train_t, x_val=x_val_t, y_val=y_val_t)
curve = igl.eval_dimension_curve(module, x_val_t, y_val_t, loss=igl.CrossEntropyLoss(n_classes=2))
print("d_eff =", igl.detect_elbow(curve))

Documentation

Local build:

uv sync --group doc
uv run mkdocs serve

Published at https://hotherio.github.io/intrinsic-green-learning/latest/ after the first release.

Examples

Three runnable scripts under examples/synthetic/:

Script Manifold Tasks Expected d_eff
torus_classification.py T² ⊂ R⁴ → R³² XOR cls + sin/cos reg ≈ 2
moons_xor.py Moons ⊂ R² → R¹⁶ cls + reg + recon d_cls ≤ d_reg ≤ d_recon
swiss_roll_recon.py Swiss roll ⊂ R³ autoencoder + reg ≈ 2

Run with python -m examples.synthetic.<name>; outputs land in results/<name>/<git_short_sha>/. Install [viz] for PNG plots.

Development

uv sync --all-groups
uv run lefthook install

Verify your environment:

uv run pytest                                # tests + 100% coverage
uv run basedpyright src                      # strict type check
uv run lefthook run pre-commit --all-files   # full pre-commit pass

Conventions

Style, typing, exceptions, commit-message format, and the rest are documented in CONTRIBUTING.md and docs/guidelines/.

Release process

Releases are fully automated by python-semantic-release on every push to main via .github/workflows/semantic-release.yml. See docs/security.md for the supply-chain posture (OIDC, sigstore attestations, GPG-signed checksums, pip-audit).

Bibliography

If you use IGL in academic work, please cite the paper this library implements:

Quemy, A. (2026). Intrinsic Green's Learning: Supervised Learning on Manifolds via Inverse PDE. ICLR 2026 Workshop on AI and PDE. https://openreview.net/forum?id=Y6RpdS98l8

@inproceedings{quemy2026igl,
  title     = {{Intrinsic Green's Learning: Supervised Learning on Manifolds via Inverse PDE}},
  author    = {Quemy, Alexandre},
  booktitle = {ICLR 2026 Workshop on AI and PDE},
  year      = {2026},
  month     = {3},
  url       = {https://openreview.net/forum?id=Y6RpdS98l8}
}

For a citation to this exact software version, GitHub's "Cite this repository" widget reads CITATION.cff; its preferred-citation block points back to the paper above.

License

MIT. See LICENSE and REUSE.toml.

Release files for intrinsic-green-learning 0.14.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for intrinsic-green-learning 0.14.1
File Size Uploaded
intrinsic_green_learning-0.14.1.tar.gz 193.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for intrinsic-green-learning 0.14.1
File Interpreter ABI Platform
intrinsic_green_learning-0.14.1-py3-none-any.whl Python 3 none any Details

Total release size: 369.5 kB

Release files / intrinsic_green_learning-0.14.1.tar.gz

Download URL intrinsic_green_learning-0.14.1.tar.gz
Size 193.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b1b0c4f40dd8577cf78773b193078cb0c93cbe3b45dbeeec0b4779a09aad1cd1
BLAKE2b-256 checksum
How to use checksums
2c6d60dc0152f41c7f034b560f681798ecd5a0393fc6294bc5588c995eae94a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Sep 9, 2026.

Transparency log

Release files / intrinsic_green_learning-0.14.1-py3-none-any.whl

Download URL intrinsic_green_learning-0.14.1-py3-none-any.whl
Size 176.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7b58698df16cde88ccece8b64cd3bcb0511d2e0b9c71f68e6c24da939e958b3f
BLAKE2b-256 checksum
How to use checksums
4ace9498cd66496fecf067c17403abe580c88761a22c79c4b9eaae558a313e99
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Sep 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.14.1 This release

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release 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