X is the preprocessed numeric matrix (scaled; see preprocessing-for-clustering.md).
k-means
from sklearn.cluster import KMeans, MiniBatchKMeans
km = KMeans(n_clusters=4, n_init="auto", random_state=0).fit(X)
labels, centres = km.labels_, km.cluster_centers_
mbk = MiniBatchKMeans(n_clusters=4, batch_size=4096, n_init="auto", random_state=0).fit(X) # large dataGaussian mixture (soft assignments, BIC for k)
from sklearn.mixture import GaussianMixture
bics = {k: GaussianMixture(n_components=k, covariance_type="full", n_init=3, random_state=0).fit(X).bic(X)
for k in range(1, 9)}
best_k = min(bics, key=bics.get)
gm = GaussianMixture(n_components=best_k, covariance_type="full", n_init=5, random_state=0).fit(X)
proba = gm.predict_proba(X) # membership probabilitiesBIC spends components on outliers: on the blobs fixture (3 Gaussian blobs + 5% uniform noise) BIC keeps falling up to k = 8, while the same data without the noise points has its minimum at k = 3. Remove or flag noise first (HDBSCAN, robust z-scores), or read the BIC curve for its elbow (here the drop flattens after k = 3-4) rather than its minimum.
HDBSCAN (scikit-learn >= 1.3)
from sklearn.cluster import HDBSCAN
hdb = HDBSCAN(min_cluster_size=15, min_samples=None, cluster_selection_method="eom").fit(X)
labels = hdb.labels_ # -1 = noise
strength = hdb.probabilities_ # membership strengthmin_cluster_size is the main knob (smallest group you care about); min_samples (defaults to it) controls
how conservative the noise labelling is. The standalone hdbscan package adds soft clustering and
approximate_predict for new points.
DBSCAN
from sklearn.cluster import DBSCAN
db = DBSCAN(eps=0.5, min_samples=2 * X.shape[1]).fit(X) # eps from the k-distance knee (dbscan-parameter-tuner)Agglomerative and dendrograms
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster
agg = AgglomerativeClustering(n_clusters=4, linkage="ward").fit(X)
Z = linkage(X, method="ward") # scipy for the dendrogram
labels_at_cut = fcluster(Z, t=4, criterion="maxclust")Linkages: ward (Euclidean, compact clusters), average / complete (any metric, metric="cosine" etc.),
single (chains; finds elongated shapes but is noise-sensitive).
Spectral
from sklearn.cluster import SpectralClustering
sc = SpectralClustering(n_clusters=3, affinity="nearest_neighbors", n_neighbors=15,
assign_labels="cluster_qr", random_state=0).fit(X)Mixed numeric + categorical: k-prototypes
from kmodes.kprototypes import KPrototypes
Xm = df[num_cols + cat_cols].to_numpy(dtype=object)
Xm[:, :len(num_cols)] = StandardScaler().fit_transform(df[num_cols]) # scale the numeric part
kp = KPrototypes(n_clusters=4, init="Cao", n_init=5, random_state=0)
labels = kp.fit_predict(Xm, categorical=list(range(len(num_cols), len(num_cols) + len(cat_cols))))gamma (default: half the numeric std) balances categorical mismatches against numeric distance.
Mixed types: Gower distance
import gower
from sklearn.cluster import HDBSCAN, AgglomerativeClustering
D = gower.gower_matrix(df[num_cols + cat_cols]) # n x n, values in [0, 1]
labels = AgglomerativeClustering(n_clusters=4, metric="precomputed", linkage="average").fit_predict(D)
labels_hdb = HDBSCAN(metric="precomputed", min_cluster_size=15).fit_predict(D.astype("float64"))O(n²) memory: sample or use k-prototypes beyond ~20k rows.
Categorical only: k-modes
from kmodes.kmodes import KModes
km = KModes(n_clusters=4, init="Huang", n_init=5, random_state=0).fit(df[cat_cols])Assigning new points
| Algorithm | New points |
|---|---|
| k-means, GMM, BIRCH | predict |
| DBSCAN / HDBSCAN (sklearn) | no predict: train a classifier on the labels, or nearest core point; hdbscan.approximate_predict in the hdbscan package |
| Agglomerative, spectral | no predict: nearest centroid of the found clusters, or a classifier |
| k-prototypes / k-modes | predict |
anomaly-detection-model-builder
Build and evaluate anomaly detection for tabular, sensor and transaction data with few or no labels: define the anomaly type (point, contextual, collective), choose detectors (robust z-score/MAD and IQR rules, Mahalanobis with robust covariance, k-NN distance, LOF, Isolation Forest, one-class SVM, PCA reconstruction / autoencoders, forecasting residuals for time series), combine them by rank, explain each alert by its deviating features, set thresholds from an alert budget or the score distribution, and evaluate with precision@k, PR-AUC and recall on known incidents, or detector agreement when no labels exist. Includes pure-Python detectors (robust z, Mahalanobis, kNN, Isolation Forest, ensemble) and an evaluation script.
catboost-model-builder
Build CatBoost models that use its strengths correctly: raw categorical columns as cat_features (ordered target statistics, no manual encoding), text_features, Pool construction with NaN-safe categories, ordered boosting and has_time for temporal data, symmetric (oblivious) trees, overfitting detector with eval_set and use_best_model, losses for classification, regression (Quantile, Poisson, Tweedie) and ranking (YetiRank), class weights, monotone constraints, feature importance (PredictionValuesChange, LossFunctionChange) and SHAP values, GPU training and model export. Plans cat/text/numeric columns from a CSV and generates a runnable training script, and checks parameter sets for the conflicts CatBoost rejects (iterations vs n_estimators, Bayesian bootstrap with subsample, multiple class-weight options, depth > 16, use_best_model without eval_set).
categorical-encoding-selector
Choose and implement the right encoding for every categorical column given the model family and the data: one-hot (with infrequent-level grouping and handle_unknown), ordinal with an explicit order, cross-fitted target encoding (scikit-learn TargetEncoder, CatBoost ordered statistics, category_encoders inside CV), frequency/count encoding, feature hashing, native categorical support in LightGBM, HistGradientBoosting, XGBoost and CatBoost, prefix levels for codes (zip3, NAICS-2), and embeddings. Measures cardinality, rare-level share, unseen-level rate on a time-ordered holdout and target signal per column, emits the ColumnTransformer, and quantifies target-encoding leakage (in-sample vs out-of-fold vs holdout AUC).
classification-model-selector
Choose the right classification algorithm for tabular, text or mixed data and prove the choice with a fair bake-off: logistic regression (L2, L1, elastic net), linear SVM, naive Bayes, k-NN, RBF SVM, decision trees, random forest, extra trees, HistGradientBoosting, LightGBM, XGBoost, CatBoost, explainable boosting machines (EBM/GAM), points scorecards and MLPs, matched to data size, width, categorical and high-cardinality share, missingness, class imbalance, text, and constraints such as interpretability, monotonic constraints, calibrated probabilities, latency budgets and tiny deployable models. Ranks candidates with starting hyperparameters and cautions, then generates a bake-off script running every candidate on identical CV folds with per-fold metrics, fit time and prediction latency.
collaborative-filtering-implementer
Implement collaborative filtering recommenders that beat popularity: item-based kNN with cosine, Jaccard or asymmetric similarity, shrinkage, neighbourhood size, positive-only or mean-centred rating signals and 'because you liked X' explanations; implicit ALS with confidence weighting, BPR pairwise ranking and the closed-form EASE model in plain NumPy, tuned on a temporal validation split by recall@k and NDCG@k and refit on all data; plus user-kNN, explicit matrix factorisation, the implicit/LightFM libraries, hyperparameter ranges, cold-start fallbacks, scaling with sparse matrices and approximate nearest neighbours. Produces top-k lists in the format of the recommendation evaluator.
counterfactual-explanation-generator
Generate counterfactual explanations and algorithmic recourse: the smallest realistic change to a row's features that changes the model's decision. Solves exact minimal-cost recourse for linear and logistic models (MAD-scaled L1 cost, immutable features, increase/decrease directions, bounds, integer and binary features, diverse alternatives, features every counterfactual must change, and a no-recourse finding when immutable features decide), generates DiCE counterfactuals for any scikit-learn model with constraints turned into permitted ranges and every result re-predicted, and validates counterfactuals from any method for constraint violations, implausible values, off-manifold rows, broken derived-feature relations and failure to flip the prediction.