Advanced Usage
This page covers advanced usage patterns and customization.
Custom Distance Metrics
While kmeans-seeding uses Euclidean distance internally, you can preprocess your data:
from sklearn.metrics import pairwise_distances
from sklearn.manifold import MDS
from kmeans_seeding import rskmeans
# Compute custom distance matrix
distances = pairwise_distances(X, metric='cosine')
# Embed in Euclidean space
mds = MDS(n_components=50, dissimilarity='precomputed')
X_embedded = mds.fit_transform(distances)
# Now use Euclidean k-means++
centers_embedded = rskmeans(X_embedded, n_clusters=10)
# Map back to original indices
center_indices = [np.argmin(np.linalg.norm(X_embedded - c, axis=1))
for c in centers_embedded]
centers = X[center_indices]
Incremental Clustering
Add more clusters to existing centers:
from kmeans_seeding import rskmeans
from sklearn.cluster import KMeans
import numpy as np
# Initial clustering
centers_10 = rskmeans(X, n_clusters=10, random_state=42)
# Add 5 more clusters
# Compute distances to existing centers
kmeans_temp = KMeans(n_clusters=10, init=centers_10, n_init=1, max_iter=0)
kmeans_temp.fit(X)
distances = kmeans_temp.transform(X)
min_distances_sq = np.min(distances, axis=1) ** 2
# Sample 5 more centers using D² distribution
probs = min_distances_sq / min_distances_sq.sum()
new_indices = np.random.choice(len(X), size=5, replace=False, p=probs)
# Combine
centers_15 = np.vstack([centers_10, X[new_indices]])
Parallel Initialization
Initialize multiple clusterings in parallel:
from joblib import Parallel, delayed
from kmeans_seeding import rskmeans
from sklearn.cluster import KMeans
def run_clustering(seed):
centers = rskmeans(X, n_clusters=100,
index_type='FastLSH',
random_state=seed)
kmeans = KMeans(n_clusters=100, init=centers, n_init=1)
kmeans.fit(X)
return kmeans.inertia_, kmeans.labels_
# Run 10 clusterings in parallel
results = Parallel(n_jobs=-1)(
delayed(run_clustering)(seed) for seed in range(10)
)
# Get best result
best_idx = np.argmin([r[0] for r in results])
best_inertia, best_labels = results[best_idx]
Hierarchical Initialization
Use k-means++ for hierarchical clustering:
from kmeans_seeding import kmeanspp
from sklearn.cluster import AgglomerativeClustering
# Initialize with well-spread points
initial_centers = kmeanspp(X, n_clusters=100, random_state=42)
# Use as initial linkage for hierarchical clustering
hierarchical = AgglomerativeClustering(n_clusters=10)
labels = hierarchical.fit_predict(initial_centers)
Weighted Sampling
Initialize with sample weights:
import numpy as np
from kmeans_seeding import rskmeans
# Define weights (e.g., based on density)
weights = compute_density(X) # Your density estimation
# Sample weighted subset
n_sample = min(50000, len(X))
probs = weights / weights.sum()
indices = np.random.choice(len(X), size=n_sample, p=probs)
X_weighted = X[indices]
# Initialize on weighted sample
centers = rskmeans(X_weighted, n_clusters=100,
index_type='FastLSH')
Warm Starting
Use previous centers to initialize new clustering:
from sklearn.cluster import KMeans
from kmeans_seeding import rskmeans
import numpy as np
# Initial clustering
centers_old = rskmeans(X, n_clusters=10, random_state=42)
kmeans = KMeans(n_clusters=10, init=centers_old, n_init=1)
kmeans.fit(X)
# New data arrives
X_new = np.vstack([X, new_data])
# Warm start with old centers
centers_new = rskmeans(X_new, n_clusters=10,
index_type='FastLSH',
random_state=42)
# Could also just use old centers directly
kmeans = KMeans(n_clusters=10, init=centers_old, n_init=1)
kmeans.fit(X_new)
Memory-Efficient Processing
For very large datasets that don’t fit in memory:
from kmeans_seeding import rskmeans
from sklearn.cluster import MiniBatchKMeans
import numpy as np
# Sample for initialization
n_sample = 100000
indices = np.random.choice(len(X), size=n_sample, replace=False)
X_sample = X[indices]
# Initialize on sample
centers = rskmeans(X_sample, n_clusters=500,
index_type='FastLSH')
# Use MiniBatchKMeans on full data
mbkmeans = MiniBatchKMeans(n_clusters=500,
init=centers,
n_init=1,
batch_size=10000)
# Process in batches
for batch in generate_batches(X, batch_size=10000):
mbkmeans.partial_fit(batch)
labels = mbkmeans.predict(X)
Custom Index Parameters (RS-k-means++)
Fine-tune FAISS index behavior:
from kmeans_seeding import rskmeans
# IVFFlat with custom nprobe
# Note: This requires modifying the C++ code
# The Python API doesn't expose all FAISS parameters yet
# For now, use the provided index types
centers = rskmeans(X, n_clusters=100,
index_type='IVFFlat',
max_iter=50)
# FastLSH parameters can be tuned
# (No FAISS needed, highly optimized)
centers = rskmeans(X, n_clusters=100,
index_type='FastLSH',
max_iter=50)
Debugging and Profiling
Profile initialization time:
import cProfile
import pstats
from kmeans_seeding import rskmeans
profiler = cProfile.Profile()
profiler.enable()
centers = rskmeans(X, n_clusters=100,
index_type='FastLSH')
profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(20)
See Also
API Reference - API reference
Scikit-Learn Integration - Sklearn patterns