From 017b92b4546f98662929e8e132591d0c04e4df53 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Fri, 4 Jul 2025 21:29:48 +0100 Subject: [PATCH 01/19] signature docs --- .../signature_based/_signature_method.py | 24 +++++++++++-------- .../transformations/signature_method.ipynb | 3 ++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/aeon/transformations/collection/signature_based/_signature_method.py b/aeon/transformations/collection/signature_based/_signature_method.py index 8606fd84fc..119cd67fff 100644 --- a/aeon/transformations/collection/signature_based/_signature_method.py +++ b/aeon/transformations/collection/signature_based/_signature_method.py @@ -19,17 +19,21 @@ class SignatureTransformer(BaseCollectionTransformer): Parameters ---------- - augmentation_list: tuple of strings, contains the augmentations to be - applied before application of the signature transform. - window_name: str, The name of the window transform to apply. - window_depth: int, The depth of the dyadic window. (Active only if - `window_name == 'dyadic'`). - window_length: int, The length of the sliding/expanding window. (Active + augmentation_list : tuple of strings, default = ``("basepoint", "addtime")`` + Contains the augmentations to be applied before application of the signature + transform. + window_name : str + The name of the window transform to apply. + window_depth : int + The depth of the dyadic window. (Active only if ``window_name == 'dyadic'``). + window_length : int + The length of the sliding/expanding window. (Active only if ``window_name`` + in ``['sliding, 'expanding']``. + window_step : int + The step of the sliding/expanding window. (Active only if `window_name in ['sliding, 'expanding']`. - window_step: int, The step of the sliding/expanding window. (Active - only if `window_name in ['sliding, 'expanding']`. - rescaling: str or None, The method of signature rescaling. - sig_tfm: str, String to specify the type of signature transform. One of: + rescaling : str or None, The method of signature rescaling. + sig_tfm : str, String to specify the type of signature transform. One of: ['signature', 'logsignature']). depth: int, Signature truncation depth. diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 81d6d4b866..b908e05468 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -146,7 +146,8 @@ "source": [ "### Overview\n", "We provide the following:\n", - "- **aeon.transformers.panel.signature_based.SignatureTransformer** - An sklearn transformer that provides the functionality to apply the signature method with some choice of variations as noted above.\n", + "- **aeon.transformers.collection.signature_based.SignatureTransformer** - An sklearn \n", + "transformer that provides the functionality to apply the signature method with some choice of variations as noted above.\n", "- **aeon.classification.feature_based.SignatureClassifier** - This provides a simple interface to append a classifier to the SignatureTransformer class." ] }, From e017292ad051bfee412a58060aa761a0feea96c5 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 5 Jul 2025 17:44:18 +0100 Subject: [PATCH 02/19] tests --- .../collection/signature_based/_rescaling.py | 4 ++-- .../signature_based/_signature_method.py | 16 ++++++------- .../signature_based/tests/test_signatures.py | 24 +++++++++++++++++++ 3 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 aeon/transformations/collection/signature_based/tests/test_signatures.py diff --git a/aeon/transformations/collection/signature_based/_rescaling.py b/aeon/transformations/collection/signature_based/_rescaling.py index b2713a4737..99f2282cd6 100644 --- a/aeon/transformations/collection/signature_based/_rescaling.py +++ b/aeon/transformations/collection/signature_based/_rescaling.py @@ -35,9 +35,9 @@ def _rescale_path(path, depth): def _rescale_signature(signature, channels, depth): - """Rescals the output signature by multiplying the depth-d term by d!. + """Rescales the output signature by multiplying the depth-d term by d!. - Ain is that every term become ~O(1). + Aim is that every term become ~O(1). Parameters ---------- diff --git a/aeon/transformations/collection/signature_based/_signature_method.py b/aeon/transformations/collection/signature_based/_signature_method.py index 119cd67fff..a618011ef3 100644 --- a/aeon/transformations/collection/signature_based/_signature_method.py +++ b/aeon/transformations/collection/signature_based/_signature_method.py @@ -39,8 +39,9 @@ class SignatureTransformer(BaseCollectionTransformer): Attributes ---------- - signature_method: sklearn.Pipeline, A sklearn pipeline object that contains - all the steps to extract the signature features. + sklearn.Pipeline + sklearn pipeline object that contains all the steps to extract the signature + features. """ _tags = { @@ -70,9 +71,8 @@ def __init__( self.depth = depth super().__init__() - self.setup_feature_pipeline() - def setup_feature_pipeline(self): + def _fit(self, X, y=None): """Set up the signature method as an sklearn pipeline.""" augmentation_step = _make_augmentation_pipeline(self.augmentation_list) transform_step = _WindowSignatureTransform( @@ -86,19 +86,17 @@ def setup_feature_pipeline(self): ) # The so-called 'signature method' as defined in the reference paper - self.signature_method = Pipeline( + self.signature_method_ = Pipeline( [ ("augmentations", augmentation_step), ("window_and_transform", transform_step), ] ) - - def _fit(self, X, y=None): - self.signature_method.fit(X) + self.signature_method_.fit(X) return self def _transform(self, X, y=None): - return self.signature_method.transform(X) + return self.signature_method_.transform(X) @classmethod def _get_test_params(cls, parameter_set="default"): diff --git a/aeon/transformations/collection/signature_based/tests/test_signatures.py b/aeon/transformations/collection/signature_based/tests/test_signatures.py new file mode 100644 index 0000000000..614cf68195 --- /dev/null +++ b/aeon/transformations/collection/signature_based/tests/test_signatures.py @@ -0,0 +1,24 @@ +"""Test signatures helper functions.""" + +import numpy as np + +from aeon.transformations.collection.signature_based._rescaling import ( + _rescale_path, + _rescale_signature, +) + + +def test_rescale_path(): + """Test rescale_path function.""" + X = np.random.random((10, 2, 40)) + data = np.swapaxes(X, 1, 2) + trans = _rescale_path(data, 1) + assert isinstance(trans, np.ndarray) + + +def test_rescale_signature(): + """Test rescale_signatures.""" + X = np.random.random((10, 2, 40)) + data = np.swapaxes(X, 1, 2) + trans = _rescale_signature(data, 1) + assert isinstance(trans, np.ndarray) From a994a065129c599a26e7a28359269c1c9fddf85d Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 14:27:51 +0100 Subject: [PATCH 03/19] typo --- aeon/forecasting/_tvp.py | 2 +- .../transformations/signature_method.ipynb | 30 +++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/aeon/forecasting/_tvp.py b/aeon/forecasting/_tvp.py index 83bb9157f6..a8a8e1731a 100644 --- a/aeon/forecasting/_tvp.py +++ b/aeon/forecasting/_tvp.py @@ -25,7 +25,7 @@ class TVPForecaster(BaseForecaster): Parameters ---------- window : int - Number of autoregressive lags to use, called window to co-ordinate with + Number of autoregressive lags to use, called window to coordinate with RegressionForecaster. var : float, default=0.01 Observation noise variance. ``var`` controls the influence of recency in the diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 04890211f7..a8cca8144b 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -100,7 +100,6 @@ }, { "cell_type": "code", - "execution_count": 6, "metadata": { "collapsed": true, "execution": { @@ -111,34 +110,43 @@ }, "jupyter": { "outputs_hidden": true + }, + "ExecuteTime": { + "end_time": "2025-07-12T13:20:25.970545Z", + "start_time": "2025-07-12T13:20:21.197682Z" } }, - "outputs": [], "source": [ "# Some additional imports we will use\n", "from sklearn.ensemble import RandomForestClassifier\n", "from sklearn.metrics import accuracy_score\n", "\n", "from aeon.datasets import load_unit_test" - ] + ], + "outputs": [], + "execution_count": 1 }, { "cell_type": "code", - "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2021-06-25T12:41:11.529792Z", "iopub.status.busy": "2021-06-25T12:41:11.529157Z", "iopub.status.idle": "2021-06-25T12:41:11.609172Z", "shell.execute_reply": "2021-06-25T12:41:11.609562Z" + }, + "ExecuteTime": { + "end_time": "2025-07-12T13:20:26.002672Z", + "start_time": "2025-07-12T13:20:25.977454Z" } }, - "outputs": [], "source": [ "# Load an example dataset\n", "train_x, train_y = load_unit_test(split=\"train\")\n", "test_x, test_y = load_unit_test(split=\"test\")" - ] + ], + "outputs": [], + "execution_count": 2 }, { "cell_type": "markdown", @@ -153,7 +161,6 @@ }, { "cell_type": "code", - "execution_count": 8, "metadata": { "collapsed": true, "execution": { @@ -164,13 +171,18 @@ }, "jupyter": { "outputs_hidden": true + }, + "ExecuteTime": { + "end_time": "2025-07-12T13:20:27.077433Z", + "start_time": "2025-07-12T13:20:26.846292Z" } }, - "outputs": [], "source": [ "from aeon.classification.feature_based import SignatureClassifier\n", "from aeon.transformations.collection.signature_based import SignatureTransformer" - ] + ], + "outputs": [], + "execution_count": 3 }, { "cell_type": "markdown", From c9049b179baeb68fb41e1b978a9eb5b62149b29e Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 14:33:56 +0100 Subject: [PATCH 04/19] notebook --- .../transformations/signature_method.ipynb | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index a8cca8144b..4f744916ad 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -16,21 +16,29 @@ "metadata": {}, "source": [ "## The Path Signature\n", - "At the heart of the signature method is the so-called \"signature transform\".\n", "\n", - "A path $X$ of finite length in $\\textit{d}$ dimensions can be described by the mapping $X:[a, b]\\rightarrow\\mathbb{R}$ $\\!\\!^d$, or in terms of coordinates $X=(X^1_t, X^2_t, ...,X^d_t)$, where each coordinate $X^i_t$ is real-valued and parameterised by $t\\in[a,b]$.\n", + "At the heart of the signature method is the so-called *signature transform*.\n", + "\n", + "A path $X$ of finite length in $d$ dimensions can be described by the mapping\n", + "$X:[a, b] \\rightarrow \\mathbb{R}^d$, or in terms of coordinates\n", + "$X = (X^1_t, X^2_t, \\ldots, X^d_t)$, where each coordinate $X^i_t$ is\n", + "real-valued and parameterised by $t \\in [a,b]$.\n", "\n", "The **signature transform** $S$ of a path $X$ is defined as an infinite sequence of values:\n", "\n", - "\\begin{equation}\n", - " S(X)_{a, b} = (1, S(X)_{a, b}^1, S(X)_{a, b}^2, ..., S(X)_{a, b}^d, S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, ...),\n", - " \\label{eq:path_signature}\n", - "\\end{equation}\n", + "```{math}\n", + "S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d,\n", + "S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)\n", + "```\n", + "\n", "where each term is a $k$-fold iterated integral of $X$ with multi-index $i_1,...,i_k$:\n", - "\\begin{equation}\n", - " S(X)_{a, b}^{i_1,...,i_k} = \\int_{a Date: Sat, 12 Jul 2025 14:35:11 +0100 Subject: [PATCH 05/19] correct image --- examples/transformations/signature_method.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 4f744916ad..6a992cc33e 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -49,7 +49,7 @@ "### A Visualisation\n", "To give an idea of what the signature terms represent physically, we consider a patient in an ICU where we are tracking their systolic blood pressure (SBP) and heart rate (HR) changing in time. This can be represented as a path in $\\mathbb{R}^3$ (assuming time is included as a channel).\n", "\n", - "[signature_visualisation](img/signatures_visualisation.png)\n", + "[signature_visualisation](img/signature.png)\n", "\n", "The plot above sketches two scenarios of how such a path might look. We are assuming here an implicit time dimension for each plot such that the path is traversed from left to right along the blue line.\n", "\n", From 6ba5736f15e6a846c1268a7d99e4ddd4c1215af8 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 14:47:53 +0100 Subject: [PATCH 06/19] fix test --- .../collection/signature_based/tests/test_signatures.py | 2 +- examples/transformations/signature_method.ipynb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aeon/transformations/collection/signature_based/tests/test_signatures.py b/aeon/transformations/collection/signature_based/tests/test_signatures.py index 614cf68195..2b459ee512 100644 --- a/aeon/transformations/collection/signature_based/tests/test_signatures.py +++ b/aeon/transformations/collection/signature_based/tests/test_signatures.py @@ -20,5 +20,5 @@ def test_rescale_signature(): """Test rescale_signatures.""" X = np.random.random((10, 2, 40)) data = np.swapaxes(X, 1, 2) - trans = _rescale_signature(data, 1) + trans = _rescale_signature(data, 1, depth=2) assert isinstance(trans, np.ndarray) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 6a992cc33e..96c08d69dd 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# The Signature Method with aeon\n", + "# The Signature Transform\n", "\n", "The ‘signature method’ refers to a collection of feature extraction techniques for multimodal sequential data, derived from the theory of controlled differential equations. In recent years, a large number of modifications have been suggested to the signature method so as to improve some aspect of it.\n", "\n", @@ -72,9 +72,9 @@ "The signature is a natural tool to apply in problems related to time-series analysis. As described above it can convert multi-dimensional time-series data into static features that represent information about the sequential nature of the time-series, that can be fed through a standard machine learning model.\n", "\n", "A simplistic view of how this works is as follows:\n", - "\\begin{equation}\n", + "```{math}\n", " \\text{Model}(\\text{Signature}(\\text{Sequential data}))) = \\text{Predictions}\n", - "\\end{equation}" + "```" ] }, { From 2b80e38ba1e172065b520efff1888507df0839e0 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 14:56:45 +0100 Subject: [PATCH 07/19] decalre in init --- .../collection/signature_based/_signature_method.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aeon/transformations/collection/signature_based/_signature_method.py b/aeon/transformations/collection/signature_based/_signature_method.py index a618011ef3..a313402db4 100644 --- a/aeon/transformations/collection/signature_based/_signature_method.py +++ b/aeon/transformations/collection/signature_based/_signature_method.py @@ -39,7 +39,7 @@ class SignatureTransformer(BaseCollectionTransformer): Attributes ---------- - sklearn.Pipeline + self.signature_method_ : sklearn.Pipeline sklearn pipeline object that contains all the steps to extract the signature features. """ @@ -69,6 +69,7 @@ def __init__( self.rescaling = rescaling self.sig_tfm = sig_tfm self.depth = depth + self.signature_method_ = None super().__init__() @@ -85,7 +86,7 @@ def _fit(self, X, y=None): rescaling=self.rescaling, ) - # The so-called 'signature method' as defined in the reference paper + # 'signature method' as defined in the reference paper self.signature_method_ = Pipeline( [ ("augmentations", augmentation_step), From 5fd2cd7306e6a2ae98181111a2cfc6a447737be4 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 15:15:03 +0100 Subject: [PATCH 08/19] switch classifier to store SignatureTransformer --- aeon/classification/feature_based/_signature_classifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aeon/classification/feature_based/_signature_classifier.py b/aeon/classification/feature_based/_signature_classifier.py index 561f5f60c8..338f17a974 100644 --- a/aeon/classification/feature_based/_signature_classifier.py +++ b/aeon/classification/feature_based/_signature_classifier.py @@ -139,7 +139,7 @@ def __init__( rescaling, sig_tfm, depth, - ).signature_method + ) self.pipeline = None def _setup_classification_pipeline(self): From c3b8ca1d0d0eb045d635bebe232541a98bba4a6a Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 15:23:44 +0100 Subject: [PATCH 09/19] revert classifier --- aeon/classification/feature_based/_signature_classifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aeon/classification/feature_based/_signature_classifier.py b/aeon/classification/feature_based/_signature_classifier.py index 338f17a974..561f5f60c8 100644 --- a/aeon/classification/feature_based/_signature_classifier.py +++ b/aeon/classification/feature_based/_signature_classifier.py @@ -139,7 +139,7 @@ def __init__( rescaling, sig_tfm, depth, - ) + ).signature_method self.pipeline = None def _setup_classification_pipeline(self): From c4d724086c52759b5ec459f8d4bcd6a9d9c0a6e3 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 15:24:31 +0100 Subject: [PATCH 10/19] revert transformer --- .../signature_based/_signature_method.py | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/aeon/transformations/collection/signature_based/_signature_method.py b/aeon/transformations/collection/signature_based/_signature_method.py index a313402db4..8606fd84fc 100644 --- a/aeon/transformations/collection/signature_based/_signature_method.py +++ b/aeon/transformations/collection/signature_based/_signature_method.py @@ -19,29 +19,24 @@ class SignatureTransformer(BaseCollectionTransformer): Parameters ---------- - augmentation_list : tuple of strings, default = ``("basepoint", "addtime")`` - Contains the augmentations to be applied before application of the signature - transform. - window_name : str - The name of the window transform to apply. - window_depth : int - The depth of the dyadic window. (Active only if ``window_name == 'dyadic'``). - window_length : int - The length of the sliding/expanding window. (Active only if ``window_name`` - in ``['sliding, 'expanding']``. - window_step : int - The step of the sliding/expanding window. (Active + augmentation_list: tuple of strings, contains the augmentations to be + applied before application of the signature transform. + window_name: str, The name of the window transform to apply. + window_depth: int, The depth of the dyadic window. (Active only if + `window_name == 'dyadic'`). + window_length: int, The length of the sliding/expanding window. (Active only if `window_name in ['sliding, 'expanding']`. - rescaling : str or None, The method of signature rescaling. - sig_tfm : str, String to specify the type of signature transform. One of: + window_step: int, The step of the sliding/expanding window. (Active + only if `window_name in ['sliding, 'expanding']`. + rescaling: str or None, The method of signature rescaling. + sig_tfm: str, String to specify the type of signature transform. One of: ['signature', 'logsignature']). depth: int, Signature truncation depth. Attributes ---------- - self.signature_method_ : sklearn.Pipeline - sklearn pipeline object that contains all the steps to extract the signature - features. + signature_method: sklearn.Pipeline, A sklearn pipeline object that contains + all the steps to extract the signature features. """ _tags = { @@ -69,11 +64,11 @@ def __init__( self.rescaling = rescaling self.sig_tfm = sig_tfm self.depth = depth - self.signature_method_ = None super().__init__() + self.setup_feature_pipeline() - def _fit(self, X, y=None): + def setup_feature_pipeline(self): """Set up the signature method as an sklearn pipeline.""" augmentation_step = _make_augmentation_pipeline(self.augmentation_list) transform_step = _WindowSignatureTransform( @@ -86,18 +81,20 @@ def _fit(self, X, y=None): rescaling=self.rescaling, ) - # 'signature method' as defined in the reference paper - self.signature_method_ = Pipeline( + # The so-called 'signature method' as defined in the reference paper + self.signature_method = Pipeline( [ ("augmentations", augmentation_step), ("window_and_transform", transform_step), ] ) - self.signature_method_.fit(X) + + def _fit(self, X, y=None): + self.signature_method.fit(X) return self def _transform(self, X, y=None): - return self.signature_method_.transform(X) + return self.signature_method.transform(X) @classmethod def _get_test_params(cls, parameter_set="default"): From 03fe462c3728dcb63ec3887c5191eb4947a9be06 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 15:42:41 +0100 Subject: [PATCH 11/19] embed image rather than link --- examples/transformations/signature_method.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 96c08d69dd..33374b68ce 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -49,7 +49,7 @@ "### A Visualisation\n", "To give an idea of what the signature terms represent physically, we consider a patient in an ICU where we are tracking their systolic blood pressure (SBP) and heart rate (HR) changing in time. This can be represented as a path in $\\mathbb{R}^3$ (assuming time is included as a channel).\n", "\n", - "[signature_visualisation](img/signature.png)\n", + "\n", "\n", "The plot above sketches two scenarios of how such a path might look. We are assuming here an implicit time dimension for each plot such that the path is traversed from left to right along the blue line.\n", "\n", From f0b75008bfd357d18959a2270d0e27b7431385a2 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 15:59:25 +0100 Subject: [PATCH 12/19] equation --- examples/transformations/signature_method.ipynb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 33374b68ce..be6c4869cd 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -26,10 +26,11 @@ "\n", "The **signature transform** $S$ of a path $X$ is defined as an infinite sequence of values:\n", "\n", - "```{math}\n", - "S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d,\n", - "S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)\n", - "```\n", + "\n", + "$$S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d$$\n", + "\n", + "$$S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)$$\n", + "\n", "\n", "where each term is a $k$-fold iterated integral of $X$ with multi-index $i_1,...,i_k$:\n", "\n", From f2647565a1fac49606233a1853408712e98b55a0 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 15:59:47 +0100 Subject: [PATCH 13/19] equation --- examples/transformations/signature_method.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index be6c4869cd..703d16e27d 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -36,10 +36,10 @@ "\n", "The **signature transform** $S$ of a path $X$ is defined as an infinite sequence of values:\n", "\n", - "```{math}\n", - "S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d,\n", - "S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)\n", - "```\n", + "$$S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d$$\n", + "\n", + "$$S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)$$\n", + "\n", "This defines a graded sequence of numbers associated with a path which is known to characterise it up to a generalised form of reparameterisation [2]. One can think of the signature as a collection of summary statistics that determine a path (almost) uniquely. Furthermore, any continuous function on the path $X$ can be approximated arbitrarily well as a linear function on its signature [3]; the signature unravels the non-linearities on functions on the space of unparameterised paths." ] }, From a15da38243883c60f0aa2a8900fcc9bfa455e48a Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 16:27:19 +0100 Subject: [PATCH 14/19] remove tests --- .../signature_based/tests/test_signatures.py | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 aeon/transformations/collection/signature_based/tests/test_signatures.py diff --git a/aeon/transformations/collection/signature_based/tests/test_signatures.py b/aeon/transformations/collection/signature_based/tests/test_signatures.py deleted file mode 100644 index 2b459ee512..0000000000 --- a/aeon/transformations/collection/signature_based/tests/test_signatures.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Test signatures helper functions.""" - -import numpy as np - -from aeon.transformations.collection.signature_based._rescaling import ( - _rescale_path, - _rescale_signature, -) - - -def test_rescale_path(): - """Test rescale_path function.""" - X = np.random.random((10, 2, 40)) - data = np.swapaxes(X, 1, 2) - trans = _rescale_path(data, 1) - assert isinstance(trans, np.ndarray) - - -def test_rescale_signature(): - """Test rescale_signatures.""" - X = np.random.random((10, 2, 40)) - data = np.swapaxes(X, 1, 2) - trans = _rescale_signature(data, 1, depth=2) - assert isinstance(trans, np.ndarray) From 14ea1918cc0c466001ef5b86dbd1f59fb704fcbe Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 16:57:21 +0100 Subject: [PATCH 15/19] maths --- examples/transformations/signature_method.ipynb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 703d16e27d..b4341545e2 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -27,9 +27,13 @@ "The **signature transform** $S$ of a path $X$ is defined as an infinite sequence of values:\n", "\n", "\n", - "$$S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d$$\n", + "$$\n", + "S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d\n", + "$$\n", "\n", - "$$S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)$$\n", + "$$\n", + "S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)\n", + "$$\n", "\n", "\n", "where each term is a $k$-fold iterated integral of $X$ with multi-index $i_1,...,i_k$:\n", From 661b4828909ec71bab8395a976dd628c2ba55b2e Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 17:11:08 +0100 Subject: [PATCH 16/19] maths --- examples/transformations/signature_method.ipynb | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index b4341545e2..4e91fc93b5 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -28,21 +28,13 @@ "\n", "\n", "$$\n", - "S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d\n", - "$$\n", - "\n", - "$$\n", - "S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)\n", + "S(X)_{a, b} = (1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d, S(X)_{a,b}^{1,\n", + " 1}, S(X)_{a,b}^{1, 2}, \\ldots)\n", "$$\n", "\n", "\n", "where each term is a $k$-fold iterated integral of $X$ with multi-index $i_1,...,i_k$:\n", "\n", - "The **signature transform** $S$ of a path $X$ is defined as an infinite sequence of values:\n", - "\n", - "$$S(X)_{a, b} = \\left(1, S(X)_{a, b}^1, S(X)_{a, b}^2, \\ldots, S(X)_{a, b}^d$$\n", - "\n", - "$$S(X)_{a,b}^{1, 1}, S(X)_{a,b}^{1, 2}, \\ldots\\right)$$\n", "\n", "This defines a graded sequence of numbers associated with a path which is known to characterise it up to a generalised form of reparameterisation [2]. One can think of the signature as a collection of summary statistics that determine a path (almost) uniquely. Furthermore, any continuous function on the path $X$ can be approximated arbitrarily well as a linear function on its signature [3]; the signature unravels the non-linearities on functions on the space of unparameterised paths." ] From 55d9b21e079d15417330bf45130919cd9815df53 Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 17:20:27 +0100 Subject: [PATCH 17/19] add eq --- examples/transformations/signature_method.ipynb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 4e91fc93b5..2f8b9c7953 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -35,6 +35,9 @@ "\n", "where each term is a $k$-fold iterated integral of $X$ with multi-index $i_1,...,i_k$:\n", "\n", + "$$\n", + "S(X)_{a, b}^{i_1,...,i_k} = \\int_{a Date: Sat, 12 Jul 2025 17:33:35 +0100 Subject: [PATCH 18/19] add eq --- examples/transformations/signature_method.ipynb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 2f8b9c7953..54114aee69 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -4,11 +4,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# The Signature Transform\n", + "# The Signature Method\n", "\n", "The ‘signature method’ refers to a collection of feature extraction techniques for multimodal sequential data, derived from the theory of controlled differential equations. In recent years, a large number of modifications have been suggested to the signature method so as to improve some aspect of it.\n", "\n", - "In the paper [\"A Generalised Signature Method for Time-Series\"](https://arxiv.org/abs/2006.00873) [1] the authors collated the vast majority of these modifications into a single document and ran a large hyper-parameter study over the multivariate UEA datasets to build a generic signature algorithm that is expected to work well on a wide range of datasets. We implement the best practice results from this study as the default starting values for our hyperparameters in the `SignatureClassifier` module.\n" + "In the paper \n", + "[\"A Generalised Signature Method for Time-Series\"](https://arxiv.org/abs/2006.00873) [1] the authors collated the vast majority of these \n", + "modifications into a single document and ran a large hyper-parameter study over the \n", + "multivariate UEA datasets to build a generic signature algorithm that is expected to \n", + "work well on a wide range of datasets. We implement the best practice results from \n", + "this study as the default starting values for our hyperparameters in the \n", + "`SignatureClassifier` estimator.\n", + "\n", + "There is a good introduction to signatures \n", + "[here](https://medium.com/@ti.tomhortons/intuitive-understandings-of-signature-method-and-practical-examples-in-machine-learning-4586ecf24926)." ] }, { From b4b2a36dcd49eda7aab67872ed976eacc217e3cd Mon Sep 17 00:00:00 2001 From: Tony Bagnall Date: Sat, 12 Jul 2025 18:14:17 +0100 Subject: [PATCH 19/19] remove example --- .../transformations/signature_method.ipynb | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/examples/transformations/signature_method.ipynb b/examples/transformations/signature_method.ipynb index 54114aee69..92b763526b 100644 --- a/examples/transformations/signature_method.ipynb +++ b/examples/transformations/signature_method.ipynb @@ -15,9 +15,7 @@ "work well on a wide range of datasets. We implement the best practice results from \n", "this study as the default starting values for our hyperparameters in the \n", "`SignatureClassifier` estimator.\n", - "\n", - "There is a good introduction to signatures \n", - "[here](https://medium.com/@ti.tomhortons/intuitive-understandings-of-signature-method-and-practical-examples-in-machine-learning-4586ecf24926)." + "\n" ] }, { @@ -55,22 +53,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### A Visualisation\n", - "To give an idea of what the signature terms represent physically, we consider a patient in an ICU where we are tracking their systolic blood pressure (SBP) and heart rate (HR) changing in time. This can be represented as a path in $\\mathbb{R}^3$ (assuming time is included as a channel).\n", - "\n", - "\n", - "\n", - "The plot above sketches two scenarios of how such a path might look. We are assuming here an implicit time dimension for each plot such that the path is traversed from left to right along the blue line.\n", - "\n", - "#### Depth 1:\n", - "The signature terms to depth 1 are simply the changes of each of the variables over the interval, in the image this is the $\\Delta \\text{HR}$ and $\\Delta \\text{SBP}$ terms. Note that these values are the same in each case.\n", - "\n", - "#### Depth 2:\n", - "The second level gives us the signed areas (the shaded orange regions), where the orientation of the left most plot is such that the negatively signed area is produced whereas the second gives the positive value, and thus, at order 2 in the signature we now have sufficient information to discriminate between these two situations where in the first rise in heart rate occurs before (or at least, initially faster than) the rise in blood pressure, and vice versa.\n", "\n", + "There is a good introduction to signatures \n", + "[here](https://medium.com/@ti.tomhortons/intuitive-understandings-of-signature-method-and-practical-examples-in-machine-learning-4586ecf24926).\n", "\n", - "#### Depth > 2:\n", - "Depths larger than 2 become more difficult to visualise graphically, however the idea is similar to that of the depth 2 case where we saw that the signature produced information on whether the increase in HR or SBP appeared to be happening first, along with some numerical quantification of how much this was happening. At higher orders the signature is doing something similar, but now with three events, rather than two. The signature picks out structural information regarding the order in which events occur." + "James Morell contributed this code as part of his \n", + "[PhD thesis](https://ora.ox.ac.uk/objects/uuid:44cb30f8-6dc8-4e0e-8347-14d40452c3e6/files/d8049g5436) \n" ] }, {