Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

nanoom

Multimodal-multitask-balanced dataset splitting: cluster-based separation and task-stratification/balancing across splits.

Design rationale is in ARCHITECTURE.md, the task list in DEVELOPMENT.md, setup and conventions in CONTRIBUTING.md.

Install

pip install nanoom

Core dependencies: polars, pulp, and scikit-learn.

Optional extras:

  • nanoom[chem] - rdkit/bblean-based clustering methods for molecular data
  • nanoom[tutorial] - marimo, for the notebooks in examples/
  • nanoom[plotting] - reserved for future split-quality visualization (not yet implemented)

Splitting

nanoom.split takes a dataframe with a pre-computed cluster column (see Clustering below) and returns a leakage-safe, task-balanced train/val/test assignment.

import nanoom

# balances by exactly solving a linear program (Tricarico et al., ported from
# https://github.com/sohviluukkonen/gbmt-splits); task columns may be a mix of
# regression, classification, and string columns, balanced jointly
out = nanoom.split(
    df,
    y_cols=["pchembl_value_mean", "target_id"],
    cluster_col="cluster",
    n_splits=3,
    method="tricarico",
)

# or: a lighter/faster fallback via sklearn's StratifiedGroupKFold
out = nanoom.split(
    df,
    y_cols="ic50",
    cluster_col="cluster",
    n_splits=3,
    method="sklearn",
)

Both methods return df with a split column added, holding 0..n_splits-1 per row (rename it with split_col=). The cluster column stays in the frame, so the per-cluster assignment is out.group_by("cluster").agg(pl.col("split").first()).

Splitting without clusters

cluster_col is optional. Passing cluster_col=None splits rows directly with no leakage constraint — each row becomes its own cluster, so the LP balances rows and sklearn falls back to StratifiedKFold:

out = nanoom.split(df, y_cols="ic50", n_splits=3, method="tricarico")

A cluster column of row indices is added so grouping and the audit functions below work the same in both modes. Note that the LP carries one binary variable per cluster per split, so cluster-free mode on a large frame gets slow; nanoom warns past 1000 clusters and suggests relative_gap for a fast near-optimal solve.

For regression task columns, method="tricarico" bins values before balancing (binning_approach=, default "qcut"): "qcut" targets roughly equal n_datapoints per bin; "gbmt_splits" instead bins the distinct values (matching gbmt-splits' behaviour). for repeated values this can skew row counts across bins. Neither option fully resolves a very-repeated value, since those rows can't be split across a bin boundary either way.

Clustering

nanoom.cluster produces the cluster_col that split() expects, decoupled from splitting itself so you can bring your own cluster assignment instead if you prefer.

clusters = nanoom.cluster(descriptors, method="kmeans", n_clusters=20)

Supports kmeans, dbscan, hdbscan, random, and hash_dummy out of the box; sphere_exclusion, bitbirch, maxmin, and leader_picker additionally require nanoom[chem]. An auto mode that adaptively tunes cluster granularity to trade off leakage-avoidance against task-balance quality is planned for a later iteration.

Auditing a split

nanoom.eval answers "is my split actually leakage-free and balanced?":

from nanoom.eval import check_no_group_overlap, check_distribution_y_similar, min_distances_splits

check_no_group_overlap(out["cluster"], out["split"])   # raises if any cluster spans >1 split
check_distribution_y_similar(out["ic50"], out["split"])  # raises if a split's y-mean drifts >10%
min_distances_splits(descriptors, out["split"], metric="euclidean")  # inter/intra-split distance stats

All three take per-row arrays and raise on a length mismatch rather than silently scoring the wrong subset.

Download files

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

Source Distribution

nanoom-0.1.0a20260814.tar.gz (27.5 kB view details)

Uploaded Source

Built Distribution

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

nanoom-0.1.0a20260814-py3-none-any.whl (29.1 kB view details)

Uploaded Python 3

File details

Details for the file nanoom-0.1.0a20260814.tar.gz.

File metadata

  • Download URL: nanoom-0.1.0a20260814.tar.gz
  • Upload date:
  • Size: 27.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for nanoom-0.1.0a20260814.tar.gz
Algorithm Hash digest
SHA256 74b61946cc03dead3b70a5603b7dfa5ef2d3284e2b90fe75d38224c9c5984f48
MD5 534a73a934898faf8b7ee9ebd24fbdd8
BLAKE2b-256 592a67b83a37f5e4e41b880cefa04c7a50c29e403c93ad43d3d354fe17e6435b

See more details on using hashes here.

File details

Details for the file nanoom-0.1.0a20260814-py3-none-any.whl.

File metadata

  • Download URL: nanoom-0.1.0a20260814-py3-none-any.whl
  • Upload date:
  • Size: 29.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for nanoom-0.1.0a20260814-py3-none-any.whl
Algorithm Hash digest
SHA256 7460f70434258e9ca43784385e07d9660c4e53a50877bdfad7a988196c8de63c
MD5 a45c266f4774e05f851473d5d0285974
BLAKE2b-256 2adb27b766b730b878ef2e49e8f75e5e8cd84c9456fc31f48401bab4830f99ca

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0a20260814 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