torchmetrics declares DaviesBouldinScore.higher_is_better = True. The Davies-Bouldin index is
lower-is-better: it decreases as clusters get tighter and better separated, with a minimum of 0.
So the flag says a higher Davies-Bouldin score is better, the opposite of what the index means, and
MetricTracker, which reads the flag to pick the best epoch, selects the worst clustering.
In torchmetrics/clustering/davies_bouldin_score.py:
higher_is_better: bool = True(line 79)plot_lower_bound: float = 0.0(line 81)- the docstring is copied verbatim from Calinski-Harabasz: line 51 "The score is higher when clusters are dense and well separated," and line 62 describes the output as "Calinski Harabasz Score."
The index itself, DB = (1/n) sum_i max_{j != i} (S_i + S_j) / D_ij with S the intra-cluster
scatter and D the centroid distance, is minimized by good clustering, and scikit-learn documents
it as "the minimum score is zero, with lower values indicating better clustering." A plot_lower_bound
of 0.0 is the shape of a minimized metric, which agrees with lower-is-better and disagrees with the
higher_is_better=True flag on the same class. The sibling CalinskiHarabaszScore also declares
higher_is_better=True, but that one is correct, so Davies-Bouldin is the odd one out: the flag and
the docstring rode in together from a copy of Calinski-Harabasz.
| metric | direction | higher_is_better |
correct |
|---|---|---|---|
| Calinski-Harabasz | higher is better | True |
yes |
| Davies-Bouldin | lower is better (min 0) | True |
no |
MetricTracker sets maximize = metric.higher_is_better (wrappers/tracker.py:126) and its
best_metric() returns the epoch with the largest value when maximize is True. Tracking
Davies-Bouldin to choose a checkpoint should minimize it; with the wrong flag the tracker maximizes
it:
Davies-Bouldin: well-separated = 0.026, overlapping = 5.939
MetricTracker (maximize = higher_is_better = True) picks: epoch_bad
actually best (lowest DB): epoch_good
Any run that tracks DaviesBouldinScore across epochs or models and lets MetricTracker pick the
best gets the worst clustering selected.
excerpt.py: thehigher_is_betterandplot_lower_bounddeclarations and the copied docstring lines, quoted with line numbers (Apache-2.0), plus theMetricTrackerflag use.direction.py: the metric is lower-is-better, so the flag should be False; theplot_lower_boundagrees with lower-is-better and the Calinski-Harabasz sibling is correct.consequence.py: the Davies-Bouldin index from its definition and the tracker's own selection, showing the worst clustering picked as best.test_dbflip.py: lower DB is better, the flag contradicts the definition, the lower bound matches a minimized metric, the sibling is correct, and the tracker selects the worst clustering.
python direction.py
python consequence.py
python test_dbflip.py
The declarations are quoted from the master branch; the fix is higher_is_better = False for
DaviesBouldinScore, and repairing the copied docstring.