fastersom
A small, fast batch self-organising map (SOM) in PyTorch: a reimplementation of Kohonen's batch map with a rectangular grid, gaussian neighbourhood and exponentially decaying neighbourhood width. Its defaults reproduce the batch-trained maps of XPySom with a gaussian neighbourhood of initial width half the grid. Data stays on the device (CUDA, MPS or CPU) and the per-epoch update smooths per-node sums with the separable gaussian, one small matrix product along each grid axis, so an epoch costs little more than one BMU search.
Install
uv add fastersom # or: pip install fastersom
Usage
import numpy as np
from fastersom import SOM
X = np.load("pixels.npy") # (n, d) or (..., d); numpy, array-like or torch
som = SOM(n_rows=30, n_cols=30, n_epochs=10, random_state=0) # device: cuda > mps > cpu
som.fit(X)
som.weights_ # (900, d) node weights, node = row * n_cols + col
som.labels_ # BMU index per training sample
labels = som.predict(X) # BMU index per sample
labels, dist = som.predict(X, return_distance=True) # and the distance to it, in the same pass
dist = som.transform(X) # (n, 900) distance to every node
umatrix = som.distance_map() # (30, 30) summed distance to the grid neighbours, max 1
print(som.quantization_error(X), som.topographic_error(X))
som = SOM.from_weights(som.weights_, n_rows=30, n_cols=30) # fitted map from saved weights, no data needed
Options:
metricsets the distance used for BMUs, distances and error measures:"euclidean"(default),"manhattan"(L1),"cosine"(1 - cosine similarity) or"correlation"(1 - Pearson correlation). Nodes are always updated to the neighbourhood-weighted mean of the raw samples (not the median under manhattan, nor centred samples under correlation). Zero-norm samples under cosine and constant samples under correlation have no BMU: they get label -1 and distance NaN inpredict, distance 1 intransform, and are left out of the update and the error measures.init="sample"initialises the nodes from random samples instead of seeded random unit vectors. An array of shape(n_rows * n_cols, d)or(n_rows, n_cols, d)gives the initial weights instead, e.g. for a warm start (SOM(init=som.weights_).fit(X)); withn_epochs=0,fitkeeps them unchanged. The sigma schedule restarts atsigma_initial, which with the default largely retrains the map; to continue training instead, pass a smallsigma_initial, e.g. the previous map'ssigma_final.sigma_initialandsigma_finalset the neighbourhood width schedule; the defaults reproduce XPySom's.batch_sizebounds memory (aboutbatch_size x n_nodesfloats) without changing the algorithm. On CUDA and MPS it defaults to the largest batch that still helps speed and fits inmemory_fraction(default 0.9 on CUDA, 0.5 on MPS) of the free GPU memory, so it rarely needs tuning.
Fitted maps pickle without device tensors and load on the configured device if available, else on the default one,
so a map fitted on a GPU loads on a CPU-only machine. BatchSOM is an alias for SOM.
Benchmark
480,000 x 34 pixels, 10 epochs, mean of 3 seeds; peak GPU memory includes the data
(benchmarks/memory.py).
| implementation | map | hardware | batch size | fit time | peak GPU memory | quantization error |
|---|---|---|---|---|---|---|
| fastersom | 30 x 30 | NVIDIA A100 | default (298,261) | 0.12 s | 1150 MiB | 0.168 |
| fastersom | 30 x 30 | NVIDIA A100 | 32,768 | 0.11 s | 204 MiB | 0.168 |
| fastersom | 30 x 30 | NVIDIA A100 | 8,096 | 0.13 s | 118 MiB | 0.168 |
| XPySom (CuPy) | 30 x 30 | NVIDIA A100 | 8,096 | 0.47 s | 313 MiB | 0.169 |
| XPySom (CuPy) | 30 x 30 | NVIDIA A100 | 65,536 | 0.41 s | 2088 MiB | 0.169 |
| torchsom | 30 x 30 | NVIDIA A100 | 1,024 | 22.3 s | 44 MiB | 0.175 |
| fastersom | 30 x 30 | 256-core CPU | default (8,192) | 1.8 s | - | 0.169 |
| XPySom (NumPy) | 30 x 30 | 256-core CPU | 8,096 | 42.3 s | - | 0.168 |
| torchsom | 30 x 30 | 256-core CPU | 1,024 | 39.2 s | - | 0.176 |
| fastersom | 100 x 100 | NVIDIA A100 | default (26,843) | 0.51 s | 1114 MiB | 0.162 |
| fastersom | 100 x 100 | NVIDIA A100 | 8,096 | 0.53 s | 400 MiB | 0.162 |
| XPySom (CuPy) | 100 x 100 | NVIDIA A100 | 8,096 | 2.8 s | 2846 MiB | 0.162 |
| fastersom | 100 x 100 | 256-core CPU | default (8,192) | 52.7 s | - | 0.162 |
At equal or less GPU memory fastersom is about 4x faster than XPySom on a 30 x 30 map and 5x faster on a 100 x 100 map (with a seventh of the memory), and over 20x faster on the CPU. torchsom updates the map per mini-batch, so it needs small batches and is far slower.
Algorithm
fastersom follows Kohonen's batch map (T. Kohonen, Self-Organizing Maps, 3rd ed., Springer, 2001). Each epoch assigns
every sample to its best matching unit and sets every node to the neighbourhood-weighted mean of the samples, with
neighbourhood h(j, k) = exp(-||r_j - r_k||^2 / (2 sigma(t)^2)) on the grid coordinates r and
sigma(t) = sigma_initial * (sigma_final / sigma_initial) ** (t / n_epochs). There is no learning rate, because it
cancels in the batch update. Only the rectangular topology, gaussian neighbourhood and exponential decay are
supported.
Development
uv sync # installs the dev group: pytest, ruff, pre-commit, twine
uv run pre-commit install # ruff, uv-lock and file checks on every commit
uv run pytest
uv build && uv run twine check --strict dist/*
License
Apache-2.0
Metadata
Release files for fastersom 0.3.1
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 | |
|---|---|---|---|---|
| fastersom-0.3.1.tar.gz | 15.9 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastersom-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.1 kB
Release files / fastersom-0.3.1.tar.gz
| Download URL | fastersom-0.3.1.tar.gz |
|---|---|
| Size | 15.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6c211b74078ce69f16f9d4149797bbc5dea705078d12e0d524cf222b5572b165
|
|
BLAKE2b-256 checksum How to use checksums |
9f05aff684ac4fa1d8d4fd69d434d9e3fdc863cb653d43762533d405c8f9ad8a
|
| 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 Oct 23, 2026.
Transparency logRelease files / fastersom-0.3.1-py3-none-any.whl
| Download URL | fastersom-0.3.1-py3-none-any.whl |
|---|---|
| Size | 16.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2e6d8f85ed4d8349e8155dcafd50d71b12a527ac2b8594cce897fc21a1c69586
|
|
BLAKE2b-256 checksum How to use checksums |
6e30fc1823db4ca287f67f9b2b748e8522410e84a752a50d558092b7d9de3ccb
|
| 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 Oct 23, 2026.
Transparency logSecurity for fastersom 0.3.1
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 fastersom-0.3.1.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 Oct 23, 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.