From 6242a749b0fc3bfd63d2054bb2001464cadc0682 Mon Sep 17 00:00:00 2001 From: chrisholder Date: Mon, 25 Nov 2024 12:20:00 +0000 Subject: [PATCH 1/3] cluster init_algorithm removed across all clusterers --- aeon/clustering/_clara.py | 26 +++++++--- aeon/clustering/_clarans.py | 25 +++++++--- aeon/clustering/_k_medoids.py | 65 +++++++++++++++---------- aeon/clustering/_k_shape.py | 25 ++++++++-- aeon/clustering/tests/test_clara.py | 4 +- aeon/clustering/tests/test_clarans.py | 8 +-- aeon/clustering/tests/test_k_medoids.py | 14 +++--- 7 files changed, 109 insertions(+), 58 deletions(-) diff --git a/aeon/clustering/_clara.py b/aeon/clustering/_clara.py index dcc0e7a912..ce3493f1ff 100644 --- a/aeon/clustering/_clara.py +++ b/aeon/clustering/_clara.py @@ -30,8 +30,8 @@ class TimeSeriesCLARA(BaseClusterer): n_clusters : int, default=8 The number of clusters to form as well as the number of centroids to generate. - init_algorithm : str or np.ndarray, default='random' - Method for initializing cluster centers. Any of the following are valid: + init : str or np.ndarray, default='random' + Method for initialising cluster centers. Any of the following are valid: ['kmedoids++', 'random', 'first']. Random is the default as it is very fast and it was found in [2] to perform about as well as the other methods. @@ -118,7 +118,7 @@ class TimeSeriesCLARA(BaseClusterer): def __init__( self, n_clusters: int = 8, - init_algorithm: Union[str, np.ndarray] = "random", + init: Union[str, np.ndarray] = "random", distance: Union[str, Callable] = "msm", n_samples: Optional[int] = None, n_sampling_iters: int = 10, @@ -128,8 +128,20 @@ def __init__( verbose: bool = False, random_state: Optional[Union[int, RandomState]] = None, distance_params: Optional[dict] = None, + init_algorithm: Optional[Union[str, np.ndarray]] = None, ): - self.init_algorithm = init_algorithm + if init_algorithm is not None: + import warnings + + warnings.warn( + "The 'init_algorithm' parameter is deprecated and will be " + "removed in version 1.1. Use 'init' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.init = init_algorithm + else: + self.init = init self.distance = distance self.n_init = n_init self.max_iter = max_iter @@ -140,6 +152,8 @@ def __init__( self.n_samples = n_samples self.n_sampling_iters = n_sampling_iters self.n_clusters = n_clusters + # Kept for testing will be deprecated + self.init_algorithm = init_algorithm self.cluster_centers_ = None self.labels_ = None @@ -175,7 +189,7 @@ def _fit(self, X: np.ndarray, y=None): ) pam = TimeSeriesKMedoids( n_clusters=self.n_clusters, - init_algorithm=self.init_algorithm, + init=self.init, distance=self.distance, n_init=self.n_init, max_iter=self.max_iter, @@ -228,7 +242,7 @@ def _get_test_params(cls, parameter_set="default"): """ return { "n_clusters": 2, - "init_algorithm": "random", + "init": "random", "distance": "euclidean", "n_init": 1, "max_iter": 1, diff --git a/aeon/clustering/_clarans.py b/aeon/clustering/_clarans.py index f1c9eff87b..ffe58ec8e0 100644 --- a/aeon/clustering/_clarans.py +++ b/aeon/clustering/_clarans.py @@ -31,7 +31,7 @@ class TimeSeriesCLARANS(TimeSeriesKMedoids): n_clusters : int, default=8 The number of clusters to form as well as the number of centroids to generate. - init_algorithm : str or np.ndarray, default='random' + init : str or np.ndarray, default='random' Method for initializing cluster centers. Any of the following are valid: ['kmedoids++', 'random', 'first']. Random is the default as it is very fast and it was found in [2] to @@ -104,19 +104,30 @@ class TimeSeriesCLARANS(TimeSeriesKMedoids): def __init__( self, n_clusters: int = 8, - init_algorithm: Union[str, np.ndarray] = "random", + init: Union[str, np.ndarray] = "random", distance: Union[str, Callable] = "msm", max_neighbours: Optional[int] = None, n_init: int = 10, verbose: bool = False, random_state: Optional[Union[int, RandomState]] = None, distance_params: Optional[dict] = None, + init_algorithm: Optional[Union[str, np.ndarray]] = None, ): + if init_algorithm is not None: + import warnings + + warnings.warn( + "The 'init_algorithm' parameter is deprecated and will be " + "removed in version 1.1. Use 'init' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.max_neighbours = max_neighbours super().__init__( n_clusters=n_clusters, - init_algorithm=init_algorithm, + init=init, distance=distance, n_init=n_init, verbose=verbose, @@ -127,10 +138,10 @@ def __init__( def _fit_one_init(self, X: np.ndarray, max_neighbours: int): j = 0 X_indexes = np.arange(X.shape[0], dtype=int) - if isinstance(self._init_algorithm, Callable): - best_medoids = self._init_algorithm(X) + if isinstance(self._init, Callable): + best_medoids = self._init(X) else: - best_medoids = self._init_algorithm + best_medoids = self._init best_non_medoids = np.setdiff1d(X_indexes, best_medoids) best_cost = ( self._compute_pairwise(X, best_non_medoids, best_medoids).min(axis=1).sum() @@ -203,7 +214,7 @@ def _get_test_params(cls, parameter_set="default"): """ return { "n_clusters": 2, - "init_algorithm": "random", + "init": "random", "distance": "euclidean", "max_neighbours": None, "n_init": 1, diff --git a/aeon/clustering/_k_medoids.py b/aeon/clustering/_k_medoids.py index ea8e860afc..04af3bd712 100644 --- a/aeon/clustering/_k_medoids.py +++ b/aeon/clustering/_k_medoids.py @@ -44,7 +44,7 @@ class TimeSeriesKMedoids(BaseClusterer): ---------- n_clusters : int, default=8 The number of clusters to form as well as the number of centroids to generate. - init_algorithm : str or np.ndarray, default='random' + init : str or np.ndarray, default='random' Method for initializing cluster centers. Any of the following are valid: ['kmedoids++', 'random', 'first']. Random is the default as it is very fast and it was found in [2] to @@ -152,7 +152,7 @@ class TimeSeriesKMedoids(BaseClusterer): def __init__( self, n_clusters: int = 8, - init_algorithm: Union[str, np.ndarray] = "random", + init: Union[str, np.ndarray] = "random", distance: Union[str, Callable] = "msm", method: str = "pam", n_init: int = 10, @@ -161,8 +161,20 @@ def __init__( verbose: bool = False, random_state: Optional[Union[int, RandomState]] = None, distance_params: Optional[dict] = None, + init_algorithm: Optional[Union[str, np.ndarray]] = None, ): - self.init_algorithm = init_algorithm + if init_algorithm is not None: + import warnings + + warnings.warn( + "The 'init_algorithm' parameter is deprecated and will be " + "removed in version 1.1. Use 'init' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.init = init_algorithm + else: + self.init = init self.distance = distance self.n_init = n_init self.max_iter = max_iter @@ -172,6 +184,8 @@ def __init__( self.distance_params = distance_params self.method = method self.n_clusters = n_clusters + # Kept for testing will be deprecated + self.init_algorithm = init_algorithm self.cluster_centers_ = None self.labels_ = None @@ -179,7 +193,7 @@ def __init__( self.n_iter_ = 0 self._random_state = None - self._init_algorithm = None + self._init = None self._distance_cache = None self._distance_callable = None self._fit_method = None @@ -267,10 +281,10 @@ def _pam_fit(self, X: np.ndarray): old_inertia = np.inf n_cases = X.shape[0] - if isinstance(self._init_algorithm, Callable): - medoids_idxs = self._init_algorithm(X) + if isinstance(self._init, Callable): + medoids_idxs = self._init(X) else: - medoids_idxs = self._init_algorithm + medoids_idxs = self._init not_medoid_idxs = np.arange(n_cases, dtype=int) distance_matrix = self._compute_pairwise(X, not_medoid_idxs, not_medoid_idxs) distance_closest_medoid, distance_second_closest_medoid = np.sort( @@ -388,9 +402,9 @@ def _compute_optimal_swaps( return None def _alternate_fit(self, X) -> tuple[np.ndarray, np.ndarray, float, int]: - cluster_center_indexes = self._init_algorithm - if isinstance(self._init_algorithm, Callable): - cluster_center_indexes = self._init_algorithm(X) + cluster_center_indexes = self._init + if isinstance(self._init, Callable): + cluster_center_indexes = self._init(X) old_inertia = np.inf old_indexes = None for i in range(self.max_iter): @@ -428,24 +442,21 @@ def _assign_clusters( def _check_params(self, X: np.ndarray) -> None: self._random_state = check_random_state(self.random_state) - if isinstance(self.init_algorithm, str): - if self.init_algorithm == "random": - self._init_algorithm = self._random_center_initializer - elif self.init_algorithm == "kmedoids++": - self._init_algorithm = self._kmedoids_plus_plus_center_initializer - elif self.init_algorithm == "first": - self._init_algorithm = self._first_center_initializer - elif self.init_algorithm == "build": - self._init_algorithm = self._pam_build_center_initializer + if isinstance(self.init, str): + if self.init == "random": + self._init = self._random_center_initializer + elif self.init == "kmedoids++": + self._init = self._kmedoids_plus_plus_center_initializer + elif self.init == "first": + self._init = self._first_center_initializer + elif self.init == "build": + self._init = self._pam_build_center_initializer else: - if ( - isinstance(self.init_algorithm, np.ndarray) - and len(self.init_algorithm) == self.n_clusters - ): - self._init_algorithm = self.init_algorithm + if isinstance(self.init, np.ndarray) and len(self.init) == self.n_clusters: + self._init = self.init else: raise ValueError( - f"The value provided for init_algorithm: {self.init_algorithm} is " + f"The value provided for init: {self.init} is " f"invalid. The following are a list of valid init algorithms " f"strings: random, kmedoids++, first. You can also pass a" f"np.ndarray of size (n_clusters, n_channels, n_timepoints)" @@ -469,7 +480,7 @@ def _check_params(self, X: np.ndarray) -> None: else: raise ValueError(f"method {self.method} is not supported") - if isinstance(self.init_algorithm, str) and self.init_algorithm == "build": + if isinstance(self.init, str) and self.init == "build": if self.n_init != 10 and self.n_init > 1: warnings.warn( "When using build n_init does not need to be greater than 1. " @@ -558,7 +569,7 @@ def _get_test_params(cls, parameter_set="default"): """ return { "n_clusters": 2, - "init_algorithm": "random", + "init": "random", "distance": "euclidean", "n_init": 1, "max_iter": 1, diff --git a/aeon/clustering/_k_shape.py b/aeon/clustering/_k_shape.py index ad94a9f10c..633b941576 100644 --- a/aeon/clustering/_k_shape.py +++ b/aeon/clustering/_k_shape.py @@ -16,7 +16,7 @@ class TimeSeriesKShape(BaseClusterer): n_clusters: int, default=8 The number of clusters to form as well as the number of centroids to generate. - init_algorithm: str or np.ndarray, default='random' + init: str or np.ndarray, default='random' Method for initializing cluster centres. Any of the following are valid: ['random']. Or a np.ndarray of shape (n_clusters, n_channels, n_timepoints) and gives the initial cluster centres. @@ -76,20 +76,35 @@ class TimeSeriesKShape(BaseClusterer): def __init__( self, n_clusters: int = 8, - init_algorithm: Union[str, np.ndarray] = "random", + init: Union[str, np.ndarray] = "random", n_init: int = 10, max_iter: int = 300, tol: float = 1e-4, verbose: bool = False, random_state: Optional[Union[int, RandomState]] = None, + init_algorithm: Optional[Union[str, np.ndarray]] = None, ): - self.init_algorithm = init_algorithm + if init_algorithm is not None: + import warnings + + warnings.warn( + "The 'init_algorithm' parameter is deprecated and will be " + "removed in version 1.1. Use 'init' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.init = init_algorithm + else: + self.init = init + self.n_init = n_init self.max_iter = max_iter self.tol = tol self.verbose = verbose self.random_state = random_state self.n_clusters = n_clusters + # Kept for testing will be deprecated + self.init_algorithm = init_algorithm self.cluster_centers_ = None self.labels_ = None @@ -124,7 +139,7 @@ def _fit(self, X, y=None): random_state=self.random_state, n_init=self.n_init, verbose=self.verbose, - init=self.init_algorithm, + init=self.init, ) _X = X.swapaxes(1, 2) @@ -173,7 +188,7 @@ def _get_test_params(cls, parameter_set="default"): """ return { "n_clusters": 2, - "init_algorithm": "random", + "init": "random", "n_init": 1, "max_iter": 1, "tol": 1e-4, diff --git a/aeon/clustering/tests/test_clara.py b/aeon/clustering/tests/test_clara.py index ebfb3dada5..81d5e8920e 100644 --- a/aeon/clustering/tests/test_clara.py +++ b/aeon/clustering/tests/test_clara.py @@ -23,7 +23,7 @@ def test_clara_uni(): n_samples=10, n_init=2, max_iter=5, - init_algorithm="first", + init="first", distance="euclidean", n_clusters=2, ) @@ -68,7 +68,7 @@ def test_clara_multi(): n_samples=10, n_init=2, max_iter=5, - init_algorithm="first", + init="first", distance="euclidean", n_clusters=2, ) diff --git a/aeon/clustering/tests/test_clarans.py b/aeon/clustering/tests/test_clarans.py index 03e250bdf3..a1da285cf3 100644 --- a/aeon/clustering/tests/test_clarans.py +++ b/aeon/clustering/tests/test_clarans.py @@ -24,7 +24,7 @@ def test_clarans_uni(): clarans = TimeSeriesCLARANS( random_state=1, n_init=2, - init_algorithm="first", + init="first", distance="euclidean", n_clusters=2, ) @@ -67,7 +67,7 @@ def test_clara_multi(): clarans = TimeSeriesCLARANS( random_state=1, n_init=2, - init_algorithm="first", + init="first", distance="euclidean", n_clusters=2, ) @@ -106,7 +106,7 @@ def test_medoids_init(): kmedoids = TimeSeriesCLARANS( random_state=1, n_init=1, - init_algorithm="first", + init="first", distance="euclidean", n_clusters=num_clusters, ) @@ -131,7 +131,7 @@ def test_medoids_init(): kmedoids = TimeSeriesCLARANS( random_state=1, n_init=1, - init_algorithm=custom_init_centres, + init=custom_init_centres, distance="euclidean", n_clusters=num_clusters, ) diff --git a/aeon/clustering/tests/test_k_medoids.py b/aeon/clustering/tests/test_k_medoids.py index 57bd7c1039..0fea3ead19 100644 --- a/aeon/clustering/tests/test_k_medoids.py +++ b/aeon/clustering/tests/test_k_medoids.py @@ -43,7 +43,7 @@ def _pam_uni_medoids(X_train, y_train, X_test, y_test): random_state=1, n_init=2, max_iter=5, - init_algorithm="first", + init="first", distance="euclidean", method="pam", ) @@ -70,7 +70,7 @@ def _alternate_uni_medoids(X_train, y_train, X_test, y_test): n_init=2, max_iter=5, method="alternate", - init_algorithm="first", + init="first", distance="euclidean", ) train_medoids_result = kmedoids.fit_predict(X_train) @@ -95,7 +95,7 @@ def _pam_multi_medoids(X_train, y_train, X_test, y_test): random_state=1, n_init=2, max_iter=5, - init_algorithm="first", + init="first", distance="euclidean", method="pam", ) @@ -121,7 +121,7 @@ def _alternate_multi_medoids(X_train, y_train, X_test, y_test): random_state=1, n_init=2, max_iter=5, - init_algorithm="first", + init="first", method="alternate", distance="euclidean", ) @@ -169,7 +169,7 @@ def test_medoids_init(): random_state=1, n_init=1, max_iter=5, - init_algorithm="first", + init="first", distance="euclidean", n_clusters=num_clusters, ) @@ -194,7 +194,7 @@ def test_medoids_init(): random_state=1, n_init=1, max_iter=5, - init_algorithm=custom_init_centres, + init=custom_init_centres, distance="euclidean", n_clusters=num_clusters, ) @@ -209,7 +209,7 @@ def _get_model_centres(data, distance, method="pam", distance_params=None): method=method, n_init=2, n_clusters=2, - init_algorithm="random", + init="random", distance=distance, distance_params=distance_params, ) From d65276427889df2377e24c31ccbb2305a4b772a5 Mon Sep 17 00:00:00 2001 From: chrisholder Date: Mon, 25 Nov 2024 12:29:50 +0000 Subject: [PATCH 2/3] removed deprecation warnings - just removed it --- aeon/clustering/_clara.py | 16 +--------------- aeon/clustering/_clarans.py | 11 ----------- aeon/clustering/_k_medoids.py | 16 +--------------- aeon/clustering/_k_shape.py | 17 +---------------- .../clustering/partitional_clustering.ipynb | 6 +++--- 5 files changed, 6 insertions(+), 60 deletions(-) diff --git a/aeon/clustering/_clara.py b/aeon/clustering/_clara.py index ce3493f1ff..66da2e9920 100644 --- a/aeon/clustering/_clara.py +++ b/aeon/clustering/_clara.py @@ -128,21 +128,9 @@ def __init__( verbose: bool = False, random_state: Optional[Union[int, RandomState]] = None, distance_params: Optional[dict] = None, - init_algorithm: Optional[Union[str, np.ndarray]] = None, ): - if init_algorithm is not None: - import warnings - - warnings.warn( - "The 'init_algorithm' parameter is deprecated and will be " - "removed in version 1.1. Use 'init' instead.", - DeprecationWarning, - stacklevel=2, - ) - self.init = init_algorithm - else: - self.init = init self.distance = distance + self.init = init self.n_init = n_init self.max_iter = max_iter self.tol = tol @@ -152,8 +140,6 @@ def __init__( self.n_samples = n_samples self.n_sampling_iters = n_sampling_iters self.n_clusters = n_clusters - # Kept for testing will be deprecated - self.init_algorithm = init_algorithm self.cluster_centers_ = None self.labels_ = None diff --git a/aeon/clustering/_clarans.py b/aeon/clustering/_clarans.py index ffe58ec8e0..8cf80f3d51 100644 --- a/aeon/clustering/_clarans.py +++ b/aeon/clustering/_clarans.py @@ -111,18 +111,7 @@ def __init__( verbose: bool = False, random_state: Optional[Union[int, RandomState]] = None, distance_params: Optional[dict] = None, - init_algorithm: Optional[Union[str, np.ndarray]] = None, ): - if init_algorithm is not None: - import warnings - - warnings.warn( - "The 'init_algorithm' parameter is deprecated and will be " - "removed in version 1.1. Use 'init' instead.", - DeprecationWarning, - stacklevel=2, - ) - self.max_neighbours = max_neighbours super().__init__( diff --git a/aeon/clustering/_k_medoids.py b/aeon/clustering/_k_medoids.py index 04af3bd712..745c9da997 100644 --- a/aeon/clustering/_k_medoids.py +++ b/aeon/clustering/_k_medoids.py @@ -161,21 +161,9 @@ def __init__( verbose: bool = False, random_state: Optional[Union[int, RandomState]] = None, distance_params: Optional[dict] = None, - init_algorithm: Optional[Union[str, np.ndarray]] = None, ): - if init_algorithm is not None: - import warnings - - warnings.warn( - "The 'init_algorithm' parameter is deprecated and will be " - "removed in version 1.1. Use 'init' instead.", - DeprecationWarning, - stacklevel=2, - ) - self.init = init_algorithm - else: - self.init = init self.distance = distance + self.init = init self.n_init = n_init self.max_iter = max_iter self.tol = tol @@ -184,8 +172,6 @@ def __init__( self.distance_params = distance_params self.method = method self.n_clusters = n_clusters - # Kept for testing will be deprecated - self.init_algorithm = init_algorithm self.cluster_centers_ = None self.labels_ = None diff --git a/aeon/clustering/_k_shape.py b/aeon/clustering/_k_shape.py index 633b941576..8af172e9b6 100644 --- a/aeon/clustering/_k_shape.py +++ b/aeon/clustering/_k_shape.py @@ -82,29 +82,14 @@ def __init__( tol: float = 1e-4, verbose: bool = False, random_state: Optional[Union[int, RandomState]] = None, - init_algorithm: Optional[Union[str, np.ndarray]] = None, ): - if init_algorithm is not None: - import warnings - - warnings.warn( - "The 'init_algorithm' parameter is deprecated and will be " - "removed in version 1.1. Use 'init' instead.", - DeprecationWarning, - stacklevel=2, - ) - self.init = init_algorithm - else: - self.init = init - self.n_init = n_init + self.init = init self.max_iter = max_iter self.tol = tol self.verbose = verbose self.random_state = random_state self.n_clusters = n_clusters - # Kept for testing will be deprecated - self.init_algorithm = init_algorithm self.cluster_centers_ = None self.labels_ = None diff --git a/examples/clustering/partitional_clustering.ipynb b/examples/clustering/partitional_clustering.ipynb index 817f66bd24..5fd9ac1eec 100644 --- a/examples/clustering/partitional_clustering.ipynb +++ b/examples/clustering/partitional_clustering.ipynb @@ -1374,7 +1374,7 @@ "source": [ "k_medoids = TimeSeriesKMedoids(\n", " n_clusters=2, # Number of desired centers\n", - " init_algorithm=\"random\", # Center initialisation technique\n", + " init=\"random\", # Center initialisation technique\n", " max_iter=10, # Maximum number of iterations for refinement on training set\n", " verbose=False, # Verbose\n", " distance=\"dtw\", # Distance to use\n", @@ -1458,7 +1458,7 @@ "source": [ "k_medoids = TimeSeriesKMedoids(\n", " n_clusters=2, # Number of desired centers\n", - " init_algorithm=\"random\", # Center initialisation technique\n", + " init=\"random\", # Center initialisation technique\n", " max_iter=10, # Maximum number of iterations for refinement on training set\n", " distance=\"msm\", # Distance to use\n", " random_state=1,\n", @@ -1527,7 +1527,7 @@ "source": [ "k_medoids = TimeSeriesKMedoids(\n", " n_clusters=2, # Number of desired centers\n", - " init_algorithm=\"random\", # Center initialisation technique\n", + " init=\"random\", # Center initialisation technique\n", " max_iter=10, # Maximum number of iterations for refinement on training set\n", " distance=\"msm\", # Distance to use\n", " random_state=1,\n", From 65e11c3ff2f7039a464203accf9cb7468e069da7 Mon Sep 17 00:00:00 2001 From: chrisholder Date: Mon, 25 Nov 2024 12:31:29 +0000 Subject: [PATCH 3/3] typo --- aeon/clustering/_clarans.py | 2 +- aeon/clustering/_k_medoids.py | 2 +- aeon/clustering/_k_shape.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aeon/clustering/_clarans.py b/aeon/clustering/_clarans.py index 8cf80f3d51..71ca1a9284 100644 --- a/aeon/clustering/_clarans.py +++ b/aeon/clustering/_clarans.py @@ -32,7 +32,7 @@ class TimeSeriesCLARANS(TimeSeriesKMedoids): The number of clusters to form as well as the number of centroids to generate. init : str or np.ndarray, default='random' - Method for initializing cluster centers. Any of the following are valid: + Method for initialising cluster centers. Any of the following are valid: ['kmedoids++', 'random', 'first']. Random is the default as it is very fast and it was found in [2] to perform about as well as the other methods. diff --git a/aeon/clustering/_k_medoids.py b/aeon/clustering/_k_medoids.py index 745c9da997..a54220cec2 100644 --- a/aeon/clustering/_k_medoids.py +++ b/aeon/clustering/_k_medoids.py @@ -45,7 +45,7 @@ class TimeSeriesKMedoids(BaseClusterer): n_clusters : int, default=8 The number of clusters to form as well as the number of centroids to generate. init : str or np.ndarray, default='random' - Method for initializing cluster centers. Any of the following are valid: + Method for initialising cluster centers. Any of the following are valid: ['kmedoids++', 'random', 'first']. Random is the default as it is very fast and it was found in [2] to perform about as well as the other methods. diff --git a/aeon/clustering/_k_shape.py b/aeon/clustering/_k_shape.py index 8af172e9b6..aa8d8a3b64 100644 --- a/aeon/clustering/_k_shape.py +++ b/aeon/clustering/_k_shape.py @@ -17,7 +17,7 @@ class TimeSeriesKShape(BaseClusterer): The number of clusters to form as well as the number of centroids to generate. init: str or np.ndarray, default='random' - Method for initializing cluster centres. Any of the following are valid: + Method for initialising cluster centres. Any of the following are valid: ['random']. Or a np.ndarray of shape (n_clusters, n_channels, n_timepoints) and gives the initial cluster centres. n_init: int, default=10