K-Means
TanayLabUtilities.KMeans
—
Module
Higher-level K-Means functions.
TanayLabUtilities.KMeans.KMeansBuffers
—
Type
KMeansBuffers{T}(; n_dims::Integer, max_k::Integer, n_points::Integer)::KMeansBuffers where {T<: AbstractFloat}
KMeansBuffers(buffers::KMeansBuffers{T}; n_dims::Integer, k::Integer, n_points::Integer) where {T <: AbstractFloat}
Pre-allocate buffers for allocation-free K-Means computation. Create a smaller view sharing the storage with
KMeansBuffers(buffers; n_dims, k, n_points)
.
TanayLabUtilities.KMeans.KmeansResultView
—
Type
KmeansResultView
A view into
KMeansBuffers
that provides the same accessor interface as
Clustering.KmeansResult
(
assignments
,
counts
,
wcounts
,
nclusters
,
totalcost
) without allocating.
TanayLabUtilities.KMeans.kmeans_in_buffers
—
Function
kmeans_in_buffers(
X::AbstractMatrix{<:Real},
k::Integer;
buffers::Maybe{KMeansBuffers} = ```nothing```,
maxiter::Integer = ```100```,
tol::Real = ```1.0e-6```,
distance::SemiMetric = ```Distances.SqEuclidean```,
rng::AbstractRNG = default_rng(),
)::Union{KmeansResult, KmeansResultView}
Same as
kmeans
, but if
buffers
are specified, run allocation-free code. Seeding is restricted to
:kmpp
. Implementation is otherwise identical to `Clustering.kmeans.
TanayLabUtilities.KMeans.kmeans_in_buffers!
—
Function
kmeans_in_buffers!(
X::AbstractMatrix{<:Real},
centers::AbstractMatrix{<:AbstractFloat};
buffers::Maybe{KMeansBuffers} = ```nothing```,
maxiter::Integer = ```100```,
tol::Real = ```1.0e-6```,
distance::SemiMetric = ```Distances.SqEuclidean```,
rng::AbstractRNG = default_rng(),
)::Union{KmeansResult, KmeansResultView}
Same as
kmeans!
, but if
buffers
are specified, run allocation-free code. Seeding is restricted to
:kmpp
. Implementation is otherwise identical to `Clustering.kmeans!.
TanayLabUtilities.KMeans.kmeans_in_rounds
—
Function
kmeans_in_rounds(
values_of_points::AbstractMatrix{<:AbstractFloat},
k::Integer;
centers::Maybe{AbstractMatrix{<:AbstractFloat}} = ```nothing```,
buffers::Maybe{Tuple{KMeansBuffers, KMeansBuffers}} = ```nothing```,
buffer_pool::Maybe{Channel} = ```nothing```,
rounds::Integer = ```10```,
min_size::Maybe{Int} = ```nothing```,
rng::AbstractRNG = default_rng(),
)::Union{KmeansResult, KmeansResultView}
Run
kmeans
multiple times with different random seeds (using
rng
) and return the best results. This is needed because K-Means is a heuristic and tends to occasionally get stuck in a local minimum.
If
buffer_pool
is specified (a
Channel{KMeansBuffers}
sized to the available concurrency), the rounds run in parallel via a nested
parallel_loop_with_rng
, which seeds each round's rng reproducibly from
rng
and the round index. Each round takes a
KMeansBuffers
from the pool, runs allocation-free
kmeans_in_buffers
/
kmeans_in_buffers!
, snapshots the result into owned arrays, and returns the buffer to the pool. The argmin over rounds picks the winner. Mutually exclusive with
buffers
.
If
buffers
(the legacy swap pair) is specified, runs allocation-free serially: each round overwrites the
current_buf
and swaps it with
best_buf
when it improves.
If neither is specified (the default), falls back to using
Clustering.kmeans
/
Clustering.kmeans!
, allocating per round.
If
min_size
is specified, rounds are ranked first by the number of clusters whose count is below
min_size
(smaller is better) and then by the kmeans cost; otherwise rounds are ranked by the cost alone.