Error-Aware Clustering
Overview
Error-aware clustering groups samples by their residual behavior rather than by raw feature proximity, so segments where a model makes similar (large) errors are surfaced as coherent clusters. Where slicing partitions one or two features at a time, this method clusters over the full feature space through a supervised model fit to the residual, exposing multivariate pockets of weak performance.
Two clustering algorithms are available, both operating on a residual response:
LTC (Learning Trajectory Cluster) — the default. A gradient-boosting model is fit to the residual response; its per-stage prediction trajectories are weighted, reduced with PCA, and clustered with k-means. Samples that the booster learns along a similar path fall in the same cluster.
RF (Random Forest) — a random forest is fit to the residual response; a proximity matrix is built from how often samples share tree leaves, and the resulting distance matrix is clustered with KMedoids.
Method
The test proceeds in three steps:
Residual response: For each sample a residual-based response is computed. The response type is configurable (
response_type):abs_residual/sq_residual— absolute or squared residual (defaultabs_residual).abs_residual_perturb/sq_residual_perturb— residual after input perturbation, as in the robustness test.pi_width— conformal prediction-interval width, as in the reliability test.
Clustering: Samples are grouped into
n_clustersclusters using LTC or RF (cluster_method).Per-cluster evaluation: The model metric and average residual are computed per cluster, ranking clusters from best to worst so weak segments stand out.
Implementation in MoDeVa
from modeva import DataSet, TestSuite
from modeva.models import MoXGBRegressor
# Load data
ds = DataSet()
ds.load("CaliforniaHousing")
ds.set_target(feature="MedHouseVal")
ds.set_task_type("Regression")
ds.set_random_split(test_ratio=0.2)
# Train model
model = MoXGBRegressor(
name="XGBoost", n_estimators=200, max_depth=5, learning_rate=0.1
)
model.fit(ds.train_x, ds.train_y.ravel())
# Run error-aware clustering
ts = TestSuite(ds, model)
result = ts.diagnose_residual_cluster(
dataset="test",
response_type="abs_residual",
n_clusters=10,
cluster_method="ltc", # or "rf"
)
# Per-cluster performance table
result.table
Output Interpretation
diagnose_residual_cluster returns a ValidationResult whose table ranks the
clusters by performance and whose value holds the cluster labels, the assignment
function, and per-cluster sample indices. Three plots are available.
Cluster Residual
Average residual response per cluster — the clusters with the highest bars are the weak segments the model struggles with most.
result.plot(name="cluster_residual")
Cluster Performance
The model metric per cluster, making performance heterogeneity across regions directly visible.
result.plot(name="cluster_performance")
Feature Importance
Feature importance of the random forest fit to the residual response, indicating which features most explain where the model errs.
result.plot(name="feature_importance")
Drilling into a Weak Cluster
Each cluster carries the sample indices inside and outside it, which can be fed straight into a data-distribution test to characterize how a weak cluster differs from the rest:
data_results = ds.data_drift_test(**result.value["clusters"][2]["data_info"])
data_results.plot("summary")
data_results.plot(("density", "MedInc"))
Parameters
The diagnose_residual_cluster method accepts the following key parameters:
For the perturbation response types, the robustness-test perturbation parameters
(perturb_features, perturb_method, noise_level, n_repeats) also apply;
for pi_width, the conformal alpha applies.
Key Method
See the TestSuite API Reference for full method documentation.