From a495364d7c4b2787e32da23010a5eb7f9d2233e3 Mon Sep 17 00:00:00 2001 From: MatthewMiddlehurst Date: Tue, 13 Oct 2026 12:38:40 +0100 Subject: [PATCH 1/8] [MNT] Restructure the distance based clusterers in get_clusterer_by_name Match names exactly like the other getters, instead of using substrings. The distance is taken from the name once, and kwargs are only passed on. The clusterers and parameters returned are unchanged. ElasticSOM now receives kwargs, which were ignored. The "No distance metric specified" print is removed. --- tsml_eval/experiments/_get_clusterer.py | 185 +++++++++++------------- 1 file changed, 86 insertions(+), 99 deletions(-) diff --git a/tsml_eval/experiments/_get_clusterer.py b/tsml_eval/experiments/_get_clusterer.py index e619aba1..42da5593 100644 --- a/tsml_eval/experiments/_get_clusterer.py +++ b/tsml_eval/experiments/_get_clusterer.py @@ -196,6 +196,8 @@ def get_clusterer_by_name( `tsml_eval.utils.experiments import load_experiment_data`. row_normalise: bool, default=False Whether to row normalise the data if it is loaded using data_vars. + **kwargs + Additional keyword arguments to be passed to the clusterer. Return ------ @@ -298,108 +300,122 @@ def _set_clusterer_distance_based( row_normalise, kwargs, ): - if "init_algorithm" in kwargs: - init_algorithm = kwargs["init_algorithm"] - else: - init_algorithm = "random" + if c == "kspectralcentroid" or c == "ksc": + return KSpectralCentroid( + # Max shift set to n_timepoints when max_shift is None + max_shift=None, + init="random", + tol=1e-06, + random_state=random_state, + **kwargs, + ) + elif c == "timeserieskshape" or c == "kshape": + return KShape( + init="random", + n_init=10, + tol=1e-06, + random_state=random_state, + **kwargs, + ) + elif c == "timeserieskernelkmeans": + return TimeSeriesKernelKMeans( + n_init=10, + tol=1e-06, + random_state=random_state, + n_jobs=n_jobs, + **kwargs, + ) + elif c == "kasba": + from aeon.clustering import KASBA - if "distance" in kwargs: - distance = kwargs["distance"] - else: - if "-" not in c: - print("No distance metric specified, using default DTW") # noqa: T201 - distance = "dtw" - else: - distance = c.split("-")[-1] - - if "distance_params" in kwargs: - distance_params = kwargs["distance_params"] - else: - distance_params = _get_distance_default_params( - distance, data_vars, row_normalise + return KASBA( + random_state=random_state, + **kwargs, ) - if "kmeans" in c or "timeserieskmeans" in c: - if "average_params" in kwargs: - average_params = kwargs["average_params"] - else: - average_params = {"distance": distance, **distance_params.copy()} + # the remaining names end with the distance to use i.e. "kmeans-msm", the + # clusterer class names use dtw + if "-" in c: + name, distance = c.rsplit("-", 1) + else: + name, distance = c, "dtw" + distance_params = _get_distance_default_params(distance, data_vars, row_normalise) - if "ssg" in c: + if name == "kmeans" or name == "timeserieskmeans": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance=distance, + distance_params=distance_params, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif name == "kmeans-ba": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance=distance, + distance_params=distance_params, + random_state=random_state, + averaging_method="ba", + average_params={"distance": distance, **distance_params}, + **kwargs, + ) + elif name == "kmeans-ssg-ba": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance=distance, + distance_params=distance_params, + random_state=random_state, + averaging_method="ba", # Sets to use subgradient BA - average_params = { - **average_params, + average_params={ + "distance": distance, + **distance_params, "method": "subgradient", - } - return TimeSeriesKMeans( - n_init=10, - init=init_algorithm, - distance=distance, - distance_params=distance_params, - random_state=random_state, - averaging_method="ba", - average_params=average_params, - **kwargs, - ) - elif "ba" in c: - return TimeSeriesKMeans( - n_init=10, - init=init_algorithm, - distance=distance, - distance_params=distance_params, - random_state=random_state, - averaging_method="ba", - average_params=average_params, - **kwargs, - ) - else: - return TimeSeriesKMeans( - n_init=10, - init=init_algorithm, - distance=distance, - distance_params=distance_params, - random_state=random_state, - averaging_method="mean", - **kwargs, - ) - elif "kmedoids" in c or "timeserieskmedoids" in c: + }, + **kwargs, + ) + elif name == "kmedoids" or name == "timeserieskmedoids": return TimeSeriesKMedoids( n_init=10, - init=init_algorithm, + init="random", distance=distance, distance_params=distance_params, random_state=random_state, method="alternate", **kwargs, ) - elif "pam" in c or "timeseriespam" in c: + elif name == "pam": return TimeSeriesKMedoids( n_init=10, - init=init_algorithm, + init="random", distance=distance, distance_params=distance_params, random_state=random_state, method="pam", **kwargs, ) - elif "clarans" in c or "timeseriesclarans" in c: + elif name == "clarans" or name == "timeseriesclarans": return TimeSeriesCLARANS( n_init=10, - init=init_algorithm, + init="random", distance=distance, distance_params=distance_params, random_state=random_state, **kwargs, ) - elif "clara" in c or "timeseriesclara" in c: + elif name == "clara" or name == "timeseriesclara": return TimeSeriesCLARA( - init=init_algorithm, + init="random", distance=distance, distance_params=distance_params, random_state=random_state, **kwargs, ) - elif "som" in c or "elasticsom" in c: + elif name == "som" or name == "elasticsom": return ElasticSOM( distance=distance, init="random", @@ -412,40 +428,9 @@ def _set_clusterer_distance_based( distance_params=distance_params, random_state=random_state, verbose=False, - ) - elif "ksc" in c or "kspectralcentroid" in c: - return KSpectralCentroid( - # Max shift set to n_timepoints when max_shift is None - max_shift=None, - init=init_algorithm, - tol=1e-06, - random_state=random_state, - **kwargs, - ) - elif "kshape" in c: - return KShape( - init=init_algorithm, - n_init=10, - tol=1e-06, - random_state=random_state, **kwargs, ) - elif "timeserieskernelkmeans" in c: - return TimeSeriesKernelKMeans( - n_init=10, - tol=1e-06, - random_state=random_state, - n_jobs=n_jobs, - **kwargs, - ) - elif c == "kasba": - from aeon.clustering import KASBA - - return KASBA( - random_state=random_state, - **kwargs, - ) - elif "agglomerative" in c: + elif name == "agglomerative" or name == "timeseriesagglomerative": from aeon.clustering import TimeSeriesAgglomerative return TimeSeriesAgglomerative( @@ -453,6 +438,8 @@ def _set_clusterer_distance_based( distance_params=distance_params, **kwargs, ) + else: + raise ValueError(f"UNKNOWN CLUSTERER: {c} in get_clusterer_by_name") def _get_distance_default_params( From 9a142be2a5554445d0ebb4dcf4604f26e7b574de Mon Sep 17 00:00:00 2001 From: MatthewMiddlehurst Date: Sun, 18 Oct 2026 15:53:57 +0100 Subject: [PATCH 2/8] Create each distance based clusterer explicitly One branch per name in distance_based_clusterers with its settings written out, as in the other getters, instead of splitting the distance from the name. Distances without default parameters now leave distance_params as None rather than {}. Only the data dependent ERP g still uses a helper. Remove the TimeSeriesKernelKMeans branch, which had no name in the list. --- tsml_eval/experiments/_get_clusterer.py | 1200 +++++++++++++++++++++-- 1 file changed, 1098 insertions(+), 102 deletions(-) diff --git a/tsml_eval/experiments/_get_clusterer.py b/tsml_eval/experiments/_get_clusterer.py index 42da5593..9c457268 100644 --- a/tsml_eval/experiments/_get_clusterer.py +++ b/tsml_eval/experiments/_get_clusterer.py @@ -9,7 +9,6 @@ KSpectralCentroid, TimeSeriesCLARA, TimeSeriesCLARANS, - TimeSeriesKernelKMeans, TimeSeriesKMeans, TimeSeriesKMedoids, ) @@ -300,124 +299,1025 @@ def _set_clusterer_distance_based( row_normalise, kwargs, ): - if c == "kspectralcentroid" or c == "ksc": - return KSpectralCentroid( - # Max shift set to n_timepoints when max_shift is None - max_shift=None, + if c == "kmeans-euclidean": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="euclidean", + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-squared": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="squared", + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-dtw" or c == "timeserieskmeans": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="dtw", + distance_params={"window": 0.2}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-ddtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="ddtw", + distance_params={"window": 0.2}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-wdtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="wdtw", + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-wddtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="wddtw", + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-lcss": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="lcss", + distance_params={"epsilon": 1.0}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-erp": + g = _get_erp_g(data_vars, row_normalise) + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="erp", + distance_params={"g": g}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-edr": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="edr", + distance_params={"epsilon": None}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-twe": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="twe", + distance_params={"nu": 0.001, "lmbda": 1.0}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-msm": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="msm", + distance_params={"c": 1.0, "independent": True}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-adtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="adtw", + distance_params={"warp_penalty": 1.0}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmeans-shape_dtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="shape_dtw", + distance_params={"descriptor": "identity", "reach": 30}, + random_state=random_state, + averaging_method="mean", + **kwargs, + ) + elif c == "kmedoids-euclidean": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="euclidean", + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-squared": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="squared", + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-dtw" or c == "timeserieskmedoids": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="dtw", + distance_params={"window": 0.2}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-ddtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="ddtw", + distance_params={"window": 0.2}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-wdtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="wdtw", + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-wddtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="wddtw", + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-lcss": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="lcss", + distance_params={"epsilon": 1.0}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-erp": + g = _get_erp_g(data_vars, row_normalise) + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="erp", + distance_params={"g": g}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-edr": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="edr", + distance_params={"epsilon": None}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-twe": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="twe", + distance_params={"nu": 0.001, "lmbda": 1.0}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-msm": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="msm", + distance_params={"c": 1.0, "independent": True}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-adtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="adtw", + distance_params={"warp_penalty": 1.0}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "kmedoids-shape_dtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="shape_dtw", + distance_params={"descriptor": "identity", "reach": 30}, + random_state=random_state, + method="alternate", + **kwargs, + ) + elif c == "clarans-euclidean": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="euclidean", + random_state=random_state, + **kwargs, + ) + elif c == "clarans-squared": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="squared", + random_state=random_state, + **kwargs, + ) + elif c == "clarans-dtw" or c == "timeseriesclarans": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="dtw", + distance_params={"window": 0.2}, + random_state=random_state, + **kwargs, + ) + elif c == "clarans-ddtw": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="ddtw", + distance_params={"window": 0.2}, + random_state=random_state, + **kwargs, + ) + elif c == "clarans-wdtw": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="wdtw", + random_state=random_state, + **kwargs, + ) + elif c == "clarans-wddtw": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="wddtw", + random_state=random_state, + **kwargs, + ) + elif c == "clarans-lcss": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="lcss", + distance_params={"epsilon": 1.0}, + random_state=random_state, + **kwargs, + ) + elif c == "clarans-erp": + g = _get_erp_g(data_vars, row_normalise) + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="erp", + distance_params={"g": g}, + random_state=random_state, + **kwargs, + ) + elif c == "clarans-edr": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="edr", + distance_params={"epsilon": None}, + random_state=random_state, + **kwargs, + ) + elif c == "clarans-twe": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="twe", + distance_params={"nu": 0.001, "lmbda": 1.0}, + random_state=random_state, + **kwargs, + ) + elif c == "clarans-msm": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="msm", + distance_params={"c": 1.0, "independent": True}, + random_state=random_state, + **kwargs, + ) + elif c == "clarans-adtw": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="adtw", + distance_params={"warp_penalty": 1.0}, + random_state=random_state, + **kwargs, + ) + elif c == "clarans-shape_dtw": + return TimeSeriesCLARANS( + n_init=10, + init="random", + distance="shape_dtw", + distance_params={"descriptor": "identity", "reach": 30}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-euclidean": + return TimeSeriesCLARA( + init="random", + distance="euclidean", + random_state=random_state, + **kwargs, + ) + elif c == "clara-squared": + return TimeSeriesCLARA( + init="random", + distance="squared", + random_state=random_state, + **kwargs, + ) + elif c == "clara-dtw" or c == "timeseriesclara": + return TimeSeriesCLARA( + init="random", + distance="dtw", + distance_params={"window": 0.2}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-ddtw": + return TimeSeriesCLARA( + init="random", + distance="ddtw", + distance_params={"window": 0.2}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-wdtw": + return TimeSeriesCLARA( + init="random", + distance="wdtw", + random_state=random_state, + **kwargs, + ) + elif c == "clara-wddtw": + return TimeSeriesCLARA( + init="random", + distance="wddtw", + random_state=random_state, + **kwargs, + ) + elif c == "clara-lcss": + return TimeSeriesCLARA( + init="random", + distance="lcss", + distance_params={"epsilon": 1.0}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-erp": + g = _get_erp_g(data_vars, row_normalise) + return TimeSeriesCLARA( + init="random", + distance="erp", + distance_params={"g": g}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-edr": + return TimeSeriesCLARA( + init="random", + distance="edr", + distance_params={"epsilon": None}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-twe": + return TimeSeriesCLARA( + init="random", + distance="twe", + distance_params={"nu": 0.001, "lmbda": 1.0}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-msm": + return TimeSeriesCLARA( + init="random", + distance="msm", + distance_params={"c": 1.0, "independent": True}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-adtw": + return TimeSeriesCLARA( + init="random", + distance="adtw", + distance_params={"warp_penalty": 1.0}, + random_state=random_state, + **kwargs, + ) + elif c == "clara-shape_dtw": + return TimeSeriesCLARA( + init="random", + distance="shape_dtw", + distance_params={"descriptor": "identity", "reach": 30}, + random_state=random_state, + **kwargs, + ) + elif c == "pam-euclidean": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="euclidean", + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-squared": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="squared", + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-dtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="dtw", + distance_params={"window": 0.2}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-ddtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="ddtw", + distance_params={"window": 0.2}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-wdtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="wdtw", + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-wddtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="wddtw", + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-lcss": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="lcss", + distance_params={"epsilon": 1.0}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-erp": + g = _get_erp_g(data_vars, row_normalise) + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="erp", + distance_params={"g": g}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-edr": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="edr", + distance_params={"epsilon": None}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-twe": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="twe", + distance_params={"nu": 0.001, "lmbda": 1.0}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-msm": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="msm", + distance_params={"c": 1.0, "independent": True}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-adtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="adtw", + distance_params={"warp_penalty": 1.0}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "pam-shape_dtw": + return TimeSeriesKMedoids( + n_init=10, + init="random", + distance="shape_dtw", + distance_params={"descriptor": "identity", "reach": 30}, + random_state=random_state, + method="pam", + **kwargs, + ) + elif c == "kmeans-ba-dtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="dtw", + distance_params={"window": 0.2}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "dtw", "window": 0.2}, + **kwargs, + ) + elif c == "kmeans-ba-ddtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="ddtw", + distance_params={"window": 0.2}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "ddtw", "window": 0.2}, + **kwargs, + ) + elif c == "kmeans-ba-wdtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="wdtw", + random_state=random_state, + averaging_method="ba", + average_params={"distance": "wdtw"}, + **kwargs, + ) + elif c == "kmeans-ba-wddtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="wddtw", + random_state=random_state, + averaging_method="ba", + average_params={"distance": "wddtw"}, + **kwargs, + ) + elif c == "kmeans-ba-lcss": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="lcss", + distance_params={"epsilon": 1.0}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "lcss", "epsilon": 1.0}, + **kwargs, + ) + elif c == "kmeans-ba-erp": + g = _get_erp_g(data_vars, row_normalise) + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="erp", + distance_params={"g": g}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "erp", "g": g}, + **kwargs, + ) + elif c == "kmeans-ba-edr": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="edr", + distance_params={"epsilon": None}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "edr", "epsilon": None}, + **kwargs, + ) + elif c == "kmeans-ba-twe": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="twe", + distance_params={"nu": 0.001, "lmbda": 1.0}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "twe", "nu": 0.001, "lmbda": 1.0}, + **kwargs, + ) + elif c == "kmeans-ba-msm": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="msm", + distance_params={"c": 1.0, "independent": True}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "msm", "c": 1.0, "independent": True}, + **kwargs, + ) + elif c == "kmeans-ba-adtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="adtw", + distance_params={"warp_penalty": 1.0}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "adtw", "warp_penalty": 1.0}, + **kwargs, + ) + elif c == "kmeans-ba-shape_dtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="shape_dtw", + distance_params={"descriptor": "identity", "reach": 30}, + random_state=random_state, + averaging_method="ba", + average_params={ + "distance": "shape_dtw", + "descriptor": "identity", + "reach": 30, + }, + **kwargs, + ) + elif c == "kmeans-ssg-ba-dtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="dtw", + distance_params={"window": 0.2}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "dtw", "window": 0.2, "method": "subgradient"}, + **kwargs, + ) + elif c == "kmeans-ssg-ba-ddtw": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="ddtw", + distance_params={"window": 0.2}, + random_state=random_state, + averaging_method="ba", + average_params={"distance": "ddtw", "window": 0.2, "method": "subgradient"}, + **kwargs, + ) + elif c == "kmeans-ssg-ba-wdtw": + return TimeSeriesKMeans( + n_init=10, init="random", - tol=1e-06, + distance="wdtw", random_state=random_state, + averaging_method="ba", + average_params={"distance": "wdtw", "method": "subgradient"}, **kwargs, ) - elif c == "timeserieskshape" or c == "kshape": - return KShape( - init="random", + elif c == "kmeans-ssg-ba-wddtw": + return TimeSeriesKMeans( n_init=10, - tol=1e-06, + init="random", + distance="wddtw", random_state=random_state, + averaging_method="ba", + average_params={"distance": "wddtw", "method": "subgradient"}, **kwargs, ) - elif c == "timeserieskernelkmeans": - return TimeSeriesKernelKMeans( + elif c == "kmeans-ssg-ba-erp": + g = _get_erp_g(data_vars, row_normalise) + return TimeSeriesKMeans( n_init=10, - tol=1e-06, + init="random", + distance="erp", + distance_params={"g": g}, random_state=random_state, - n_jobs=n_jobs, + averaging_method="ba", + average_params={"distance": "erp", "g": g, "method": "subgradient"}, **kwargs, ) - elif c == "kasba": - from aeon.clustering import KASBA - - return KASBA( + elif c == "kmeans-ssg-ba-edr": + return TimeSeriesKMeans( + n_init=10, + init="random", + distance="edr", + distance_params={"epsilon": None}, random_state=random_state, + averaging_method="ba", + average_params={ + "distance": "edr", + "epsilon": None, + "method": "subgradient", + }, **kwargs, ) - - # the remaining names end with the distance to use i.e. "kmeans-msm", the - # clusterer class names use dtw - if "-" in c: - name, distance = c.rsplit("-", 1) - else: - name, distance = c, "dtw" - distance_params = _get_distance_default_params(distance, data_vars, row_normalise) - - if name == "kmeans" or name == "timeserieskmeans": + elif c == "kmeans-ssg-ba-twe": return TimeSeriesKMeans( n_init=10, init="random", - distance=distance, - distance_params=distance_params, + distance="twe", + distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, - averaging_method="mean", + averaging_method="ba", + average_params={ + "distance": "twe", + "nu": 0.001, + "lmbda": 1.0, + "method": "subgradient", + }, **kwargs, ) - elif name == "kmeans-ba": + elif c == "kmeans-ssg-ba-msm": return TimeSeriesKMeans( n_init=10, init="random", - distance=distance, - distance_params=distance_params, + distance="msm", + distance_params={"c": 1.0, "independent": True}, random_state=random_state, averaging_method="ba", - average_params={"distance": distance, **distance_params}, + average_params={ + "distance": "msm", + "c": 1.0, + "independent": True, + "method": "subgradient", + }, **kwargs, ) - elif name == "kmeans-ssg-ba": + elif c == "kmeans-ssg-ba-adtw": return TimeSeriesKMeans( n_init=10, init="random", - distance=distance, - distance_params=distance_params, + distance="adtw", + distance_params={"warp_penalty": 1.0}, random_state=random_state, averaging_method="ba", - # Sets to use subgradient BA average_params={ - "distance": distance, - **distance_params, + "distance": "adtw", + "warp_penalty": 1.0, "method": "subgradient", }, **kwargs, ) - elif name == "kmedoids" or name == "timeserieskmedoids": - return TimeSeriesKMedoids( + elif c == "kmeans-ssg-ba-shape_dtw": + return TimeSeriesKMeans( n_init=10, init="random", - distance=distance, - distance_params=distance_params, + distance="shape_dtw", + distance_params={"descriptor": "identity", "reach": 30}, random_state=random_state, - method="alternate", + averaging_method="ba", + average_params={ + "distance": "shape_dtw", + "descriptor": "identity", + "reach": 30, + "method": "subgradient", + }, **kwargs, ) - elif name == "pam": - return TimeSeriesKMedoids( - n_init=10, + elif c == "som-dtw" or c == "elasticsom": + return ElasticSOM( + distance="dtw", init="random", - distance=distance, - distance_params=distance_params, + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"window": 0.2}, random_state=random_state, - method="pam", + verbose=False, **kwargs, ) - elif name == "clarans" or name == "timeseriesclarans": - return TimeSeriesCLARANS( - n_init=10, + elif c == "som-ddtw": + return ElasticSOM( + distance="ddtw", + init="random", + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"window": 0.2}, + random_state=random_state, + verbose=False, + **kwargs, + ) + elif c == "som-wdtw": + return ElasticSOM( + distance="wdtw", init="random", - distance=distance, - distance_params=distance_params, + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, random_state=random_state, + verbose=False, **kwargs, ) - elif name == "clara" or name == "timeseriesclara": - return TimeSeriesCLARA( + elif c == "som-wddtw": + return ElasticSOM( + distance="wddtw", + init="random", + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + random_state=random_state, + verbose=False, + **kwargs, + ) + elif c == "som-lcss": + return ElasticSOM( + distance="lcss", + init="random", + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"epsilon": 1.0}, + random_state=random_state, + verbose=False, + **kwargs, + ) + elif c == "som-erp": + g = _get_erp_g(data_vars, row_normalise) + return ElasticSOM( + distance="erp", + init="random", + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"g": g}, + random_state=random_state, + verbose=False, + **kwargs, + ) + elif c == "som-edr": + return ElasticSOM( + distance="edr", + init="random", + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"epsilon": None}, + random_state=random_state, + verbose=False, + **kwargs, + ) + elif c == "som-twe": + return ElasticSOM( + distance="twe", init="random", - distance=distance, - distance_params=distance_params, + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"nu": 0.001, "lmbda": 1.0}, + random_state=random_state, + verbose=False, + **kwargs, + ) + elif c == "som-msm": + return ElasticSOM( + distance="msm", + init="random", + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"c": 1.0, "independent": True}, + random_state=random_state, + verbose=False, + **kwargs, + ) + elif c == "som-adtw": + return ElasticSOM( + distance="adtw", + init="random", + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"warp_penalty": 1.0}, + random_state=random_state, + verbose=False, + **kwargs, + ) + elif c == "som-shape_dtw": + return ElasticSOM( + distance="shape_dtw", + init="random", + sigma=1.0, + learning_rate=0.5, + decay_function="asymptotic_decay", + neighborhood_function="gaussian", + sigma_decay_function="asymptotic_decay", + num_iterations=500, + distance_params={"descriptor": "identity", "reach": 30}, random_state=random_state, + verbose=False, **kwargs, ) - elif name == "som" or name == "elasticsom": + elif c == "som-soft_dtw": return ElasticSOM( - distance=distance, + distance="soft_dtw", init="random", sigma=1.0, learning_rate=0.5, @@ -425,58 +1325,154 @@ def _set_clusterer_distance_based( neighborhood_function="gaussian", sigma_decay_function="asymptotic_decay", num_iterations=500, - distance_params=distance_params, random_state=random_state, verbose=False, **kwargs, ) - elif name == "agglomerative" or name == "timeseriesagglomerative": + elif c == "kspectralcentroid" or c == "ksc": + return KSpectralCentroid( + # Max shift set to n_timepoints when max_shift is None + max_shift=None, + init="random", + tol=1e-06, + random_state=random_state, + **kwargs, + ) + elif c == "timeserieskshape" or c == "kshape": + return KShape( + init="random", + n_init=10, + tol=1e-06, + random_state=random_state, + **kwargs, + ) + elif c == "kasba": + from aeon.clustering import KASBA + + return KASBA( + random_state=random_state, + **kwargs, + ) + elif c == "agglomerative-euclidean": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="euclidean", + **kwargs, + ) + elif c == "agglomerative-squared": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="squared", + **kwargs, + ) + elif c == "agglomerative-dtw" or c == "timeseriesagglomerative": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="dtw", + distance_params={"window": 0.2}, + **kwargs, + ) + elif c == "agglomerative-ddtw": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="ddtw", + distance_params={"window": 0.2}, + **kwargs, + ) + elif c == "agglomerative-wdtw": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="wdtw", + **kwargs, + ) + elif c == "agglomerative-wddtw": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="wddtw", + **kwargs, + ) + elif c == "agglomerative-lcss": from aeon.clustering import TimeSeriesAgglomerative return TimeSeriesAgglomerative( - distance=distance, - distance_params=distance_params, + distance="lcss", + distance_params={"epsilon": 1.0}, + **kwargs, + ) + elif c == "agglomerative-erp": + from aeon.clustering import TimeSeriesAgglomerative + + g = _get_erp_g(data_vars, row_normalise) + return TimeSeriesAgglomerative( + distance="erp", + distance_params={"g": g}, + **kwargs, + ) + elif c == "agglomerative-edr": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="edr", + distance_params={"epsilon": None}, + **kwargs, + ) + elif c == "agglomerative-twe": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="twe", + distance_params={"nu": 0.001, "lmbda": 1.0}, + **kwargs, + ) + elif c == "agglomerative-msm": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="msm", + distance_params={"c": 1.0, "independent": True}, + **kwargs, + ) + elif c == "agglomerative-adtw": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="adtw", + distance_params={"warp_penalty": 1.0}, + **kwargs, + ) + elif c == "agglomerative-shape_dtw": + from aeon.clustering import TimeSeriesAgglomerative + + return TimeSeriesAgglomerative( + distance="shape_dtw", + distance_params={"descriptor": "identity", "reach": 30}, **kwargs, ) else: raise ValueError(f"UNKNOWN CLUSTERER: {c} in get_clusterer_by_name") -def _get_distance_default_params( - dist_name: str, data_vars: list, row_normalise: bool -) -> dict: - if dist_name == "dtw" or dist_name == "ddtw": - return {"window": 0.2} - if dist_name == "lcss": - return {"epsilon": 1.0} - if dist_name == "erp": - # load dataset to get std if available - if data_vars is not None: - X_train, _, _, _, _ = load_experiment_data(*data_vars) - - # can't handle unequal length series - if isinstance(X_train, np.ndarray): - if row_normalise: - scaler = Normalizer() - X_train = scaler.fit_transform(X_train) - - return {"g": X_train.std(axis=0).sum()} - elif not isinstance(X_train, list): - raise ValueError("Unknown data type in _get_distance_default_params") - return {"g": 0.05} - if dist_name == "msm": - return {"c": 1.0, "independent": True} - if dist_name == "edr": - return {"epsilon": None} - if dist_name == "twe": - return {"nu": 0.001, "lmbda": 1.0} - if dist_name == "psi_dtw": - return {"r": 0.5} - if dist_name == "adtw": - return {"warp_penalty": 1.0} - if dist_name == "shape_dtw": - return {"descriptor": "identity", "reach": 30} - return {} +def _get_erp_g(data_vars: list, row_normalise: bool) -> float: + # load dataset to get std if available + if data_vars is not None: + X_train, _, _, _, _ = load_experiment_data(*data_vars) + + # can't handle unequal length series + if isinstance(X_train, np.ndarray): + if row_normalise: + scaler = Normalizer() + X_train = scaler.fit_transform(X_train) + + return X_train.std(axis=0).sum() + elif not isinstance(X_train, list): + raise ValueError("Unknown data type in _get_erp_g") + return 0.05 def _set_clusterer_feature_based( From 95bf8a1ba4ee7db1d3c200f5903361d0c65aaf94 Mon Sep 17 00:00:00 2001 From: MatthewMiddlehurst Date: Sun, 18 Oct 2026 18:02:29 +0100 Subject: [PATCH 3/8] Add TimeSeriesKernelKMeans to get_clusterer_by_name Uses the settings of the branch which could not be reached before. --- tsml_eval/experiments/_get_clusterer.py | 10 ++++++++++ tsml_eval/experiments/tests/test_clustering.py | 2 -- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tsml_eval/experiments/_get_clusterer.py b/tsml_eval/experiments/_get_clusterer.py index 9c457268..0069f30a 100644 --- a/tsml_eval/experiments/_get_clusterer.py +++ b/tsml_eval/experiments/_get_clusterer.py @@ -9,6 +9,7 @@ KSpectralCentroid, TimeSeriesCLARA, TimeSeriesCLARANS, + TimeSeriesKernelKMeans, TimeSeriesKMeans, TimeSeriesKMedoids, ) @@ -127,6 +128,7 @@ "som-soft_dtw", ["kspectralcentroid", "ksc"], ["timeserieskshape", "kshape"], + "timeserieskernelkmeans", "kasba", "agglomerative-euclidean", "agglomerative-squared", @@ -1346,6 +1348,14 @@ def _set_clusterer_distance_based( random_state=random_state, **kwargs, ) + elif c == "timeserieskernelkmeans": + return TimeSeriesKernelKMeans( + n_init=10, + tol=1e-06, + random_state=random_state, + n_jobs=n_jobs, + **kwargs, + ) elif c == "kasba": from aeon.clustering import KASBA diff --git a/tsml_eval/experiments/tests/test_clustering.py b/tsml_eval/experiments/tests/test_clustering.py index 818c3c9b..ac699be2 100644 --- a/tsml_eval/experiments/tests/test_clustering.py +++ b/tsml_eval/experiments/tests/test_clustering.py @@ -231,8 +231,6 @@ def test_aeon_clusterers_available(): # composable/wrapper "ClustererPipeline", "SklearnClustererWrapper", - # just missing - "TimeSeriesKernelKMeans", ] est = [e for e, _ in all_estimators(type_filter="clusterer")] From 1de4b472a07e25a38a631d4004aafe79a3ff9b79 Mon Sep 17 00:00:00 2001 From: MatthewMiddlehurst Date: Sun, 18 Oct 2026 18:10:01 +0100 Subject: [PATCH 4/8] Import clusterers in each branch of get_clusterer_by_name --- tsml_eval/experiments/_get_clusterer.py | 224 ++++++++++++++++++++++-- 1 file changed, 213 insertions(+), 11 deletions(-) diff --git a/tsml_eval/experiments/_get_clusterer.py b/tsml_eval/experiments/_get_clusterer.py index 0069f30a..5121f396 100644 --- a/tsml_eval/experiments/_get_clusterer.py +++ b/tsml_eval/experiments/_get_clusterer.py @@ -3,18 +3,7 @@ __maintainer__ = ["TonyBagnall", "MatthewMiddlehurst"] import numpy as np -from aeon.clustering import ( - ElasticSOM, - KShape, - KSpectralCentroid, - TimeSeriesCLARA, - TimeSeriesCLARANS, - TimeSeriesKernelKMeans, - TimeSeriesKMeans, - TimeSeriesKMedoids, -) from aeon.transformations.collection import Normalizer -from sklearn.cluster import KMeans from tsml_eval.utils.datasets import load_experiment_data from tsml_eval.utils.functions import str_in_nested_list @@ -242,6 +231,7 @@ def _set_clusterer_deep_learning( c, random_state, n_jobs, fit_contract, checkpoint, kwargs ): if c == "aefcnclusterer" or c == "aefcn": + from aeon.clustering import TimeSeriesKMeans from aeon.clustering.deep_learning import AEFCNClusterer return AEFCNClusterer( @@ -250,6 +240,7 @@ def _set_clusterer_deep_learning( **kwargs, ) elif c == "aeresnetclusterer" or c == "aeresnet": + from aeon.clustering import TimeSeriesKMeans from aeon.clustering.deep_learning import AEResNetClusterer return AEResNetClusterer( @@ -258,6 +249,7 @@ def _set_clusterer_deep_learning( **kwargs, ) elif c == "aeattentionbigruclusterer" or c == "aeattentionbigru": + from aeon.clustering import TimeSeriesKMeans from aeon.clustering.deep_learning import AEAttentionBiGRUClusterer return AEAttentionBiGRUClusterer( @@ -266,6 +258,7 @@ def _set_clusterer_deep_learning( **kwargs, ) elif c == "aebigruclusterer" or c == "aebigru": + from aeon.clustering import TimeSeriesKMeans from aeon.clustering.deep_learning import AEBiGRUClusterer return AEBiGRUClusterer( @@ -274,6 +267,7 @@ def _set_clusterer_deep_learning( **kwargs, ) elif c == "aedcnnclusterer" or c == "aedcnn": + from aeon.clustering import TimeSeriesKMeans from aeon.clustering.deep_learning import AEDCNNClusterer return AEDCNNClusterer( @@ -282,6 +276,7 @@ def _set_clusterer_deep_learning( **kwargs, ) elif c == "aedrnnclusterer" or c == "aedrnn": + from aeon.clustering import TimeSeriesKMeans from aeon.clustering.deep_learning import AEDRNNClusterer return AEDRNNClusterer( @@ -302,6 +297,8 @@ def _set_clusterer_distance_based( kwargs, ): if c == "kmeans-euclidean": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -311,6 +308,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-squared": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -320,6 +319,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-dtw" or c == "timeserieskmeans": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -330,6 +331,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ddtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -340,6 +343,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-wdtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -349,6 +354,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-wddtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -358,6 +365,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-lcss": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -368,6 +377,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-erp": + from aeon.clustering import TimeSeriesKMeans + g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMeans( n_init=10, @@ -379,6 +390,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-edr": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -389,6 +402,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-twe": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -399,6 +414,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-msm": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -409,6 +426,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-adtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -419,6 +438,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-shape_dtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -429,6 +450,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-euclidean": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -438,6 +461,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-squared": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -447,6 +472,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-dtw" or c == "timeserieskmedoids": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -457,6 +484,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-ddtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -467,6 +496,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-wdtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -476,6 +507,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-wddtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -485,6 +518,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-lcss": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -495,6 +530,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-erp": + from aeon.clustering import TimeSeriesKMedoids + g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMedoids( n_init=10, @@ -506,6 +543,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-edr": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -516,6 +555,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-twe": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -526,6 +567,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-msm": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -536,6 +579,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-adtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -546,6 +591,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmedoids-shape_dtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -556,6 +603,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-euclidean": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -564,6 +613,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-squared": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -572,6 +623,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-dtw" or c == "timeseriesclarans": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -581,6 +634,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-ddtw": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -590,6 +645,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-wdtw": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -598,6 +655,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-wddtw": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -606,6 +665,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-lcss": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -615,6 +676,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-erp": + from aeon.clustering import TimeSeriesCLARANS + g = _get_erp_g(data_vars, row_normalise) return TimeSeriesCLARANS( n_init=10, @@ -625,6 +688,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-edr": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -634,6 +699,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-twe": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -643,6 +710,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-msm": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -652,6 +721,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-adtw": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -661,6 +732,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clarans-shape_dtw": + from aeon.clustering import TimeSeriesCLARANS + return TimeSeriesCLARANS( n_init=10, init="random", @@ -670,6 +743,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-euclidean": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="euclidean", @@ -677,6 +752,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-squared": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="squared", @@ -684,6 +761,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-dtw" or c == "timeseriesclara": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="dtw", @@ -692,6 +771,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-ddtw": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="ddtw", @@ -700,6 +781,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-wdtw": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="wdtw", @@ -707,6 +790,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-wddtw": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="wddtw", @@ -714,6 +799,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-lcss": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="lcss", @@ -722,6 +809,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-erp": + from aeon.clustering import TimeSeriesCLARA + g = _get_erp_g(data_vars, row_normalise) return TimeSeriesCLARA( init="random", @@ -731,6 +820,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-edr": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="edr", @@ -739,6 +830,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-twe": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="twe", @@ -747,6 +840,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-msm": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="msm", @@ -755,6 +850,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-adtw": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="adtw", @@ -763,6 +860,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "clara-shape_dtw": + from aeon.clustering import TimeSeriesCLARA + return TimeSeriesCLARA( init="random", distance="shape_dtw", @@ -771,6 +870,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-euclidean": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -780,6 +881,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-squared": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -789,6 +892,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-dtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -799,6 +904,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-ddtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -809,6 +916,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-wdtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -818,6 +927,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-wddtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -827,6 +938,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-lcss": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -837,6 +950,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-erp": + from aeon.clustering import TimeSeriesKMedoids + g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMedoids( n_init=10, @@ -848,6 +963,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-edr": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -858,6 +975,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-twe": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -868,6 +987,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-msm": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -878,6 +999,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-adtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -888,6 +1011,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "pam-shape_dtw": + from aeon.clustering import TimeSeriesKMedoids + return TimeSeriesKMedoids( n_init=10, init="random", @@ -898,6 +1023,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-dtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -909,6 +1036,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-ddtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -920,6 +1049,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-wdtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -930,6 +1061,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-wddtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -940,6 +1073,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-lcss": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -951,6 +1086,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-erp": + from aeon.clustering import TimeSeriesKMeans + g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMeans( n_init=10, @@ -963,6 +1100,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-edr": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -974,6 +1113,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-twe": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -985,6 +1126,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-msm": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -996,6 +1139,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-adtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1007,6 +1152,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ba-shape_dtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1022,6 +1169,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-dtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1033,6 +1182,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-ddtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1044,6 +1195,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-wdtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1054,6 +1207,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-wddtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1064,6 +1219,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-erp": + from aeon.clustering import TimeSeriesKMeans + g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMeans( n_init=10, @@ -1076,6 +1233,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-edr": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1091,6 +1250,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-twe": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1107,6 +1268,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-msm": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1123,6 +1286,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-adtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1138,6 +1303,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kmeans-ssg-ba-shape_dtw": + from aeon.clustering import TimeSeriesKMeans + return TimeSeriesKMeans( n_init=10, init="random", @@ -1154,6 +1321,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-dtw" or c == "elasticsom": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="dtw", init="random", @@ -1169,6 +1338,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-ddtw": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="ddtw", init="random", @@ -1184,6 +1355,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-wdtw": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="wdtw", init="random", @@ -1198,6 +1371,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-wddtw": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="wddtw", init="random", @@ -1212,6 +1387,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-lcss": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="lcss", init="random", @@ -1227,6 +1404,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-erp": + from aeon.clustering import ElasticSOM + g = _get_erp_g(data_vars, row_normalise) return ElasticSOM( distance="erp", @@ -1243,6 +1422,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-edr": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="edr", init="random", @@ -1258,6 +1439,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-twe": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="twe", init="random", @@ -1273,6 +1456,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-msm": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="msm", init="random", @@ -1288,6 +1473,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-adtw": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="adtw", init="random", @@ -1303,6 +1490,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-shape_dtw": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="shape_dtw", init="random", @@ -1318,6 +1507,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "som-soft_dtw": + from aeon.clustering import ElasticSOM + return ElasticSOM( distance="soft_dtw", init="random", @@ -1332,6 +1523,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "kspectralcentroid" or c == "ksc": + from aeon.clustering import KSpectralCentroid + return KSpectralCentroid( # Max shift set to n_timepoints when max_shift is None max_shift=None, @@ -1341,6 +1534,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "timeserieskshape" or c == "kshape": + from aeon.clustering import KShape + return KShape( init="random", n_init=10, @@ -1349,6 +1544,8 @@ def _set_clusterer_distance_based( **kwargs, ) elif c == "timeserieskernelkmeans": + from aeon.clustering import TimeSeriesKernelKMeans + return TimeSeriesKernelKMeans( n_init=10, tol=1e-06, @@ -1490,18 +1687,21 @@ def _set_clusterer_feature_based( ): if c == "catch22" or c == "catch22clusterer": from aeon.clustering.feature_based import Catch22Clusterer + from sklearn.cluster import KMeans return Catch22Clusterer( estimator=KMeans(), random_state=random_state, n_jobs=n_jobs, **kwargs ) elif c == "tsfresh" or c == "tsfreshclusterer": from aeon.clustering.feature_based import TSFreshClusterer + from sklearn.cluster import KMeans return TSFreshClusterer( estimator=KMeans(), random_state=random_state, n_jobs=n_jobs, **kwargs ) elif c == "summary" or c == "summaryclusterer": from aeon.clustering.feature_based import SummaryClusterer + from sklearn.cluster import KMeans return SummaryClusterer( estimator=KMeans(), random_state=random_state, n_jobs=n_jobs, **kwargs @@ -1518,6 +1718,8 @@ def _set_clusterer_other(c, random_state, n_jobs, fit_contract, checkpoint, kwar return DummyClusterer(strategy="random", random_state=random_state, **kwargs) elif c == "dummyclusterer-sklearn": + from sklearn.cluster import KMeans + return KMeans( n_init=1, init="random", From 8606fadb931d3593ba9dc1ef6ae58876c58257fe Mon Sep 17 00:00:00 2001 From: MatthewMiddlehurst Date: Sun, 18 Oct 2026 20:04:59 +0100 Subject: [PATCH 5/8] Only pass non-default settings to the distance based clusterers Remove arguments equal to the aeon defaults, which are the same in aeon 1.0 to 1.6. The averaging distance is added by TimeSeriesKMeans, so average_params only holds the non-default distance settings. KShape keeps tol=1e-06, which only became its default in aeon 1.4. --- tsml_eval/experiments/_get_clusterer.py | 419 ++---------------------- 1 file changed, 23 insertions(+), 396 deletions(-) diff --git a/tsml_eval/experiments/_get_clusterer.py b/tsml_eval/experiments/_get_clusterer.py index 5121f396..7e87101b 100644 --- a/tsml_eval/experiments/_get_clusterer.py +++ b/tsml_eval/experiments/_get_clusterer.py @@ -300,8 +300,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="euclidean", random_state=random_state, averaging_method="mean", @@ -311,8 +309,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="squared", random_state=random_state, averaging_method="mean", @@ -322,8 +318,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="dtw", distance_params={"window": 0.2}, random_state=random_state, @@ -334,8 +328,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, @@ -346,8 +338,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="wdtw", random_state=random_state, averaging_method="mean", @@ -357,8 +347,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="wddtw", random_state=random_state, averaging_method="mean", @@ -368,10 +356,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="lcss", - distance_params={"epsilon": 1.0}, random_state=random_state, averaging_method="mean", **kwargs, @@ -381,8 +366,6 @@ def _set_clusterer_distance_based( g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMeans( - n_init=10, - init="random", distance="erp", distance_params={"g": g}, random_state=random_state, @@ -393,10 +376,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="edr", - distance_params={"epsilon": None}, random_state=random_state, averaging_method="mean", **kwargs, @@ -405,10 +385,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="twe", - distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, averaging_method="mean", **kwargs, @@ -417,10 +394,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="msm", - distance_params={"c": 1.0, "independent": True}, random_state=random_state, averaging_method="mean", **kwargs, @@ -429,10 +403,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="adtw", - distance_params={"warp_penalty": 1.0}, random_state=random_state, averaging_method="mean", **kwargs, @@ -441,10 +412,8 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="shape_dtw", - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, random_state=random_state, averaging_method="mean", **kwargs, @@ -453,8 +422,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="euclidean", random_state=random_state, method="alternate", @@ -464,8 +431,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="squared", random_state=random_state, method="alternate", @@ -475,8 +440,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="dtw", distance_params={"window": 0.2}, random_state=random_state, @@ -487,8 +450,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, @@ -499,8 +460,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="wdtw", random_state=random_state, method="alternate", @@ -510,8 +469,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="wddtw", random_state=random_state, method="alternate", @@ -521,10 +478,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="lcss", - distance_params={"epsilon": 1.0}, random_state=random_state, method="alternate", **kwargs, @@ -534,8 +488,6 @@ def _set_clusterer_distance_based( g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMedoids( - n_init=10, - init="random", distance="erp", distance_params={"g": g}, random_state=random_state, @@ -546,10 +498,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="edr", - distance_params={"epsilon": None}, random_state=random_state, method="alternate", **kwargs, @@ -558,10 +507,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="twe", - distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, method="alternate", **kwargs, @@ -570,10 +516,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="msm", - distance_params={"c": 1.0, "independent": True}, random_state=random_state, method="alternate", **kwargs, @@ -582,10 +525,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="adtw", - distance_params={"warp_penalty": 1.0}, random_state=random_state, method="alternate", **kwargs, @@ -594,10 +534,8 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="shape_dtw", - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, random_state=random_state, method="alternate", **kwargs, @@ -606,8 +544,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="euclidean", random_state=random_state, **kwargs, @@ -616,8 +552,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="squared", random_state=random_state, **kwargs, @@ -626,8 +560,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="dtw", distance_params={"window": 0.2}, random_state=random_state, @@ -637,8 +569,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, @@ -648,8 +578,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="wdtw", random_state=random_state, **kwargs, @@ -658,8 +586,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="wddtw", random_state=random_state, **kwargs, @@ -668,10 +594,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="lcss", - distance_params={"epsilon": 1.0}, random_state=random_state, **kwargs, ) @@ -680,8 +603,6 @@ def _set_clusterer_distance_based( g = _get_erp_g(data_vars, row_normalise) return TimeSeriesCLARANS( - n_init=10, - init="random", distance="erp", distance_params={"g": g}, random_state=random_state, @@ -691,10 +612,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="edr", - distance_params={"epsilon": None}, random_state=random_state, **kwargs, ) @@ -702,10 +620,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="twe", - distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, **kwargs, ) @@ -713,10 +628,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="msm", - distance_params={"c": 1.0, "independent": True}, random_state=random_state, **kwargs, ) @@ -724,10 +636,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="adtw", - distance_params={"warp_penalty": 1.0}, random_state=random_state, **kwargs, ) @@ -735,10 +644,8 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARANS return TimeSeriesCLARANS( - n_init=10, - init="random", distance="shape_dtw", - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, random_state=random_state, **kwargs, ) @@ -746,7 +653,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="euclidean", random_state=random_state, **kwargs, @@ -755,7 +661,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="squared", random_state=random_state, **kwargs, @@ -764,7 +669,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="dtw", distance_params={"window": 0.2}, random_state=random_state, @@ -774,7 +678,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, @@ -784,7 +687,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="wdtw", random_state=random_state, **kwargs, @@ -793,7 +695,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="wddtw", random_state=random_state, **kwargs, @@ -802,9 +703,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="lcss", - distance_params={"epsilon": 1.0}, random_state=random_state, **kwargs, ) @@ -813,7 +712,6 @@ def _set_clusterer_distance_based( g = _get_erp_g(data_vars, row_normalise) return TimeSeriesCLARA( - init="random", distance="erp", distance_params={"g": g}, random_state=random_state, @@ -823,9 +721,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="edr", - distance_params={"epsilon": None}, random_state=random_state, **kwargs, ) @@ -833,9 +729,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="twe", - distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, **kwargs, ) @@ -843,9 +737,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="msm", - distance_params={"c": 1.0, "independent": True}, random_state=random_state, **kwargs, ) @@ -853,9 +745,7 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="adtw", - distance_params={"warp_penalty": 1.0}, random_state=random_state, **kwargs, ) @@ -863,9 +753,8 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesCLARA return TimeSeriesCLARA( - init="random", distance="shape_dtw", - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, random_state=random_state, **kwargs, ) @@ -873,80 +762,58 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="euclidean", random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-squared": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="squared", random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-dtw": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="dtw", distance_params={"window": 0.2}, random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-ddtw": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-wdtw": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="wdtw", random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-wddtw": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="wddtw", random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-lcss": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="lcss", - distance_params={"epsilon": 1.0}, random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-erp": @@ -954,135 +821,94 @@ def _set_clusterer_distance_based( g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMedoids( - n_init=10, - init="random", distance="erp", distance_params={"g": g}, random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-edr": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="edr", - distance_params={"epsilon": None}, random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-twe": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="twe", - distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-msm": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="msm", - distance_params={"c": 1.0, "independent": True}, random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-adtw": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="adtw", - distance_params={"warp_penalty": 1.0}, random_state=random_state, - method="pam", **kwargs, ) elif c == "pam-shape_dtw": from aeon.clustering import TimeSeriesKMedoids return TimeSeriesKMedoids( - n_init=10, - init="random", distance="shape_dtw", - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, random_state=random_state, - method="pam", **kwargs, ) elif c == "kmeans-ba-dtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="dtw", distance_params={"window": 0.2}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "dtw", "window": 0.2}, + average_params={"window": 0.2}, **kwargs, ) elif c == "kmeans-ba-ddtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "ddtw", "window": 0.2}, + average_params={"window": 0.2}, **kwargs, ) elif c == "kmeans-ba-wdtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="wdtw", random_state=random_state, - averaging_method="ba", - average_params={"distance": "wdtw"}, **kwargs, ) elif c == "kmeans-ba-wddtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="wddtw", random_state=random_state, - averaging_method="ba", - average_params={"distance": "wddtw"}, **kwargs, ) elif c == "kmeans-ba-lcss": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="lcss", - distance_params={"epsilon": 1.0}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "lcss", "epsilon": 1.0}, **kwargs, ) elif c == "kmeans-ba-erp": @@ -1090,132 +916,90 @@ def _set_clusterer_distance_based( g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMeans( - n_init=10, - init="random", distance="erp", distance_params={"g": g}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "erp", "g": g}, + average_params={"g": g}, **kwargs, ) elif c == "kmeans-ba-edr": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="edr", - distance_params={"epsilon": None}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "edr", "epsilon": None}, **kwargs, ) elif c == "kmeans-ba-twe": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="twe", - distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "twe", "nu": 0.001, "lmbda": 1.0}, **kwargs, ) elif c == "kmeans-ba-msm": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="msm", - distance_params={"c": 1.0, "independent": True}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "msm", "c": 1.0, "independent": True}, **kwargs, ) elif c == "kmeans-ba-adtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="adtw", - distance_params={"warp_penalty": 1.0}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "adtw", "warp_penalty": 1.0}, **kwargs, ) elif c == "kmeans-ba-shape_dtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="shape_dtw", - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, random_state=random_state, - averaging_method="ba", - average_params={ - "distance": "shape_dtw", - "descriptor": "identity", - "reach": 30, - }, + average_params={"reach": 30}, **kwargs, ) elif c == "kmeans-ssg-ba-dtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="dtw", distance_params={"window": 0.2}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "dtw", "window": 0.2, "method": "subgradient"}, + average_params={"window": 0.2, "method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-ddtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "ddtw", "window": 0.2, "method": "subgradient"}, + average_params={"window": 0.2, "method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-wdtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="wdtw", random_state=random_state, - averaging_method="ba", - average_params={"distance": "wdtw", "method": "subgradient"}, + average_params={"method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-wddtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="wddtw", random_state=random_state, - averaging_method="ba", - average_params={"distance": "wddtw", "method": "subgradient"}, + average_params={"method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-erp": @@ -1223,101 +1007,56 @@ def _set_clusterer_distance_based( g = _get_erp_g(data_vars, row_normalise) return TimeSeriesKMeans( - n_init=10, - init="random", distance="erp", distance_params={"g": g}, random_state=random_state, - averaging_method="ba", - average_params={"distance": "erp", "g": g, "method": "subgradient"}, + average_params={"g": g, "method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-edr": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="edr", - distance_params={"epsilon": None}, random_state=random_state, - averaging_method="ba", - average_params={ - "distance": "edr", - "epsilon": None, - "method": "subgradient", - }, + average_params={"method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-twe": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="twe", - distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, - averaging_method="ba", - average_params={ - "distance": "twe", - "nu": 0.001, - "lmbda": 1.0, - "method": "subgradient", - }, + average_params={"method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-msm": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="msm", - distance_params={"c": 1.0, "independent": True}, random_state=random_state, - averaging_method="ba", - average_params={ - "distance": "msm", - "c": 1.0, - "independent": True, - "method": "subgradient", - }, + average_params={"method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-adtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="adtw", - distance_params={"warp_penalty": 1.0}, random_state=random_state, - averaging_method="ba", - average_params={ - "distance": "adtw", - "warp_penalty": 1.0, - "method": "subgradient", - }, + average_params={"method": "subgradient"}, **kwargs, ) elif c == "kmeans-ssg-ba-shape_dtw": from aeon.clustering import TimeSeriesKMeans return TimeSeriesKMeans( - n_init=10, - init="random", distance="shape_dtw", - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, random_state=random_state, - averaging_method="ba", - average_params={ - "distance": "shape_dtw", - "descriptor": "identity", - "reach": 30, - "method": "subgradient", - }, + average_params={"reach": 30, "method": "subgradient"}, **kwargs, ) elif c == "som-dtw" or c == "elasticsom": @@ -1325,16 +1064,8 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="dtw", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, distance_params={"window": 0.2}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-ddtw": @@ -1342,16 +1073,8 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="ddtw", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, distance_params={"window": 0.2}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-wdtw": @@ -1359,15 +1082,7 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="wdtw", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-wddtw": @@ -1375,15 +1090,7 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="wddtw", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-lcss": @@ -1391,16 +1098,7 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="lcss", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, - distance_params={"epsilon": 1.0}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-erp": @@ -1409,16 +1107,8 @@ def _set_clusterer_distance_based( g = _get_erp_g(data_vars, row_normalise) return ElasticSOM( distance="erp", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, distance_params={"g": g}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-edr": @@ -1426,16 +1116,7 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="edr", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, - distance_params={"epsilon": None}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-twe": @@ -1443,16 +1124,7 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="twe", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, - distance_params={"nu": 0.001, "lmbda": 1.0}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-msm": @@ -1460,16 +1132,7 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="msm", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, - distance_params={"c": 1.0, "independent": True}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-adtw": @@ -1477,16 +1140,7 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="adtw", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, - distance_params={"warp_penalty": 1.0}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-shape_dtw": @@ -1494,16 +1148,8 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="shape_dtw", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, random_state=random_state, - verbose=False, **kwargs, ) elif c == "som-soft_dtw": @@ -1511,25 +1157,13 @@ def _set_clusterer_distance_based( return ElasticSOM( distance="soft_dtw", - init="random", - sigma=1.0, - learning_rate=0.5, - decay_function="asymptotic_decay", - neighborhood_function="gaussian", - sigma_decay_function="asymptotic_decay", - num_iterations=500, random_state=random_state, - verbose=False, **kwargs, ) elif c == "kspectralcentroid" or c == "ksc": from aeon.clustering import KSpectralCentroid return KSpectralCentroid( - # Max shift set to n_timepoints when max_shift is None - max_shift=None, - init="random", - tol=1e-06, random_state=random_state, **kwargs, ) @@ -1537,7 +1171,6 @@ def _set_clusterer_distance_based( from aeon.clustering import KShape return KShape( - init="random", n_init=10, tol=1e-06, random_state=random_state, @@ -1547,7 +1180,6 @@ def _set_clusterer_distance_based( from aeon.clustering import TimeSeriesKernelKMeans return TimeSeriesKernelKMeans( - n_init=10, tol=1e-06, random_state=random_state, n_jobs=n_jobs, @@ -1609,7 +1241,6 @@ def _set_clusterer_distance_based( return TimeSeriesAgglomerative( distance="lcss", - distance_params={"epsilon": 1.0}, **kwargs, ) elif c == "agglomerative-erp": @@ -1626,7 +1257,6 @@ def _set_clusterer_distance_based( return TimeSeriesAgglomerative( distance="edr", - distance_params={"epsilon": None}, **kwargs, ) elif c == "agglomerative-twe": @@ -1634,7 +1264,6 @@ def _set_clusterer_distance_based( return TimeSeriesAgglomerative( distance="twe", - distance_params={"nu": 0.001, "lmbda": 1.0}, **kwargs, ) elif c == "agglomerative-msm": @@ -1642,7 +1271,6 @@ def _set_clusterer_distance_based( return TimeSeriesAgglomerative( distance="msm", - distance_params={"c": 1.0, "independent": True}, **kwargs, ) elif c == "agglomerative-adtw": @@ -1650,7 +1278,6 @@ def _set_clusterer_distance_based( return TimeSeriesAgglomerative( distance="adtw", - distance_params={"warp_penalty": 1.0}, **kwargs, ) elif c == "agglomerative-shape_dtw": @@ -1658,7 +1285,7 @@ def _set_clusterer_distance_based( return TimeSeriesAgglomerative( distance="shape_dtw", - distance_params={"descriptor": "identity", "reach": 30}, + distance_params={"reach": 30}, **kwargs, ) else: From e027a4578af300ae6e18cabef87046b92eee0957 Mon Sep 17 00:00:00 2001 From: MatthewMiddlehurst Date: Sun, 18 Oct 2026 21:51:29 +0100 Subject: [PATCH 6/8] Remove clusterers which cannot fit with barycentre averaging aeon barycentre averaging does not support lcss, and erp support was removed in aeon 1.3.0, so kmeans-ba-lcss, kmeans-ba-erp and kmeans-ssg-ba-erp always raised in fit. --- tsml_eval/experiments/_get_clusterer.py | 33 ------------------------- 1 file changed, 33 deletions(-) diff --git a/tsml_eval/experiments/_get_clusterer.py b/tsml_eval/experiments/_get_clusterer.py index 7e87101b..8bef95e9 100644 --- a/tsml_eval/experiments/_get_clusterer.py +++ b/tsml_eval/experiments/_get_clusterer.py @@ -86,8 +86,6 @@ "kmeans-ba-ddtw", "kmeans-ba-wdtw", "kmeans-ba-wddtw", - "kmeans-ba-lcss", - "kmeans-ba-erp", "kmeans-ba-edr", "kmeans-ba-twe", "kmeans-ba-msm", @@ -97,7 +95,6 @@ "kmeans-ssg-ba-ddtw", "kmeans-ssg-ba-wdtw", "kmeans-ssg-ba-wddtw", - "kmeans-ssg-ba-erp", "kmeans-ssg-ba-edr", "kmeans-ssg-ba-twe", "kmeans-ssg-ba-msm", @@ -903,25 +900,6 @@ def _set_clusterer_distance_based( random_state=random_state, **kwargs, ) - elif c == "kmeans-ba-lcss": - from aeon.clustering import TimeSeriesKMeans - - return TimeSeriesKMeans( - distance="lcss", - random_state=random_state, - **kwargs, - ) - elif c == "kmeans-ba-erp": - from aeon.clustering import TimeSeriesKMeans - - g = _get_erp_g(data_vars, row_normalise) - return TimeSeriesKMeans( - distance="erp", - distance_params={"g": g}, - random_state=random_state, - average_params={"g": g}, - **kwargs, - ) elif c == "kmeans-ba-edr": from aeon.clustering import TimeSeriesKMeans @@ -1002,17 +980,6 @@ def _set_clusterer_distance_based( average_params={"method": "subgradient"}, **kwargs, ) - elif c == "kmeans-ssg-ba-erp": - from aeon.clustering import TimeSeriesKMeans - - g = _get_erp_g(data_vars, row_normalise) - return TimeSeriesKMeans( - distance="erp", - distance_params={"g": g}, - random_state=random_state, - average_params={"g": g, "method": "subgradient"}, - **kwargs, - ) elif c == "kmeans-ssg-ba-edr": from aeon.clustering import TimeSeriesKMeans From ff1f6ac9b5f3379c7597f838e56da83f96c7b4a0 Mon Sep 17 00:00:00 2001 From: MatthewMiddlehurst Date: Sun, 18 Oct 2026 22:47:03 +0100 Subject: [PATCH 7/8] Pass n_jobs to clusterers and use the experiment train data for ERP g Pass n_jobs to TimeSeriesKMeans, KSpectralCentroid and KShape. The ERP g was found from the default train split. Resample the data when the experiment does, and include the test data when the train and test splits are combined, so g comes from the data the clusterer is fit on. --- tsml_eval/experiments/_get_clusterer.py | 54 +++++++++++++++++-- .../experiments/clustering_experiments.py | 9 +++- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/tsml_eval/experiments/_get_clusterer.py b/tsml_eval/experiments/_get_clusterer.py index 8bef95e9..031fd98e 100644 --- a/tsml_eval/experiments/_get_clusterer.py +++ b/tsml_eval/experiments/_get_clusterer.py @@ -7,6 +7,7 @@ from tsml_eval.utils.datasets import load_experiment_data from tsml_eval.utils.functions import str_in_nested_list +from tsml_eval.utils.resampling import stratified_resample_data deep_learning_clusterers = [ ["aefcnclusterer", "aefcn"], @@ -180,7 +181,9 @@ def get_clusterer_by_name( Checkpoint to save model data_vars: list, default=None List of arguments to load the dataset using - `tsml_eval.utils.experiments import load_experiment_data`. + `tsml_eval.utils.datasets.load_experiment_data`, used to find the ERP g + parameter from the train data. An optional fifth item is True if the train + and test data are combined. row_normalise: bool, default=False Whether to row normalise the data if it is loaded using data_vars. **kwargs @@ -299,6 +302,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="euclidean", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -308,6 +312,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="squared", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -318,6 +323,7 @@ def _set_clusterer_distance_based( distance="dtw", distance_params={"window": 0.2}, random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -328,6 +334,7 @@ def _set_clusterer_distance_based( distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -337,6 +344,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="wdtw", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -346,6 +354,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="wddtw", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -355,6 +364,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="lcss", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -366,6 +376,7 @@ def _set_clusterer_distance_based( distance="erp", distance_params={"g": g}, random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -375,6 +386,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="edr", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -384,6 +396,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="twe", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -393,6 +406,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="msm", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -402,6 +416,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="adtw", random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -412,6 +427,7 @@ def _set_clusterer_distance_based( distance="shape_dtw", distance_params={"reach": 30}, random_state=random_state, + n_jobs=n_jobs, averaging_method="mean", **kwargs, ) @@ -871,6 +887,7 @@ def _set_clusterer_distance_based( distance="dtw", distance_params={"window": 0.2}, random_state=random_state, + n_jobs=n_jobs, average_params={"window": 0.2}, **kwargs, ) @@ -881,6 +898,7 @@ def _set_clusterer_distance_based( distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, + n_jobs=n_jobs, average_params={"window": 0.2}, **kwargs, ) @@ -890,6 +908,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="wdtw", random_state=random_state, + n_jobs=n_jobs, **kwargs, ) elif c == "kmeans-ba-wddtw": @@ -898,6 +917,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="wddtw", random_state=random_state, + n_jobs=n_jobs, **kwargs, ) elif c == "kmeans-ba-edr": @@ -906,6 +926,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="edr", random_state=random_state, + n_jobs=n_jobs, **kwargs, ) elif c == "kmeans-ba-twe": @@ -914,6 +935,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="twe", random_state=random_state, + n_jobs=n_jobs, **kwargs, ) elif c == "kmeans-ba-msm": @@ -922,6 +944,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="msm", random_state=random_state, + n_jobs=n_jobs, **kwargs, ) elif c == "kmeans-ba-adtw": @@ -930,6 +953,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="adtw", random_state=random_state, + n_jobs=n_jobs, **kwargs, ) elif c == "kmeans-ba-shape_dtw": @@ -939,6 +963,7 @@ def _set_clusterer_distance_based( distance="shape_dtw", distance_params={"reach": 30}, random_state=random_state, + n_jobs=n_jobs, average_params={"reach": 30}, **kwargs, ) @@ -949,6 +974,7 @@ def _set_clusterer_distance_based( distance="dtw", distance_params={"window": 0.2}, random_state=random_state, + n_jobs=n_jobs, average_params={"window": 0.2, "method": "subgradient"}, **kwargs, ) @@ -959,6 +985,7 @@ def _set_clusterer_distance_based( distance="ddtw", distance_params={"window": 0.2}, random_state=random_state, + n_jobs=n_jobs, average_params={"window": 0.2, "method": "subgradient"}, **kwargs, ) @@ -968,6 +995,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="wdtw", random_state=random_state, + n_jobs=n_jobs, average_params={"method": "subgradient"}, **kwargs, ) @@ -977,6 +1005,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="wddtw", random_state=random_state, + n_jobs=n_jobs, average_params={"method": "subgradient"}, **kwargs, ) @@ -986,6 +1015,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="edr", random_state=random_state, + n_jobs=n_jobs, average_params={"method": "subgradient"}, **kwargs, ) @@ -995,6 +1025,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="twe", random_state=random_state, + n_jobs=n_jobs, average_params={"method": "subgradient"}, **kwargs, ) @@ -1004,6 +1035,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="msm", random_state=random_state, + n_jobs=n_jobs, average_params={"method": "subgradient"}, **kwargs, ) @@ -1013,6 +1045,7 @@ def _set_clusterer_distance_based( return TimeSeriesKMeans( distance="adtw", random_state=random_state, + n_jobs=n_jobs, average_params={"method": "subgradient"}, **kwargs, ) @@ -1023,6 +1056,7 @@ def _set_clusterer_distance_based( distance="shape_dtw", distance_params={"reach": 30}, random_state=random_state, + n_jobs=n_jobs, average_params={"reach": 30, "method": "subgradient"}, **kwargs, ) @@ -1132,6 +1166,7 @@ def _set_clusterer_distance_based( return KSpectralCentroid( random_state=random_state, + n_jobs=n_jobs, **kwargs, ) elif c == "timeserieskshape" or c == "kshape": @@ -1141,6 +1176,7 @@ def _set_clusterer_distance_based( n_init=10, tol=1e-06, random_state=random_state, + n_jobs=n_jobs, **kwargs, ) elif c == "timeserieskernelkmeans": @@ -1260,9 +1296,21 @@ def _set_clusterer_distance_based( def _get_erp_g(data_vars: list, row_normalise: bool) -> float: - # load dataset to get std if available + # load the experiment train data to get std if available if data_vars is not None: - X_train, _, _, _, _ = load_experiment_data(*data_vars) + X_train, y_train, X_test, y_test, resample = load_experiment_data( + *data_vars[:4] + ) + if resample: + X_train, y_train, X_test, y_test = stratified_resample_data( + X_train, y_train, X_test, y_test, random_state=data_vars[2] + ) + if len(data_vars) > 4 and data_vars[4]: + X_train = ( + np.concatenate([X_train, X_test], axis=0) + if isinstance(X_train, np.ndarray) + else X_train + X_test + ) # can't handle unequal length series if isinstance(X_train, np.ndarray): diff --git a/tsml_eval/experiments/clustering_experiments.py b/tsml_eval/experiments/clustering_experiments.py index 42911093..e5ca3551 100644 --- a/tsml_eval/experiments/clustering_experiments.py +++ b/tsml_eval/experiments/clustering_experiments.py @@ -92,6 +92,7 @@ def run_experiment(args): args.dataset_name, args.resample_id, args.predefined_resample, + args.combine_test_train_split, ], row_normalise=args.row_normalise, **args.kwargs, @@ -147,7 +148,13 @@ def run_experiment(args): n_jobs=1, fit_contract=fit_contract, checkpoint=checkpoint, - data_vars=[data_path, dataset_name, resample_id, predefined_resample], + data_vars=[ + data_path, + dataset_name, + resample_id, + predefined_resample, + combine_test_train_split, + ], row_normalise=row_normalise, **kwargs, ) From 88f274f737d3115e3846a15d81091d949be3f900 Mon Sep 17 00:00:00 2001 From: MatthewMiddlehurst Date: Mon, 19 Oct 2026 11:44:42 +0100 Subject: [PATCH 8/8] Use the KShape default tol in get_clusterer_by_name --- tsml_eval/experiments/_get_clusterer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tsml_eval/experiments/_get_clusterer.py b/tsml_eval/experiments/_get_clusterer.py index 031fd98e..de1ba086 100644 --- a/tsml_eval/experiments/_get_clusterer.py +++ b/tsml_eval/experiments/_get_clusterer.py @@ -1174,7 +1174,6 @@ def _set_clusterer_distance_based( return KShape( n_init=10, - tol=1e-06, random_state=random_state, n_jobs=n_jobs, **kwargs,