From f01b0322817fb8b3e0979bb84569a3c55a0f6ccd Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 17:08:59 +0100 Subject: [PATCH 01/28] base --- .gitignore | 1 + sktime/classification/base.py | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/.gitignore b/.gitignore index 569c3277c5f..73d7ddd9b33 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,4 @@ sktime/contrib/nothing_to_see_here.py sktime/distances/elastic_cython.html *.html sktime/contrib/distance_based/old_time_series_neighbors.py +sktime/contrib/debug.py diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 0d48d814d7b..7a2a3afa48f 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -75,6 +75,11 @@ class BaseClassifier(BaseEstimator): _tags = { "coerce-X-to-numpy": True, "coerce-X-to-pandas": False, + "capability:multivariate": False, + "capability:unequal_length": False, + "capability:missing_values": False, + "capability:train_estimate": False, + "capability:contractable": False, } def __init__(self): @@ -105,6 +110,9 @@ def fit(self, X, y): """ coerce_to_numpy = self.get_tag("coerce-X-to-numpy", False) coerce_to_pandas = self.get_tag("coerce-X-to-pandas", False) + + + enforce_univariate = self.get_tag("coerce-X-to-pandas", False) X, y = check_X_y( X, y, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas ) From 3c14b91d0ccef1f6579578551300d48d1dbbce3d Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 17:59:06 +0100 Subject: [PATCH 02/28] enforce univariate in base class --- sktime/classification/base.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 7a2a3afa48f..328ac4857de 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -108,13 +108,13 @@ def fit(self, X, y): Changes state by creating a fitted model that updates attributes ending in "_" and sets is_fitted flag to True. """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", False) - - - enforce_univariate = self.get_tag("coerce-X-to-pandas", False) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) + coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) + enforce_univariate = self.get_tag("capability:multivariate", + tag_value_default=False) X, y = check_X_y( - X, y, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas + X, y, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, + enforce_univariate=enforce_univariate ) self._fit(X, y) From 498b8ddf89104a612bf2d10eed0f62138b6f6560 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 18:03:42 +0100 Subject: [PATCH 03/28] remove unnecessary classifier tags --- sktime/registry/_tags.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sktime/registry/_tags.py b/sktime/registry/_tags.py index 608a7b8182e..fa7fb61d57b 100644 --- a/sktime/registry/_tags.py +++ b/sktime/registry/_tags.py @@ -89,13 +89,13 @@ ), ( "X-y-must-have-same-index", - ["forecaster", "classifier", "regressor"], + ["forecaster", "regressor"], "bool", "do X/y in fit/update and X/fh in predict have to be same indices?", ), ( "enforce_index_type", - ["forecaster", "classifier", "regressor"], + ["forecaster", "regressor"], "type", "passed to input checks, input conversion index type to enforce", ), From 8b72f4daab0b8711c8c82079c8d73e5e35e7834d Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 18:08:27 +0100 Subject: [PATCH 04/28] predict and predict_proba --- sktime/classification/base.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 328ac4857de..8a51874b1b6 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -138,10 +138,13 @@ def predict(self, X): ------- y : array-like, shape = [n_instances] - predicted class labels """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", False) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) + coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) + enforce_univariate = self.get_tag("capability:multivariate", + tag_value_default=False) X = check_X( - X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas + X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, + enforce_univariate=enforce_univariate ) self.check_is_fitted() @@ -163,10 +166,13 @@ def predict_proba(self, X): ------- y : array-like, shape = [n_instances, n_classes] - predictive pmf """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", False) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) + coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) + enforce_univariate = self.get_tag("capability:multivariate", + tag_value_default=False) X = check_X( - X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas + X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, + enforce_univariate=enforce_univariate ) self.check_is_fitted() return self._predict_proba(X) From b79f65bfbaa4c6c64dc8431ccfe9343a6abf45d0 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 20:01:22 +0100 Subject: [PATCH 05/28] tweaks to classifier base class --- sktime/base/_base.py | 8 +++-- sktime/classification/base.py | 57 +++++++++-------------------------- 2 files changed, 19 insertions(+), 46 deletions(-) diff --git a/sktime/base/_base.py b/sktime/base/_base.py index b1b75665d0d..7cc2eb47b7d 100644 --- a/sktime/base/_base.py +++ b/sktime/base/_base.py @@ -142,17 +142,19 @@ def get_tag(self, tag_name, tag_value_default=None, raise_error=True): tag_value_default : any type, optional; default=None Default/fallback value if tag is not found raise_error : bool - whether a ValueError is raised when the tag is not found + whether a ValueError is raised when the tag is not found and + tag_value_default is None Returns ------- tag_value : Value of the `tag_name` tag in self. If not found, returns - `tag_value_default`. + `tag_value_default`, or raises a ValueError if `tag_value_default` is None. Raises ------ - ValueError if raise_error is True and tag_name does not exist + ValueError if raise_error is True, tag_name does not exist and + `tag_value_default` is None. i.e., if tag_name is not in self.get_tags().keys() """ collected_tags = self.get_tags() diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 8a51874b1b6..f1234a4e96e 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -8,6 +8,7 @@ class name: BaseClassifier Scitype defining methods: fitting - fit(self, X, y) predicting - predict(self, X) + - predict_proba(self, X) State: fitted model/strategy - by convention, any attributes ending in "_" @@ -26,50 +27,20 @@ class name: BaseClassifier __all__ = [ "BaseClassifier", - "classifier_list", ] -__author__ = ["mloning", "fkiraly"] +__author__ = ["mloning", "fkiraly","TonyBagnall"] import numpy as np from sktime.base import BaseEstimator from sktime.utils.validation.panel import check_X, check_X_y -""" -Main list of classifiers extending this class. For clarity, some utility classifiers, -such as Proximity Stump, are not listed. -""" -classifier_list = [ - # in classification/distance_based - "ProximityForest", - # "KNeighborsTimeSeriesClassifier", - # "ElasticEnsemble", - # "ShapeDTW", - # in classification/dictionary_based - "BOSS", - "ContractableBOSS", - "TemporalDictionaryEnsemble", - "WEASEL", - "MUSE", - # in classification/interval_based - "RandomIntervalSpectralForest", - "TimeSeriesForest", - "CanonicalIntervalForest", - # in classification/shapelet_based - "ShapeletTransformClassifier", - "ROCKET", - "MrSEQLClassifier", -] - class BaseClassifier(BaseEstimator): """Base time series classifier template class. - The base classifier specifies the methods and method - signatures that all forecasters have to implement. - - Specific implementations of these methods is deferred to concrete - forecasters. + The base classifier specifies the methods and method signatures that all + classifiers have to implement. """ _tags = { @@ -94,8 +65,7 @@ def fit(self, X, y): ---------- X : 3D np.array, array-like or sparse matrix of shape = [n_instances,n_dimensions,series_length] - or shape = [n_instances,series_length] - or single-column pd.DataFrame with pd.Series entries + or pd.DataFrame with each column a dimension, each cell a pd.Series y : array-like, shape = [n_instances] - the class labels. Returns @@ -132,7 +102,7 @@ def predict(self, X): X : 3D np.array, array-like or sparse matrix of shape = [n_instances,n_dimensions,series_length] or shape = [n_instances,series_length] - or single-column pd.DataFrame with pd.Series entries + or pd.DataFrame with each column a dimension, each cell a pd.Series Returns ------- @@ -160,11 +130,12 @@ def predict_proba(self, X): X : 3D np.array, array-like or sparse matrix of shape = [n_instances,n_dimensions,series_length] or shape = [n_instances,series_length] - or single-column pd.DataFrame with pd.Series entries + or pd.DataFrame with each column a dimension, each cell a pd.Series Returns ------- - y : array-like, shape = [n_instances, n_classes] - predictive pmf + y : array-like, shape = [n_instances, n_classes] - estimated class + probabilities """ coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) @@ -185,7 +156,7 @@ def score(self, X, y): X : 3D np.array, array-like or sparse matrix of shape = [n_instances,n_dimensions,series_length] or shape = [n_instances,series_length] - or single-column pd.DataFrame with pd.Series entries + or pd.DataFrame with each column a dimension, each cell a pd.Series y : array-like, shape = [n_instances] - predicted class labels Returns @@ -199,14 +170,14 @@ def score(self, X, y): def _fit(self, X, y): """Fit time series classifier to training data. - core logic + Abstract method Parameters ---------- X : 3D np.array, array-like or sparse matrix of shape = [n_instances,n_dimensions,series_length] or shape = [n_instances,series_length] - or single-column pd.DataFrame with pd.Series entries + or pd.DataFrame with each column a dimension, each cell a pd.Series y : array-like, shape = [n_instances] - the class labels Returns @@ -224,14 +195,14 @@ def _fit(self, X, y): def _predict(self, X): """Predicts labels for sequences in X. - core logic + Default behaviour: make predictions from predict_proba Parameters ---------- X : 3D np.array, array-like or sparse matrix of shape = [n_instances,n_dimensions,series_length] or shape = [n_instances,series_length] - or single-column pd.DataFrame with pd.Series entries + or pd.DataFrame with each column a dimension, each cell a pd.Series Returns ------- From 9d36d91394e6b8480306258ae7ff34f7e9cdf7ae Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 20:10:56 +0100 Subject: [PATCH 06/28] formatting 1 --- sktime/classification/base.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index f1234a4e96e..c66ab6eba1f 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -28,7 +28,7 @@ class name: BaseClassifier __all__ = [ "BaseClassifier", ] -__author__ = ["mloning", "fkiraly","TonyBagnall"] +__author__ = ["mloning", "fkiraly", "TonyBagnall"] import numpy as np @@ -80,8 +80,9 @@ def fit(self, X, y): """ coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag("capability:multivariate", - tag_value_default=False) + enforce_univariate = self.get_tag( + "capability:multivariate", tag_value_default=False + ) X, y = check_X_y( X, y, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, enforce_univariate=enforce_univariate @@ -110,10 +111,13 @@ def predict(self, X): """ coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag("capability:multivariate", - tag_value_default=False) + enforce_univariate = self.get_tag( + "capability:multivariate", tag_value_default=False + ) X = check_X( - X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, + X, + coerce_to_numpy=coerce_to_numpy, + coerce_to_pandas=coerce_to_pandas, enforce_univariate=enforce_univariate ) self.check_is_fitted() @@ -139,10 +143,13 @@ def predict_proba(self, X): """ coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag("capability:multivariate", - tag_value_default=False) + enforce_univariate = self.get_tag( + "capability:multivariate", tag_value_default=False + ) X = check_X( - X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, + X, + coerce_to_numpy=coerce_to_numpy, + coerce_to_pandas=coerce_to_pandas, enforce_univariate=enforce_univariate ) self.check_is_fitted() @@ -170,7 +177,7 @@ def score(self, X, y): def _fit(self, X, y): """Fit time series classifier to training data. - Abstract method + Abstract method Parameters ---------- From 4ccd2dfecd2e4a1a8aba44d6a4ad51c60153bdff Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 20:13:49 +0100 Subject: [PATCH 07/28] formatting 3 --- sktime/classification/base.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index c66ab6eba1f..0aecd48d875 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -84,7 +84,10 @@ def fit(self, X, y): "capability:multivariate", tag_value_default=False ) X, y = check_X_y( - X, y, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, + X, + y, + coerce_to_numpy=coerce_to_numpy, + coerce_to_pandas=coerce_to_pandas, enforce_univariate=enforce_univariate ) @@ -118,7 +121,7 @@ def predict(self, X): X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, - enforce_univariate=enforce_univariate + enforce_univariate=enforce_univariate, ) self.check_is_fitted() @@ -150,7 +153,7 @@ def predict_proba(self, X): X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, - enforce_univariate=enforce_univariate + enforce_univariate=enforce_univariate, ) self.check_is_fitted() return self._predict_proba(X) From 5503c54debe4b80f338356497d3ac80015f2adbd Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 20:16:03 +0100 Subject: [PATCH 08/28] formatting 4 --- sktime/classification/base.py | 2 +- sktime/registry/_tags.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 0aecd48d875..f28b42ca7c3 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -88,7 +88,7 @@ def fit(self, X, y): y, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, - enforce_univariate=enforce_univariate + enforce_univariate=enforce_univariate, ) self._fit(X, y) diff --git a/sktime/registry/_tags.py b/sktime/registry/_tags.py index fa7fb61d57b..b1f7b6842f5 100644 --- a/sktime/registry/_tags.py +++ b/sktime/registry/_tags.py @@ -43,7 +43,6 @@ import pandas as pd - ESTIMATOR_TAG_REGISTER = [ ( "ignores-exogeneous-X", From 50ca231ef97dec47c539d69561054fb11019cf33 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 20:19:35 +0100 Subject: [PATCH 09/28] formatting 6? --- sktime/base/_base.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/sktime/base/_base.py b/sktime/base/_base.py index 7cc2eb47b7d..cf442e57596 100644 --- a/sktime/base/_base.py +++ b/sktime/base/_base.py @@ -49,13 +49,10 @@ class name: BaseEstimator __all__ = ["BaseEstimator", "BaseObject"] import inspect - from copy import deepcopy - from sklearn import clone from sklearn.base import BaseEstimator as _BaseEstimator from sklearn.ensemble._base import _set_random_states - from sktime.exceptions import NotFittedError From f7dc72901a9d652bacf46f4eb09477443a86bcee Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Wed, 13 Oct 2021 20:22:23 +0100 Subject: [PATCH 10/28] blank lines or no blank lines? --- sktime/base/_base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sktime/base/_base.py b/sktime/base/_base.py index cf442e57596..c7645cac09d 100644 --- a/sktime/base/_base.py +++ b/sktime/base/_base.py @@ -50,9 +50,11 @@ class name: BaseEstimator import inspect from copy import deepcopy + from sklearn import clone from sklearn.base import BaseEstimator as _BaseEstimator from sklearn.ensemble._base import _set_random_states + from sktime.exceptions import NotFittedError From 5919fbb8c55f30d707866be31c4bee9e8277f3e6 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Thu, 14 Oct 2021 05:00:47 +0100 Subject: [PATCH 11/28] remove unnecessary argument to get_tag --- sktime/classification/base.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index f28b42ca7c3..21e14d7ee29 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -78,11 +78,9 @@ def fit(self, X, y): Changes state by creating a fitted model that updates attributes ending in "_" and sets is_fitted flag to True. """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag( - "capability:multivariate", tag_value_default=False - ) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") + coerce_to_pandas = self.get_tag("coerce-X-to-pandas") + enforce_univariate = self.get_tag("capability:multivariate") X, y = check_X_y( X, y, @@ -112,11 +110,9 @@ def predict(self, X): ------- y : array-like, shape = [n_instances] - predicted class labels """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag( - "capability:multivariate", tag_value_default=False - ) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") + coerce_to_pandas = self.get_tag("coerce-X-to-pandas") + enforce_univariate = self.get_tag("capability:multivariate") X = check_X( X, coerce_to_numpy=coerce_to_numpy, @@ -144,11 +140,9 @@ def predict_proba(self, X): y : array-like, shape = [n_instances, n_classes] - estimated class probabilities """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag( - "capability:multivariate", tag_value_default=False - ) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") + coerce_to_pandas = self.get_tag("coerce-X-to-pandas") + enforce_univariate = self.get_tag("capability:multivariate") X = check_X( X, coerce_to_numpy=coerce_to_numpy, From 4bdb4574053ae56b4cb3a87842602cfecaafba9c Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Thu, 14 Oct 2021 10:17:52 +0100 Subject: [PATCH 12/28] negate tag correctly, remove unnecessary get_tag argument --- sktime/classification/base.py | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index f28b42ca7c3..1b3934a656b 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -78,17 +78,15 @@ def fit(self, X, y): Changes state by creating a fitted model that updates attributes ending in "_" and sets is_fitted flag to True. """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag( - "capability:multivariate", tag_value_default=False - ) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") + coerce_to_pandas = self.get_tag("coerce-X-to-pandas") + allow_multivariate = self.get_tag("capability:multivariate") X, y = check_X_y( X, y, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, - enforce_univariate=enforce_univariate, + enforce_univariate=not allow_multivariate, ) self._fit(X, y) @@ -112,16 +110,14 @@ def predict(self, X): ------- y : array-like, shape = [n_instances] - predicted class labels """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag( - "capability:multivariate", tag_value_default=False - ) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") + coerce_to_pandas = self.get_tag("coerce-X-to-pandas") + allow_multivariate = self.get_tag("capability:multivariate") X = check_X( X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, - enforce_univariate=enforce_univariate, + enforce_univariate=not allow_multivariate, ) self.check_is_fitted() @@ -144,16 +140,14 @@ def predict_proba(self, X): y : array-like, shape = [n_instances, n_classes] - estimated class probabilities """ - coerce_to_numpy = self.get_tag("coerce-X-to-numpy", tag_value_default=False) - coerce_to_pandas = self.get_tag("coerce-X-to-pandas", tag_value_default=False) - enforce_univariate = self.get_tag( - "capability:multivariate", tag_value_default=False - ) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") + coerce_to_pandas = self.get_tag("coerce-X-to-pandas") + allow_multivariate = self.get_tag("capability:multivariate") X = check_X( X, coerce_to_numpy=coerce_to_numpy, coerce_to_pandas=coerce_to_pandas, - enforce_univariate=enforce_univariate, + enforce_univariate=not allow_multivariate, ) self.check_is_fitted() return self._predict_proba(X) From 6accbc6dee25a8752af0a92b79973710bc4bc8a2 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Thu, 14 Oct 2021 10:21:13 +0100 Subject: [PATCH 13/28] correct tag negation --- sktime/classification/base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 59d623e8859..1b3934a656b 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -80,7 +80,7 @@ def fit(self, X, y): """ coerce_to_numpy = self.get_tag("coerce-X-to-numpy") coerce_to_pandas = self.get_tag("coerce-X-to-pandas") - enforce_univariate = self.get_tag("capability:multivariate") + allow_multivariate = self.get_tag("capability:multivariate") X, y = check_X_y( X, y, @@ -112,7 +112,7 @@ def predict(self, X): """ coerce_to_numpy = self.get_tag("coerce-X-to-numpy") coerce_to_pandas = self.get_tag("coerce-X-to-pandas") - enforce_univariate = self.get_tag("capability:multivariate") + allow_multivariate = self.get_tag("capability:multivariate") X = check_X( X, coerce_to_numpy=coerce_to_numpy, @@ -142,7 +142,7 @@ def predict_proba(self, X): """ coerce_to_numpy = self.get_tag("coerce-X-to-numpy") coerce_to_pandas = self.get_tag("coerce-X-to-pandas") - enforce_univariate = self.get_tag("capability:multivariate") + allow_multivariate = self.get_tag("capability:multivariate") X = check_X( X, coerce_to_numpy=coerce_to_numpy, From d40840885b6a8925737656062677d7fc203809bc Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 16 Oct 2021 13:20:49 +0100 Subject: [PATCH 14/28] _predict _predict_proba _predict made abstract, _ predict_proba given a default implmentation n_classes_ added to base class --- sktime/classification/base.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 1b3934a656b..607f0bb25a6 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -55,6 +55,7 @@ class BaseClassifier(BaseEstimator): def __init__(self): self._is_fitted = False + self.n_classes_ = 0 super(BaseClassifier, self).__init__() @@ -88,7 +89,7 @@ def fit(self, X, y): coerce_to_pandas=coerce_to_pandas, enforce_univariate=not allow_multivariate, ) - + self.n_classes_ = np.unique(y).shape[0] self._fit(X, y) # this should happen last @@ -194,12 +195,13 @@ def _fit(self, X, y): Changes state by creating a fitted model that updates attributes ending in "_" and sets is_fitted flag to True. """ - raise NotImplementedError("abstract method") + raise NotImplementedError("_fit is a protected abstract method, it must be " + "implemented.") def _predict(self, X): """Predicts labels for sequences in X. - Default behaviour: make predictions from predict_proba + Abstract class, must be implemented. Parameters ---------- @@ -212,28 +214,32 @@ def _predict(self, X): ------- y : array-like, shape = [n_instances] - predicted class labels """ - distributions = self.predict_proba(X) - predictions = [] - for instance_index in range(0, X.shape[0]): - distribution = distributions[instance_index] - prediction = np.argmax(distribution) - predictions.append(prediction) - y = self.label_encoder.inverse_transform(predictions) - return y + raise NotImplementedError("_predict is a protected abstract method, it must be " + "implemented.") def _predict_proba(self, X): """Predicts labels probabilities for sequences in X. + Default behaviour is to call _predict and set the predicted class probability + to 1, other class probabilities to 0. Override if better estimates are + obtainable. + Parameters ---------- X : 3D np.array, array-like or sparse matrix of shape = [n_instances,n_dimensions,series_length] or shape = [n_instances,series_length] - or single-column pd.DataFrame with pd.Series entries + or pd.DataFrame with each column a dimension, each cell a pd.Series Returns ------- - y : array-like, shape = [n_instances, n_classes] - predictive pmf + y : array-like, shape = [n_instances, n_classes] - estimated probabilities + of class membership. """ - raise NotImplementedError("abstract method") + dists = np.zeros((X.shape[0], self.n_classes_)) + preds = self._predict(X) + for i in range(0,len(preds)): + dists[preds[i]] = 1 + + return dists From b17f9a7da271055f096e690aaa35e17758b1a082 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 16 Oct 2021 13:26:33 +0100 Subject: [PATCH 15/28] formatting 1 --- sktime/classification/base.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 607f0bb25a6..917812ecc36 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -195,8 +195,9 @@ def _fit(self, X, y): Changes state by creating a fitted model that updates attributes ending in "_" and sets is_fitted flag to True. """ - raise NotImplementedError("_fit is a protected abstract method, it must be " - "implemented.") + raise NotImplementedError( + "_fit is a protected abstract method, it must be implemented." + ) def _predict(self, X): """Predicts labels for sequences in X. @@ -215,8 +216,9 @@ def _predict(self, X): y : array-like, shape = [n_instances] - predicted class labels """ - raise NotImplementedError("_predict is a protected abstract method, it must be " - "implemented.") + raise NotImplementedError( + "_predict is a protected abstract method, it must be implemented." + ) def _predict_proba(self, X): """Predicts labels probabilities for sequences in X. @@ -239,7 +241,7 @@ def _predict_proba(self, X): """ dists = np.zeros((X.shape[0], self.n_classes_)) preds = self._predict(X) - for i in range(0,len(preds)): + for i in range(0, len(preds)): dists[preds[i]] = 1 return dists From 57347f783e2a8354fd62088dcfbe4240e1fc2d81 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 16 Oct 2021 13:29:00 +0100 Subject: [PATCH 16/28] formatting 2 --- sktime/classification/base.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 917812ecc36..b1aaac23138 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -215,7 +215,6 @@ def _predict(self, X): ------- y : array-like, shape = [n_instances] - predicted class labels """ - raise NotImplementedError( "_predict is a protected abstract method, it must be implemented." ) From 8b29a99e983d2ff86e9d4a8aac913e4efa11ea74 Mon Sep 17 00:00:00 2001 From: Matthew Middlehurst Date: Sun, 17 Oct 2021 21:12:44 +0100 Subject: [PATCH 17/28] HC comments an experiments fixes --- sktime/classification/base.py | 38 ++++++++++++++++++++++++++--------- sktime/registry/_tags.py | 10 +++++++-- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index b1aaac23138..eb83de5beab 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -33,6 +33,7 @@ class name: BaseClassifier import numpy as np from sktime.base import BaseEstimator +from sktime.utils.validation import check_n_jobs from sktime.utils.validation.panel import check_X, check_X_y @@ -51,12 +52,14 @@ class BaseClassifier(BaseEstimator): "capability:missing_values": False, "capability:train_estimate": False, "capability:contractable": False, + "capability:multithreading": False, } def __init__(self): - self._is_fitted = False + self.classes_ = [] self.n_classes_ = 0 - + self._class_dictionary = {} + self._threads_to_use = 1 super(BaseClassifier, self).__init__() def fit(self, X, y): @@ -89,7 +92,21 @@ def fit(self, X, y): coerce_to_pandas=coerce_to_pandas, enforce_univariate=not allow_multivariate, ) - self.n_classes_ = np.unique(y).shape[0] + + multithread = self.get_tag("capability:multithreading") + if multithread: + try: + self._threads_to_use = check_n_jobs(self.n_jobs) + except NameError: + raise AttributeError( + "self.n_jobs must be set if capability:multithreading is True" + ) + + self.classes_ = np.unique(y) + self.n_classes_ = self.classes_.shape[0] + for index, classVal in enumerate(self.classes_): + self._class_dictionary[classVal] = index + self._fit(X, y) # this should happen last @@ -111,6 +128,8 @@ def predict(self, X): ------- y : array-like, shape = [n_instances] - predicted class labels """ + self.check_is_fitted() + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") coerce_to_pandas = self.get_tag("coerce-X-to-pandas") allow_multivariate = self.get_tag("capability:multivariate") @@ -120,11 +139,8 @@ def predict(self, X): coerce_to_pandas=coerce_to_pandas, enforce_univariate=not allow_multivariate, ) - self.check_is_fitted() - - y = self._predict(X) - return y + return self._predict(X) def predict_proba(self, X): """Predicts labels probabilities for sequences in X. @@ -141,6 +157,8 @@ def predict_proba(self, X): y : array-like, shape = [n_instances, n_classes] - estimated class probabilities """ + self.check_is_fitted() + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") coerce_to_pandas = self.get_tag("coerce-X-to-pandas") allow_multivariate = self.get_tag("capability:multivariate") @@ -150,7 +168,7 @@ def predict_proba(self, X): coerce_to_pandas=coerce_to_pandas, enforce_univariate=not allow_multivariate, ) - self.check_is_fitted() + return self._predict_proba(X) def score(self, X, y): @@ -240,7 +258,7 @@ def _predict_proba(self, X): """ dists = np.zeros((X.shape[0], self.n_classes_)) preds = self._predict(X) - for i in range(0, len(preds)): - dists[preds[i]] = 1 + for i in range(0, X.shape[0]): + dists[i, np.where(self.classes_ == preds[i])] = 1 return dists diff --git a/sktime/registry/_tags.py b/sktime/registry/_tags.py index b1f7b6842f5..4867ec0932c 100644 --- a/sktime/registry/_tags.py +++ b/sktime/registry/_tags.py @@ -138,13 +138,13 @@ "capability:multivariate", "classifier", "bool", - "can classifier classify time series with 2 or more variables?", + "can the classifier classify time series with 2 or more variables?", ), ( "capability:unequal_length", "classifier", "bool", - "can classifier handle unequal length time series?", + "can the classifier handle unequal length time series?", ), # "capability:missing_values" is same as "handles-missing-data" tag. # They are kept distinct intentionally for easier TSC refactoring. @@ -167,6 +167,12 @@ "bool", "contract time setting, i.e. does the estimator support limiting max fit time?", ), + ( + "capability:multithreading", + "classifier", + "bool", + "can the classifier set n_jobs to use multiple threads?", + ), ( "coerce-X-to-pandas", ["classifier", "transformer"], From b31afcda35f8349a83c052986180208a013cced7 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Tue, 19 Oct 2021 10:16:08 +0100 Subject: [PATCH 18/28] Update base.py --- sktime/classification/base.py | 51 +++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index eb83de5beab..ea066a0f0da 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -67,10 +67,13 @@ def fit(self, X, y): Parameters ---------- - X : 3D np.array, array-like or sparse matrix - of shape = [n_instances,n_dimensions,series_length] - or pd.DataFrame with each column a dimension, each cell a pd.Series - y : array-like, shape = [n_instances] - the class labels. + X : 2D np.array (univariate, equal length series) of shape = [n_instances, + series_length] + or 3D np.array (any number of dimensions, equal length series) of shape = + [n_instances,n_dimensions,series_length] + or pd.DataFrame with each column a dimension, each cell a pd.Series (any + number of dimensions, equal or unequal length series) + y : 1D np.array of shape = [n_instances] - the class labels. Returns ------- @@ -119,14 +122,16 @@ def predict(self, X): Parameters ---------- - X : 3D np.array, array-like or sparse matrix - of shape = [n_instances,n_dimensions,series_length] - or shape = [n_instances,series_length] - or pd.DataFrame with each column a dimension, each cell a pd.Series + X : 2D np.array (univariate, equal length series) of shape = [n_instances, + series_length] + or 3D np.array (any number of dimensions, equal length series) of shape = + [n_instances,n_dimensions,series_length] + or pd.DataFrame with each column a dimension, each cell a pd.Series (any + number of dimensions, equal or unequal length series) Returns ------- - y : array-like, shape = [n_instances] - predicted class labels + y : 1D np.array of shape = [n_instances] - predicted class labels """ self.check_is_fitted() @@ -147,14 +152,18 @@ def predict_proba(self, X): Parameters ---------- - X : 3D np.array, array-like or sparse matrix - of shape = [n_instances,n_dimensions,series_length] - or shape = [n_instances,series_length] - or pd.DataFrame with each column a dimension, each cell a pd.Series + Parameters + ---------- + X : 2D np.array (univariate, equal length series) of shape = [n_instances, + series_length] + or 3D np.array (any number of dimensions, equal length series) of shape = + [n_instances,n_dimensions,series_length] + or pd.DataFrame with each column a dimension, each cell a pd.Series (any + number of dimensions, equal or unequal length series) Returns ------- - y : array-like, shape = [n_instances, n_classes] - estimated class + y : 2D array of shape = [n_instances, n_classes] - estimated class probabilities """ self.check_is_fitted() @@ -171,16 +180,18 @@ def predict_proba(self, X): return self._predict_proba(X) - def score(self, X, y): + def score(self, X, y) -> float: """Scores predicted labels against ground truth labels on X. Parameters ---------- - X : 3D np.array, array-like or sparse matrix - of shape = [n_instances,n_dimensions,series_length] - or shape = [n_instances,series_length] - or pd.DataFrame with each column a dimension, each cell a pd.Series - y : array-like, shape = [n_instances] - predicted class labels + X : 2D np.array (univariate, equal length series) of shape = [n_instances, + series_length] + or 3D np.array (any number of dimensions, equal length series) of shape = + [n_instances,n_dimensions,series_length] + or pd.DataFrame with each column a dimension, each cell a pd.Series (any + number of dimensions, equal or unequal length series) + y : array-like, shape = [n_instances] - actual class labels Returns ------- From 26069f775d59257ea1da63758628020a9110b19b Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Tue, 19 Oct 2021 10:19:41 +0100 Subject: [PATCH 19/28] Update base.py --- sktime/classification/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index ea066a0f0da..fa497e3c7ad 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -231,7 +231,7 @@ def _fit(self, X, y): def _predict(self, X): """Predicts labels for sequences in X. - Abstract class, must be implemented. + Abstract method, must be implemented. Parameters ---------- From 27949f6900b1e97c063ca02097403cc5194df017 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Tue, 19 Oct 2021 10:30:29 +0100 Subject: [PATCH 20/28] fix comments in get_tags --- sktime/base/_base.py | 9 ++++----- sktime/classification/base.py | 5 +++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/sktime/base/_base.py b/sktime/base/_base.py index c7645cac09d..9c19b55e8d8 100644 --- a/sktime/base/_base.py +++ b/sktime/base/_base.py @@ -147,14 +147,13 @@ def get_tag(self, tag_name, tag_value_default=None, raise_error=True): Returns ------- tag_value : - Value of the `tag_name` tag in self. If not found, returns - `tag_value_default`, or raises a ValueError if `tag_value_default` is None. + Value of the `tag_name` tag in self. If not found, returns an error if + raise_error is True, otherwise it returns `tag_value_default`. Raises ------ - ValueError if raise_error is True, tag_name does not exist and - `tag_value_default` is None. - i.e., if tag_name is not in self.get_tags().keys() + ValueError if raise_error is True i.e. if tag_name is not in self.get_tags( + ).keys() """ collected_tags = self.get_tags() diff --git a/sktime/classification/base.py b/sktime/classification/base.py index fa497e3c7ad..7f70c8d462f 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -85,6 +85,11 @@ def fit(self, X, y): Changes state by creating a fitted model that updates attributes ending in "_" and sets is_fitted flag to True. """ +# blah = self.get_tag("not-here") +# print(" blah = ", blah) + blah = self.get_tag("not-here", raise_error=False) + print(" blah = ", blah) + coerce_to_numpy = self.get_tag("coerce-X-to-numpy") coerce_to_pandas = self.get_tag("coerce-X-to-pandas") allow_multivariate = self.get_tag("capability:multivariate") From 031a18b921c5dbd78b7b862f7294234451c4869f Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Tue, 19 Oct 2021 10:34:13 +0100 Subject: [PATCH 21/28] remove debug --- sktime/classification/base.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 7f70c8d462f..fa497e3c7ad 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -85,11 +85,6 @@ def fit(self, X, y): Changes state by creating a fitted model that updates attributes ending in "_" and sets is_fitted flag to True. """ -# blah = self.get_tag("not-here") -# print(" blah = ", blah) - blah = self.get_tag("not-here", raise_error=False) - print(" blah = ", blah) - coerce_to_numpy = self.get_tag("coerce-X-to-numpy") coerce_to_pandas = self.get_tag("coerce-X-to-pandas") allow_multivariate = self.get_tag("capability:multivariate") From dee524b4323b11e6da4c31e37052f8222031756e Mon Sep 17 00:00:00 2001 From: Matthew Middlehurst Date: Tue, 19 Oct 2021 10:36:19 +0100 Subject: [PATCH 22/28] get_tag comment revert --- sktime/base/_base.py | 3 +-- sktime/classification/base.py | 7 ------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/sktime/base/_base.py b/sktime/base/_base.py index 9c19b55e8d8..ea32fc4351d 100644 --- a/sktime/base/_base.py +++ b/sktime/base/_base.py @@ -141,8 +141,7 @@ def get_tag(self, tag_name, tag_value_default=None, raise_error=True): tag_value_default : any type, optional; default=None Default/fallback value if tag is not found raise_error : bool - whether a ValueError is raised when the tag is not found and - tag_value_default is None + whether a ValueError is raised when the tag is not found Returns ------- diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 7f70c8d462f..ffc52daf406 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -85,11 +85,6 @@ def fit(self, X, y): Changes state by creating a fitted model that updates attributes ending in "_" and sets is_fitted flag to True. """ -# blah = self.get_tag("not-here") -# print(" blah = ", blah) - blah = self.get_tag("not-here", raise_error=False) - print(" blah = ", blah) - coerce_to_numpy = self.get_tag("coerce-X-to-numpy") coerce_to_pandas = self.get_tag("coerce-X-to-pandas") allow_multivariate = self.get_tag("capability:multivariate") @@ -155,8 +150,6 @@ def predict(self, X): def predict_proba(self, X): """Predicts labels probabilities for sequences in X. - Parameters - ---------- Parameters ---------- X : 2D np.array (univariate, equal length series) of shape = [n_instances, From feade0ebc14157bce957a6fd976a342ad1f6dcde Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Tue, 19 Oct 2021 10:36:22 +0100 Subject: [PATCH 23/28] format 1 --- sktime/classification/base.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index fa497e3c7ad..ffc52daf406 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -150,8 +150,6 @@ def predict(self, X): def predict_proba(self, X): """Predicts labels probabilities for sequences in X. - Parameters - ---------- Parameters ---------- X : 2D np.array (univariate, equal length series) of shape = [n_instances, From 87dfa72dc161f25ac1cc949965f3fdd898743282 Mon Sep 17 00:00:00 2001 From: Matthew Middlehurst Date: Tue, 19 Oct 2021 10:40:38 +0100 Subject: [PATCH 24/28] doc consistency --- sktime/classification/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index ffc52daf406..3dcdef22f8f 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -202,7 +202,7 @@ def score(self, X, y) -> float: def _fit(self, X, y): """Fit time series classifier to training data. - Abstract method + Abstract method, must be implemented. Parameters ---------- From d85c4c6e53b5c1dd5de074fe3d668530bab395a6 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Tue, 19 Oct 2021 13:38:07 +0100 Subject: [PATCH 25/28] change contributors on both base Use markus's github instead of full name, added matthew. --- sktime/classification/base.py | 11 +++-------- sktime/forecasting/base/_base.py | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 3dcdef22f8f..1bf399f2b12 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -1,20 +1,15 @@ # -*- coding: utf-8 -*- # copyright: sktime developers, BSD-3-Clause License (see LICENSE file) """ -Base class template for time series classifier scitype. +Base class template for time series classifier. class name: BaseClassifier -Scitype defining methods: +Defining methods: fitting - fit(self, X, y) predicting - predict(self, X) - predict_proba(self, X) -State: - fitted model/strategy - by convention, any attributes ending in "_" - fitted state flag - is_fitted (property) - fitted state inspection - check_is_fitted() - Inspection methods: hyper-parameter inspection - get_params() fitted parameter inspection - get_fitted_params() @@ -28,7 +23,7 @@ class name: BaseClassifier __all__ = [ "BaseClassifier", ] -__author__ = ["mloning", "fkiraly", "TonyBagnall"] +__author__ = ["mloning", "fkiraly", "TonyBagnall", "MatthewMiddlehurst"] import numpy as np diff --git a/sktime/forecasting/base/_base.py b/sktime/forecasting/base/_base.py index f2479325a5f..c47bb2f3426 100644 --- a/sktime/forecasting/base/_base.py +++ b/sktime/forecasting/base/_base.py @@ -26,7 +26,7 @@ class name: BaseForecaster """ -__author__ = ["Markus Löning", "@big-o", "fkiraly"] +__author__ = ["mloning", "@big-o", "fkiraly"] __all__ = ["BaseForecaster"] from sktime.base import BaseEstimator From f0b64bc97783d448c3d2d51b91209fef6e5ee85a Mon Sep 17 00:00:00 2001 From: Matthew Middlehurst Date: Tue, 19 Oct 2021 14:00:31 +0100 Subject: [PATCH 26/28] class dictionary useage in predict_proba default --- sktime/classification/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 3dcdef22f8f..093da115e22 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -268,6 +268,6 @@ def _predict_proba(self, X): dists = np.zeros((X.shape[0], self.n_classes_)) preds = self._predict(X) for i in range(0, X.shape[0]): - dists[i, np.where(self.classes_ == preds[i])] = 1 + dists[i, self._class_dictionary[preds[i]]] = 1 return dists From aa7f500379077bb7f8cb7dd1be7c52af4c805269 Mon Sep 17 00:00:00 2001 From: Matthew Middlehurst Date: Tue, 19 Oct 2021 14:08:05 +0100 Subject: [PATCH 27/28] code quality --- sktime/forecasting/base/_base.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/sktime/forecasting/base/_base.py b/sktime/forecasting/base/_base.py index c47bb2f3426..be356537254 100644 --- a/sktime/forecasting/base/_base.py +++ b/sktime/forecasting/base/_base.py @@ -29,24 +29,23 @@ class name: BaseForecaster __author__ = ["mloning", "@big-o", "fkiraly"] __all__ = ["BaseForecaster"] -from sktime.base import BaseEstimator - from contextlib import contextmanager from warnings import warn import numpy as np import pandas as pd -from sktime.utils.datetime import _shift -from sktime.utils.validation.forecasting import check_X -from sktime.utils.validation.forecasting import check_alpha -from sktime.utils.validation.forecasting import check_cv -from sktime.utils.validation.forecasting import check_fh -from sktime.utils.validation.forecasting import check_y_X -from sktime.utils.validation.series import check_series, check_equal_time_index - +from sktime.base import BaseEstimator from sktime.datatypes import convert_to, mtype - +from sktime.utils.datetime import _shift +from sktime.utils.validation.forecasting import ( + check_alpha, + check_cv, + check_fh, + check_X, + check_y_X, +) +from sktime.utils.validation.series import check_equal_time_index, check_series DEFAULT_ALPHA = 0.05 From a4b5b1a4250d033cb8ca863002e200d65df22475 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Tue, 19 Oct 2021 14:44:40 +0100 Subject: [PATCH 28/28] Update base.py --- sktime/classification/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sktime/classification/base.py b/sktime/classification/base.py index 48d4163bb32..8767fdea9ba 100644 --- a/sktime/classification/base.py +++ b/sktime/classification/base.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # copyright: sktime developers, BSD-3-Clause License (see LICENSE file) """ -Base class template for time series classifier. +Abstract base class for time series classifiers. class name: BaseClassifier @@ -33,7 +33,7 @@ class name: BaseClassifier class BaseClassifier(BaseEstimator): - """Base time series classifier template class. + """Abstract base class for time series classifiers. The base classifier specifies the methods and method signatures that all classifiers have to implement.