Skip to content

[BUG] Fix clustering experiments for clusterers that cannot predict new cases - #553

Open
MatthewMiddlehurst wants to merge 4 commits into
time-series-machine-learning:mainfrom
MatthewMiddlehurst:mm/transductive-clusterers
Open

MatthewMiddlehurst wants to merge 4 commits into
time-series-machine-learning:mainfrom
MatthewMiddlehurst:mm/transductive-clusterers

Conversation

@MatthewMiddlehurst

@MatthewMiddlehurst MatthewMiddlehurst commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Reference Issues/PRs

Resolves the todo in test_clustering.py to add DBSCAN back to the tests.

What does this implement/fix? Explain your changes

run_clustering_experiment fails for scikit-learn clusterers that cannot predict new cases, such as DBSCAN, even for train-only runs. It raises AttributeError: 'DBSCAN' object has no attribute 'predict'. can_predict was only worked out for aeon clusterers. For wrapped scikit-learn clusterers it stayed True, so the train results called predict_proba, which reached DBSCAN.predict. The test fold never checked can_predict, so TimeSeriesAgglomerative also failed whenever a test file was requested.

  • SklearnToAeonClusterer sets aeon's capability:predict tag from whether the wrapped clusterer has predict. scikit-learn has no tag for this; method availability is how it declares it (available_if makes hasattr False). This also applies to OPTICS, HDBSCAN, AgglomerativeClustering and SpectralClustering.
  • run_clustering_experiment reads that tag right after wrapping, so wrapped scikit-learn clusterers use labels_ for train results, as aeon clusterers that cannot predict already do. The TimeSeriesAgglomerative class-name workaround stays, as aeon 1.6.0 does not set its tag.
  • Asking for a test file with a clusterer that cannot predict now raises a ValueError before fitting. Skipping the test file instead would make _check_existing_results rerun the experiment every time, as the file never appears.

Other fixes to SklearnToAeonClusterer found while testing:

  • Negative labels from labels_ and predict are mapped to one cluster after the others. scikit-learn clusterers such as DBSCAN, OPTICS, HDBSCAN and MeanShift(cluster_all=False) label noise -1, which aeon and tsml clusterers do not use. Before, -1 from labels_ was written to file as the prediction while its probability went to the last column through negative indexing. -1 from predict (for example Birch with DBSCAN as its final clustering step) went through aeon's default _predict_proba, which renumbers predictions in place; a negative label made every cluster collapse into one. Relabelling noise raises a warning with the number of cases and the cluster they go to. If predict labels noise but no training cases were noise, there is no noise cluster to use, so it raises a ValueError.
  • n_clusters is only copied from the wrapped clusterer when it is an integer, otherwise it is the number of clusters in labels_. Birch also accepts None or a clusterer. A clusterer raised TypeError in predict_proba, and None made aeon size the probabilities per call, so train and test files had different cluster counts (13 and 8 in one run).

Tests: DBSCAN is back in test_n_clusters, test_transductive_clusterer runs for DBSCAN too and checks that the written predictions match the probabilities, a new test checks the test-file error for both clusterers, and new wrapper tests cover the tag, noise from labels_ and predict with its warnings, noise in predict without training noise, and non-integer n_clusters.

@MatthewMiddlehurst MatthewMiddlehurst added bug Something isn't working experiments Experiments package estimators Estimators package labels Oct 19, 2026
@tsml-actions-bot

Copy link
Copy Markdown
Contributor

Thank you for contributing to tsml-eval

I would have added the following labels to this PR based on the changes made: estimators experiments, however some package labels are already present.

The Checks tab will show the status of our automated tests. You can click on individual test runs in the tab or "Details" in the panel below to see more information if there is a failure.

If our pre-commit code quality check fails, please run pre-commit locally and push the fixes to your PR branch.

PR CI actions

These checkboxes will add labels to enable or disable CI functionality for this PR. This may not take effect immediately, and a new commit may be required to run the new configuration.

  • Run pre-commit checks for all files
  • Run all pytest tests and configurations
  • Run all notebook example tests
  • Push an empty commit to re-run CI checks

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working estimators Estimators package experiments Experiments package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant