Algorithms
This page gives step-by-step explanations, pseudocode, input/output definitions, and complexity estimates for the main algorithms.
Notation used in this page:
| Symbol |
Meaning |
n |
number of samples |
d |
number of features |
m |
number of divergences |
K |
number of clusters per divergence |
I |
number of Lloyd iterations |
R |
number of random initializations in Bregman K-Means |
q |
number of base estimators in COBRA |
n_l |
number of calibration samples |
1. Bregman K-Means
| Name |
Shape |
Description |
X |
(n, d) |
Feature matrix. |
n_clusters |
scalar |
Number of clusters. |
divergence |
object |
Bregman divergence implementation. |
max_iter |
scalar |
Maximum Lloyd iterations. |
n_init |
scalar |
Number of random initializations. |
Output
| Name |
Shape |
Description |
labels_ |
(n,) |
Cluster assignment for each sample. |
cluster_centers_ |
(K, d) |
Learned centroids. |
inertia_ |
scalar |
Best average distortion. |
n_iter_ |
scalar |
Iterations used by best run. |
Pseudocode
Algorithm: BregmanKMeans.fit(X)
Input: X, divergence D_phi, K, max_iter, n_init
Output: labels, centroids
1. Validate X and divergence domain.
2. best_distortion ← +∞
3. For r = 1 to n_init:
a. Initialize K centroids by sampling training points.
b. previous_distortion ← +∞
c. For t = 1 to max_iter:
i. Compute distance matrix D[i, k] = D_phi(X_i, μ_k)
ii. Assign label_i = argmin_k D[i, k]
iii. Update each centroid μ_k = mean({X_i : label_i = k})
iv. Reinitialize empty clusters with random data points.
v. Compute average minimum distortion.
vi. Stop if relative distortion change < tol.
d. If run distortion is lower than best_distortion, save run.
4. Store best labels and centroids.
Complexity
Each Lloyd iteration computes a distance matrix between n samples and K centroids.
| Quantity |
Complexity |
| Time per iteration |
O(n K d) |
| Time per fit |
O(R I n K d) |
| Distance matrix memory |
O(n K) |
| Centroid memory |
O(K d) |
The implementation computes distortion in blocks to reduce peak memory during scoring, but assignment still builds a distance matrix for each iteration.
2. K-step: multi-divergence clustering
| Name |
Shape |
Description |
X |
(n, d) |
Training features. |
divergences |
list length m |
Divergence identifiers or objects. |
n_clusters |
scalar |
Number of clusters per divergence. |
Output
models_ = {
"euclidean": BregmanKMeans(...),
"gkl": BregmanKMeans(...),
}
clusters_ = {
"euclidean": array([...]),
"gkl": array([...]),
}
Pseudocode
Algorithm: KStep.fit(X)
Input: X, divergences = [d1, ..., dm]
Output: models_, clusters_
1. Convert X to float array.
2. For each divergence d_j:
a. Resolve string name to divergence object.
b. Create BregmanKMeans(n_clusters=K, divergence=d_j).
c. Fit BregmanKMeans on X.
d. Store fitted model under divergence name.
e. Store model.labels_ under divergence name.
3. Return self.
Complexity
If each divergence uses R initializations and I iterations:
| Quantity |
Complexity |
| Time |
O(m R I n K d) |
| Memory |
O(m (K d + n)) for stored models and cluster labels |
3. F-step: cluster-local model fitting
| Name |
Shape |
Description |
X |
(n, d) |
Training features. |
y |
(n,) |
Target values or class labels. |
clusters |
dictionary |
One cluster assignment array per divergence. |
local_model |
string or object |
Local supervised model. |
Output
Nested dictionary of fitted local models:
models_[divergence_name][cluster_key] = {
"divergence": div_name,
"cluster": cluster_id,
"model": fitted_model,
}
Pseudocode
Algorithm: FStep.fit(X, y, clusters)
Input: X, y, clusters dictionary
Output: models_
1. For each divergence name div_name:
a. Create empty model dictionary.
b. For each cluster id k in unique cluster labels:
i. Select samples where clusters[div_name] == k.
ii. Resolve local model from LocalModelFactory.
iii. Fit local model on selected samples.
iv. Store fitted model.
2. Return self.
Prediction pseudocode
Algorithm: FStep.predict(X, clusters)
Input: X, cluster assignments for X
Output: P prediction matrix
1. outputs ← []
2. For each divergence div_name:
a. pred ← array of NaN with length n
b. For each fitted cluster model:
i. Select samples assigned to this cluster.
ii. Predict those samples using the cluster model.
iii. Write predictions into pred.
c. Append pred as one column to outputs.
3. Return column_stack(outputs)
Complexity
Let T_fit(n_k, d) be the training cost of the selected local model on cluster k, and T_pred(n_k, d) its prediction cost.
| Quantity |
Complexity |
| Fit time |
O(Σ_j Σ_k T_fit(n_{j,k}, d)) |
| Predict time |
O(Σ_j Σ_k T_pred(n_{j,k}^{test}, d)) |
| Model memory |
O(m K × model_size) |
| Prediction matrix memory |
O(n m) |
4. C-step: prediction aggregation
| Name |
Shape |
Description |
P |
(n, m) |
Prediction matrix from F-step. |
y |
(n,) |
Ground-truth values for training learned combiners. |
combiner |
string or object |
Aggregation strategy. |
Output
| Name |
Shape |
Description |
y_pred |
(n,) |
Final prediction. |
Pseudocode
Algorithm: CStep.fit(P, y)
Input: prediction matrix P, target y
Output: fitted strategy_
1. Resolve combiner from CombinerFactory.
2. Fit combiner on (P, y).
3. Store fitted strategy_.
Algorithm: CStep.predict(P)
Input: prediction matrix P
Output: final predictions
1. Check that strategy_ is fitted.
2. Return strategy_.predict(P).
Complexity by combiner
| Combiner |
Fit time |
Predict time |
Notes |
mean |
O(1) |
O(n m) |
Stateless row mean. |
weighted_mean |
approximately O(n m^2 + m^3) |
O(n m) |
Linear regression over prediction columns. |
stacking_regressor |
depends on meta-model |
depends on meta-model |
Default is linear regression. |
majority_vote |
O(1) |
O(n m) |
Row-wise mode. |
stacking_classifier |
depends on meta-classifier |
depends on meta-classifier |
Default logistic regression. |
| COBRA combiners |
O(n_l^2 m + optimization) |
O(n_test n_l m) |
Kernel aggregation over calibration samples. |
5. Full KFCProcedure training algorithm
| Name |
Shape |
Description |
X |
(n, d) |
Feature matrix. |
y |
(n,) |
Target values or labels. |
divergences |
list length m |
Divergences for K-step. |
local_model |
string/object |
F-step local model. |
combiner |
string/object |
C-step combiner. |
Output
A fitted estimator containing:
Pseudocode
Algorithm: KFCProcedure.fit(X, y)
Input: X, y
Output: fitted KFCProcedure
1. Convert X and y to NumPy arrays.
2. Split data into two halves:
(X_k, y_k) for K-step and F-step
(X_l, y_l) for C-step calibration
If task is classification, stratify by y.
3. K-step:
a. Fit KStep on X_k.
b. Obtain training clusters for X_k.
c. Predict clusters for X_l.
4. F-step:
a. Fit local models on X_k, y_k using training clusters.
b. Predict X_l using local models and X_l clusters.
c. Build prediction matrix P_l.
5. C-step:
a. Fit combiner on P_l, y_l.
6. Return fitted estimator.
Prediction pseudocode
Algorithm: KFCProcedure.predict(X_new)
Input: X_new
Output: final predictions
1. Predict cluster assignments for X_new using kstep_.
2. Predict local outputs using fstep_.
3. Build prediction matrix P.
4. Return cstep_.predict(P).
Complexity
Let n_t ≈ n/2 be the K/F training size and n_l ≈ n/2 be the C-step calibration size.
| Stage |
Time |
| K-step fit |
O(m R I n_t K d) |
| F-step fit |
O(Σ_j Σ_k T_fit(n_{j,k}, d)) |
| F-step calibration prediction |
O(Σ_j Σ_k T_pred(n_{j,k}^{cal}, d)) |
| C-step fit |
combiner-dependent |
Prediction for s test samples:
| Stage |
Time |
| Cluster assignment |
O(m s K d) |
| Local prediction |
O(Σ_j Σ_k T_pred(s_{j,k}, d)) |
| Aggregation |
combiner-dependent |
6. GradientCOBRA algorithm
| Name |
Shape |
Description |
X |
(n, d) |
Training features or prediction matrix if as_predictions=True. |
y |
(n,) |
Regression target. |
estimators |
list |
Base estimators, unless using precomputed predictions. |
Output
- fitted base estimators, if not using
as_predictions=True;
- calibration prediction matrix;
- optimized bandwidth;
- fitted distance, kernel, loss, optimizer, and aggregator components.
Pseudocode
Algorithm: GradientCOBRA.fit(X, y)
Input: X, y
Output: fitted GradientCOBRA
1. Resolve training context into model-training and calibration subsets.
2. If as_predictions is False:
a. Fit base estimators on X_k, y_k.
b. Predict calibration set X_l to build Z_l.
Else:
a. Treat X_l as precomputed prediction features Z_l.
3. Normalize prediction matrix Z_l.
4. Compute pairwise distance matrix between calibration prediction vectors.
5. Create cross-validation folds on the calibration set.
6. Optimize bandwidth by minimizing CV loss:
a. Transform distances with bandwidth.
b. Apply kernel to obtain weights.
c. Aggregate calibration targets.
d. Evaluate loss.
7. Store best bandwidth and optimization history.
Prediction pseudocode
Algorithm: GradientCOBRA.predict(X_new)
Input: X_new
Output: y_pred
1. Build prediction-space representation Z_new.
2. Normalize Z_new using stored normalization constant.
3. Compute distances from Z_new to calibration prediction matrix Z_l.
4. Apply optimized bandwidth and kernel.
5. Aggregate calibration targets y_l using kernel weights.
6. Return predictions.
Complexity
| Stage |
Complexity |
| Base estimator training |
Σ T_fit_base |
| Calibration predictions |
Σ T_pred_base |
| Calibration distance matrix |
O(n_l^2 q) |
| Grid optimization |
O(G n_l^2 + CV aggregation) |
| Prediction |
O(s n_l q) plus base estimator prediction |
G is the number of bandwidth candidates.
7. MixCOBRA algorithm
MixCOBRARegressor extends COBRA by combining two similarity spaces:
- original input space
X;
- prediction space
Z from base estimator outputs.
Pseudocode
Algorithm: MixCOBRARegressor.fit(X, y)
Input: X, y
Output: fitted MixCOBRARegressor
1. Resolve training and calibration subsets.
2. Train base estimators and compute prediction matrix Z_l, unless as_predictions=True.
3. Normalize X_l and Z_l.
4. If one_parameter=True:
a. Concatenate normalized [X_l, Z_l].
b. Compute one mixed distance matrix.
c. Optimize a bandwidth-like parameter.
5. Else:
a. Compute D_x in input space.
b. Compute D_z in prediction space.
c. Optimize alpha and beta in D = alpha D_x + beta D_z.
6. Store optimized parameters.
Prediction pseudocode
Algorithm: MixCOBRARegressor.predict(X_new)
Input: X_new
Output: predictions
1. Generate or receive prediction features Z_new.
2. Normalize X_new and Z_new.
3. Compute distances to calibration samples.
4. Combine distances using optimized parameter(s).
5. Apply kernel.
6. Aggregate calibration targets with kernel weights.
Complexity
| Stage |
Complexity |
| Fit distance matrices |
O(n_l^2 d + n_l^2 q) |
| Grid optimization, two parameters |
O(G_alpha G_beta n_l^2) |
| Grid optimization, one parameter |
O(G n_l^2) |
| Prediction |
O(s n_l (d + q)) |
8. CombinedClassifier algorithm
CombinedClassifier is the classification counterpart to kernel-weighted COBRA aggregation.
Pseudocode
Algorithm: CombinedClassifier.fit(X, y)
Input: X, class labels y
Output: fitted CombinedClassifier
1. Resolve training and calibration subsets.
2. Train base estimators and compute calibration prediction matrix, unless as_predictions=True.
3. Store class labels and global majority class.
4. Resolve distance, kernel, aggregator, loss, optimizer, adapter, and CV components.
5. Compute pairwise distances in prediction space.
6. Optimize kernel bandwidth using cross-validation.
Algorithm: CombinedClassifier.predict(X_new)
Input: X_new
Output: predicted class labels
1. Compute prediction-space representation for X_new.
2. Compute distances to calibration prediction matrix.
3. Apply bandwidth and kernel to obtain weights.
4. If no positive weights, return the global majority class.
5. Otherwise, apply weighted vote over calibration labels.
Complexity
| Stage |
Complexity |
| Calibration distance matrix |
O(n_l^2 q) |
| Optimization |
O(G n_l^2) for grid search |
| Prediction |
O(s n_l q) |
| Probability prediction |
O(s n_l + s C) where C is number of classes |