From eccd89916a6522f7fca3859322d0543885378f77 Mon Sep 17 00:00:00 2001 From: code2x Date: Thu, 23 Jan 2025 01:29:22 +0500 Subject: [PATCH 01/25] Add example notebook for using aeon distances with sklearn clusterers --- ...learn_clustering_with_aeon_distances.ipynb | 274 ++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 examples/clustering/sklearn_clustering_with_aeon_distances.ipynb diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb new file mode 100644 index 0000000000..f6e3794fc9 --- /dev/null +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -0,0 +1,274 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# **Using aeon Distances with scikit-learn Clusterers**\n", + "\n", + "This notebook demonstrates how to integrate aeon’s distance metrics with hierarchical, density-based, and spectral clustering methods from scikit-learn. While aeon primarily supports partition-based clustering algorithms, such as $k$-means and $k$-medoids, its robust distance measures can be leveraged to enable other clustering techniques using scikit-learn.\n", + "\n", + "Broadly, clustering algorithms can be categorized into partition-based, hierarchical, density-based, and spectral methods. In this notebook, we focus on using aeon’s distance metrics with:\n", + "1. **Hierarchical clustering**: `AgglomerativeClustering` with `metric=\"precomputed\"`.\n", + "2. **Density-based clustering**: `DBSCAN` and `OPTICS` with `metric=\"precomputed\"`.\n", + "3. **Spectral clustering**: `SpectralClustering` with `affinity=\"precomputed\"` and the inverse of the distance matrix.\n", + "\n", + "To measure similarity between time series and enable clustering, we use aeon’s precomputed distance matrices. For details about distance metrics, see the [distance examples](../distances/distances.ipynb).\n", + "\n", + "## **Contents**\n", + "1. **Introduction**: Overview of clustering methods and motivation for this notebook.\n", + "2. **Loading Data**: Using the `load_unit_test` dataset from aeon.\n", + "3. **Computing Distance Matrices with aeon**: Precomputing distance matrices with aeon’s distance metrics.\n", + "\n", + "4. **Hierarchical Clustering**\n", + " 4.1 sklearn.cluster.AgglomerativeClustering with metric=\"precomputed\"\n", + "\n", + "5. **Density-Based Clustering**\n", + " 5.1 sklearn.cluster.DBSCAN with metric=\"precomputed\"\n", + " 5.2 sklearn.cluster.OPTICS with metric=\"precomputed\"\n", + "\n", + "6. **Spectral Clustering**\n", + " 6.1 sklearn.cluster.SpectralClustering with affinity=\"precomputed\"\n", + " 6.2 Using the Inverse of the Distance Matrix\n", + "\n", + "## **Introduction**\n", + "\n", + "While aeon primarily focuses on partition-based clustering methods, it's possible to extend its capabilities by integrating its distance metrics with scikit-learn's clustering algorithms. This approach allows us to perform hierarchical, density-based, and spectral clustering on time series data using aeon's rich set of distance measures.\n", + "\n", + "## **Loading Data**\n", + "\n", + "We'll begin by loading a sample dataset. For this demonstration, we'll use the `load_unit_test` dataset from aeon." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Import & load data\n", + "from aeon.datasets import load_unit_test\n", + "X_train, y_train = load_unit_test(split=\"train\")\n", + "X_test, y_test = load_unit_test(split=\"test\")\n", + "\n", + "# For simplicity, we'll work with the training data\n", + "X = X_train\n", + "y = y_train\n", + "\n", + "print(f\"Data shape: {X.shape}\")\n", + "print(f\"Labels shape: {y.shape}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Computing Distance Matrices with aeon**\n", + "Aeon provides a variety of distance measures suitable for time series data. We'll compute the distance matrix using the Dynamic Time Warping (DTW) distance as an example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from aeon.distances import pairwise_distance\n", + "\n", + "# Compute the pairwise distance matrix using DTW\n", + "distance_matrix = pairwise_distance(X, metric=\"dtw\")\n", + "\n", + "print(f\"Distance matrix shape: {distance_matrix.shape}\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Hierarchical Clustering**\n", + "Hierarchical clustering builds a hierarchy of clusters either by progressively merging or splitting existing clusters. We'll use scikit-learn's AgglomerativeClustering with the precomputed distance matrix." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.cluster import AgglomerativeClustering\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "# Perform Agglomerative Clustering\n", + "agg_clustering = AgglomerativeClustering(\n", + " n_clusters=2, affinity=\"precomputed\", linkage=\"average\"\n", + ")\n", + "labels = agg_clustering.fit_predict(distance_matrix)\n", + "\n", + "# Visualize the clustering results\n", + "plt.figure(figsize=(10, 6))\n", + "for label in np.unique(labels):\n", + " plt.plot(X[labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", + "plt.title(\"Hierarchical Clustering with DTW Distance\")\n", + "plt.legend()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Density-Based Clustering**\n", + "Density-based clustering identifies clusters based on the density of data points in the feature space. We'll demonstrate this using scikit-learn's `DBSCAN` and `OPTICS` algorithms." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### **DBSCAN**\n", + "\n", + "DBSCAN is a density-based clustering algorithm that groups data points based on their density connectivity. \n", + "We use the `DBSCAN` algorithm from scikit-learn with a precomputed distance matrix.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.cluster import DBSCAN\n", + "\n", + "# Perform DBSCAN clustering\n", + "dbscan = DBSCAN(eps=0.5, min_samples=5, metric=\"precomputed\")\n", + "dbscan_labels = dbscan.fit_predict(distance_matrix)\n", + "\n", + "# Visualize the clustering results\n", + "plt.figure(figsize=(10, 6))\n", + "for label in np.unique(dbscan_labels):\n", + " if label == -1:\n", + " # Noise points\n", + " plt.plot(X[dbscan_labels == label].mean(axis=0), label=\"Noise\", linestyle=\"--\")\n", + " else:\n", + " plt.plot(X[dbscan_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", + "plt.title(\"DBSCAN Clustering with DTW Distance\")\n", + "plt.legend()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### **OPTICS**\n", + "OPTICS is a density-based clustering algorithm similar to DBSCAN but provides better handling of varying \n", + "densities. We use the `OPTICS` algorithm from scikit-learn with a precomputed distance matrix." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.cluster import OPTICS\n", + "\n", + "# Perform OPTICS clustering\n", + "optics = OPTICS(min_samples=5, metric=\"precomputed\")\n", + "optics_labels = optics.fit_predict(distance_matrix)\n", + "\n", + "# Visualize the clustering results\n", + "plt.figure(figsize=(10, 6))\n", + "for label in np.unique(optics_labels):\n", + " if label == -1:\n", + " # Noise points\n", + " plt.plot(X[optics_labels == label].mean(axis=0), label=\"Noise\", linestyle=\"--\")\n", + " else:\n", + " plt.plot(X[optics_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", + "plt.title(\"OPTICS Clustering with DTW Distance\")\n", + "plt.legend()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Spectral Clustering**\n", + "Spectral clustering performs dimensionality reduction on the data before clustering in fewer dimensions. It requires a similarity matrix, so we'll convert our distance matrix accordingly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.cluster import SpectralClustering\n", + "import numpy as np\n", + "\n", + "# Ensure the distance matrix does not contain zeros on the diagonal or elsewhere\n", + "# Now adding a small constant to avoid division by zero\n", + "epsilon = 1e-10\n", + "inverse_distance_matrix = 1 /(distance_matrix + epsilon)\n", + "\n", + "# Perform Spectral Clustering with affinity=\"precomputed\"\n", + "spectral = SpectralClustering(\n", + " n_clusters=2, affinity=\"precomputed\", random_state=42\n", + ")\n", + "spectral_labels = spectral.fit_predict(inverse_distance_matrix)\n", + "\n", + "# Visualising the clustering results\n", + "plt.figure(figsize=(10, 6))\n", + "for label in np.unique(spectral_labels):\n", + " plt.plot(X[spectral_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", + "plt.title(\"Spectral Clustering with Inverse Distance Matrix\")\n", + "plt.legend()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **References**\n", + "\n", + "[1] Christopher Holder, Matthew Middlehurst, and Anthony Bagnall. A Review and Evaluation of Elastic Distance Functions for Time Series Clustering, Knowledge and Information Systems. In Press (2023).\n", + "\n", + "[2] Christopher Holder, David Guijo-Rubio, and Anthony Bagnall. Barycentre averaging for the move-split-merge time series distance measure. 15th International Joint Conference on Knowledge Discovery, Knowledge Engineering and Knowledge Management (2023).\n", + "\n", + "[3] Kaufman, Leonard & Rousseeuw, Peter. (1986). Clustering Large Data Sets. 10.1016/B978-0-444-87877-9.50039-X.\n", + "\n", + "[4] R. T. Ng and Jiawei Han. \"CLARANS: a method for clustering objects spatial data mining.\" IEEE Transactions on Knowledge and Data Engineering vol. 14, no. 5, pp. 1003-1016, Sept.-Oct. 2002, doi: 10.1109/TKDE.2002.1033770.\n", + "\n", + "[5] Paparrizos, John, and Luis Gravano. \"Fast and Accurate Time-Series Clustering.\" ACM Transactions on Database Systems 42, no. 2 (2017): 8:1-8:49.\n", + "\n", + "[6] F. Petitjean, A. Ketterlin and P. Gancarski. “A global averaging method for dynamic time warping, with applications to clustering,” Pattern Recognition, vol. 44, pp. 678-693, 2011.\n", + "\n", + "Generated using [nbsphinx](https://nbsphinx.readthedocs.io/). The Jupyter notebook can be found here[here](sklearn_clustering_with_aeon_distances.html)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 714be2851fa4d3eb4e650e8ea1395e85df69514d Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 26 Jan 2025 21:40:32 +0500 Subject: [PATCH 02/25] Resolved conflicts and updated notebook: - Removed "metric=..." details from TOC and introduction. - Renamed "Loading Data" to "Example Dataset." - Deleted redundant Introduction section. --- ...learn_clustering_with_aeon_distances.ipynb | 32 ++++--------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index f6e3794fc9..a17439558d 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -8,36 +8,18 @@ "\n", "This notebook demonstrates how to integrate aeon’s distance metrics with hierarchical, density-based, and spectral clustering methods from scikit-learn. While aeon primarily supports partition-based clustering algorithms, such as $k$-means and $k$-medoids, its robust distance measures can be leveraged to enable other clustering techniques using scikit-learn.\n", "\n", - "Broadly, clustering algorithms can be categorized into partition-based, hierarchical, density-based, and spectral methods. In this notebook, we focus on using aeon’s distance metrics with:\n", - "1. **Hierarchical clustering**: `AgglomerativeClustering` with `metric=\"precomputed\"`.\n", - "2. **Density-based clustering**: `DBSCAN` and `OPTICS` with `metric=\"precomputed\"`.\n", - "3. **Spectral clustering**: `SpectralClustering` with `affinity=\"precomputed\"` and the inverse of the distance matrix.\n", - "\n", "To measure similarity between time series and enable clustering, we use aeon’s precomputed distance matrices. For details about distance metrics, see the [distance examples](../distances/distances.ipynb).\n", "\n", "## **Contents**\n", - "1. **Introduction**: Overview of clustering methods and motivation for this notebook.\n", - "2. **Loading Data**: Using the `load_unit_test` dataset from aeon.\n", - "3. **Computing Distance Matrices with aeon**: Precomputing distance matrices with aeon’s distance metrics.\n", - "\n", - "4. **Hierarchical Clustering**\n", - " 4.1 sklearn.cluster.AgglomerativeClustering with metric=\"precomputed\"\n", - "\n", - "5. **Density-Based Clustering**\n", - " 5.1 sklearn.cluster.DBSCAN with metric=\"precomputed\"\n", - " 5.2 sklearn.cluster.OPTICS with metric=\"precomputed\"\n", - "\n", - "6. **Spectral Clustering**\n", - " 6.1 sklearn.cluster.SpectralClustering with affinity=\"precomputed\"\n", - " 6.2 Using the Inverse of the Distance Matrix\n", - "\n", - "## **Introduction**\n", - "\n", - "While aeon primarily focuses on partition-based clustering methods, it's possible to extend its capabilities by integrating its distance metrics with scikit-learn's clustering algorithms. This approach allows us to perform hierarchical, density-based, and spectral clustering on time series data using aeon's rich set of distance measures.\n", + "1. **Example Dataset**: Using the `load_unit_test` dataset from aeon.\n", + "2. **Computing Distance Matrices with aeon**: Precomputing distance matrices with aeon’s distance metrics.\n", + "3. **Hierarchical Clustering**\n", + "4. **Density-Based Clustering**\n", + "5. **Spectral Clustering**\n", "\n", - "## **Loading Data**\n", + "## **Example Dataset**\n", "\n", - "We'll begin by loading a sample dataset. For this demonstration, we'll use the `load_unit_test` dataset from aeon." + "We'll begin by loading a sample dataset. For this demonstration, we'll use the `load_unit_test` dataset from aeon.\n" ] }, { From fd26c31bde72f63187fe7d00832bb3ab8d830c3e Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 26 Jan 2025 21:52:05 +0500 Subject: [PATCH 03/25] Simplified dataset loading using `load_unit_test(split="train")` as suggested. --- .../sklearn_clustering_with_aeon_distances.ipynb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index a17439558d..02d7a97a12 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -30,15 +30,10 @@ "source": [ "# Import & load data\n", "from aeon.datasets import load_unit_test\n", - "X_train, y_train = load_unit_test(split=\"train\")\n", - "X_test, y_test = load_unit_test(split=\"test\")\n", - "\n", - "# For simplicity, we'll work with the training data\n", - "X = X_train\n", - "y = y_train\n", + "X, y = load_unit_test(split=\"train\")\n", "\n", "print(f\"Data shape: {X.shape}\")\n", - "print(f\"Labels shape: {y.shape}\")" + "print(f\"Labels shape: {y.shape}\")\n" ] }, { From 450b0ccad1984f5b69d2ec410364feb85ffe52a0 Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 26 Jan 2025 22:01:44 +0500 Subject: [PATCH 04/25] Added this sentence after the introductory line: "For a comprehensive overview of all available distance metrics in aeon, see the aeon distances API reference." --- .../clustering/sklearn_clustering_with_aeon_distances.ipynb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 02d7a97a12..6e17c0d72e 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -41,7 +41,10 @@ "metadata": {}, "source": [ "## **Computing Distance Matrices with aeon**\n", - "Aeon provides a variety of distance measures suitable for time series data. We'll compute the distance matrix using the Dynamic Time Warping (DTW) distance as an example." + "\n", + "Aeon provides a variety of distance measures suitable for time series data. We'll compute the distance matrix using the Dynamic Time Warping (DTW) distance as an example.\n", + "\n", + "For a comprehensive overview of all available distance metrics in aeon, see the [aeon distances API reference](https://www.aeon-toolkit.org/en/stable/api_reference/distances.html).\n" ] }, { From 49d8e66ec85921e8e2f50c562d737ce6b056c08b Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 26 Jan 2025 22:11:44 +0500 Subject: [PATCH 05/25] Changes made:- "AgglomerativeClustering is, as the name suggests, an agglomerative approach that works by merging clusters bottom-up." Clarified Supported Linkage Methods: Included the supported linkage methods (single, complete, average, weighted) for precomputed distance matrices. --- .../sklearn_clustering_with_aeon_distances.ipynb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 6e17c0d72e..0e2ff38ccc 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -66,7 +66,16 @@ "metadata": {}, "source": [ "## **Hierarchical Clustering**\n", - "Hierarchical clustering builds a hierarchy of clusters either by progressively merging or splitting existing clusters. We'll use scikit-learn's AgglomerativeClustering with the precomputed distance matrix." + "\n", + "AgglomerativeClustering is, as the name suggests, an agglomerative approach that works by merging clusters bottom-up. \n", + "\n", + "Hierarchical clustering builds a hierarchy of clusters either by progressively merging or splitting existing clusters. We'll use scikit-learn's AgglomerativeClustering with the precomputed distance matrix.\n", + "\n", + "Not all linkage methods can be used with a precomputed distance matrix. The following linkage methods work with aeon distances:\n", + "- `single`\n", + "- `complete`\n", + "- `average`\n", + "- `weighted`" ] }, { @@ -91,7 +100,7 @@ " plt.plot(X[labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", "plt.title(\"Hierarchical Clustering with DTW Distance\")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { From 1ce463e4ba189395a78c91a099ebd55c57dccd62 Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 26 Jan 2025 22:21:11 +0500 Subject: [PATCH 06/25] Added links to the scikit-learn documentation pages for all referenced estimators. --- .../sklearn_clustering_with_aeon_distances.ipynb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 0e2ff38ccc..9b123b9cd5 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -67,7 +67,10 @@ "source": [ "## **Hierarchical Clustering**\n", "\n", - "AgglomerativeClustering is, as the name suggests, an agglomerative approach that works by merging clusters bottom-up. \n", + "## **Hierarchical Clustering**\n", + "\n", + "[AgglomerativeClustering](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.AgglomerativeClustering.html) is, as the name suggests, an agglomerative approach that works by merging clusters bottom-up. \n", + " \n", "\n", "Hierarchical clustering builds a hierarchy of clusters either by progressively merging or splitting existing clusters. We'll use scikit-learn's AgglomerativeClustering with the precomputed distance matrix.\n", "\n", @@ -117,7 +120,7 @@ "source": [ "### **DBSCAN**\n", "\n", - "DBSCAN is a density-based clustering algorithm that groups data points based on their density connectivity. \n", + "[DBSCAN](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html) is a density-based clustering algorithm that groups data points based on their density connectivity. \n", "We use the `DBSCAN` algorithm from scikit-learn with a precomputed distance matrix.\n" ] }, @@ -151,7 +154,7 @@ "metadata": {}, "source": [ "### **OPTICS**\n", - "OPTICS is a density-based clustering algorithm similar to DBSCAN but provides better handling of varying \n", + "[DBSCAN](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html) is a density-based clustering algorithm similar to DBSCAN but provides better handling of varying \n", "densities. We use the `OPTICS` algorithm from scikit-learn with a precomputed distance matrix." ] }, @@ -185,7 +188,7 @@ "metadata": {}, "source": [ "## **Spectral Clustering**\n", - "Spectral clustering performs dimensionality reduction on the data before clustering in fewer dimensions. It requires a similarity matrix, so we'll convert our distance matrix accordingly." + "[SpectralClustering](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.SpectralClustering.html) performs dimensionality reduction on the data before clustering in fewer dimensions. It requires a similarity matrix, so we'll convert our distance matrix accordingly." ] }, { From fb04db03b9ab0604b71ca2996f4db6e8d2f32bc7 Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 26 Jan 2025 22:26:50 +0500 Subject: [PATCH 07/25] Updated distance-to-similarity conversion to normalize distances and subtract from 1, ensuring proper preservation of distance distribution. --- .../sklearn_clustering_with_aeon_distances.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 9b123b9cd5..4645653080 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -199,11 +199,11 @@ "source": [ "from sklearn.cluster import SpectralClustering\n", "import numpy as np\n", + "import matplotlib.pyplot as plt\n", "\n", "# Ensure the distance matrix does not contain zeros on the diagonal or elsewhere\n", - "# Now adding a small constant to avoid division by zero\n", - "epsilon = 1e-10\n", - "inverse_distance_matrix = 1 /(distance_matrix + epsilon)\n", + "# Normalize distance values to [0, 1] and convert to similarities\n", + "inverse_distance_matrix = 1 - (distance_matrix / distance_matrix.max())\n", "\n", "# Perform Spectral Clustering with affinity=\"precomputed\"\n", "spectral = SpectralClustering(\n", @@ -215,7 +215,7 @@ "plt.figure(figsize=(10, 6))\n", "for label in np.unique(spectral_labels):\n", " plt.plot(X[spectral_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", - "plt.title(\"Spectral Clustering with Inverse Distance Matrix\")\n", + "plt.title(\"Spectral Clustering with Normalized Similarity Matrix\")\n", "plt.legend()\n", "plt.show()\n" ] From 0c3435b086b93a8510e3dd37e761a3a8fe4af525 Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 26 Jan 2025 22:36:34 +0500 Subject: [PATCH 08/25] Removed the references section as it was not cited in the notebook, per feedback. --- ...klearn_clustering_with_aeon_distances.ipynb | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 4645653080..eb5b2f36ab 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -223,23 +223,7 @@ { "cell_type": "markdown", "metadata": {}, - "source": [ - "## **References**\n", - "\n", - "[1] Christopher Holder, Matthew Middlehurst, and Anthony Bagnall. A Review and Evaluation of Elastic Distance Functions for Time Series Clustering, Knowledge and Information Systems. In Press (2023).\n", - "\n", - "[2] Christopher Holder, David Guijo-Rubio, and Anthony Bagnall. Barycentre averaging for the move-split-merge time series distance measure. 15th International Joint Conference on Knowledge Discovery, Knowledge Engineering and Knowledge Management (2023).\n", - "\n", - "[3] Kaufman, Leonard & Rousseeuw, Peter. (1986). Clustering Large Data Sets. 10.1016/B978-0-444-87877-9.50039-X.\n", - "\n", - "[4] R. T. Ng and Jiawei Han. \"CLARANS: a method for clustering objects spatial data mining.\" IEEE Transactions on Knowledge and Data Engineering vol. 14, no. 5, pp. 1003-1016, Sept.-Oct. 2002, doi: 10.1109/TKDE.2002.1033770.\n", - "\n", - "[5] Paparrizos, John, and Luis Gravano. \"Fast and Accurate Time-Series Clustering.\" ACM Transactions on Database Systems 42, no. 2 (2017): 8:1-8:49.\n", - "\n", - "[6] F. Petitjean, A. Ketterlin and P. Gancarski. “A global averaging method for dynamic time warping, with applications to clustering,” Pattern Recognition, vol. 44, pp. 678-693, 2011.\n", - "\n", - "Generated using [nbsphinx](https://nbsphinx.readthedocs.io/). The Jupyter notebook can be found here[here](sklearn_clustering_with_aeon_distances.html)." - ] + "source": [] } ], "metadata": { From b03348455a176c611d40c949dbb9814f742e14ba Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 26 Jan 2025 23:39:30 +0500 Subject: [PATCH 09/25] Added a reference to the new notebook (sklearn_clustering_with_aeon_distances.ipynb) in the Clustering Overview under Clustering Notebooks. --- examples/clustering/clustering.ipynb | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/examples/clustering/clustering.ipynb b/examples/clustering/clustering.ipynb index b0e51431ea..cd0d0ae051 100644 --- a/examples/clustering/clustering.ipynb +++ b/examples/clustering/clustering.ipynb @@ -2,6 +2,9 @@ "cells": [ { "cell_type": "markdown", + "metadata": { + "collapsed": false + }, "source": [ "# Time Series Clustering\n", "\n", @@ -23,13 +26,13 @@ "erative [16], Feature K-means [17], Feature K-medoids [17], U-shapelets [18],\n", "USSL [19], RSFS [20], NDFS [21], Deep learning and dimensionality reduction\n", "approaches see [22]" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "collapsed": false + }, "source": [ "## Clustering notebooks\n", "\n", @@ -41,6 +44,8 @@ "these can be used in conjunction with `aeon` elastic distances. See the [sklearn and\n", "aeon distances](../distances/sklearn_distances.ipynb) notebook.\n", "\n", + "- For more detailed examples of using `aeon` distances with sklearn clusterers, refer to the [sklearn clustering with aeon distances](sklearn_clustering_with_aeon_distances.ipynb) notebook.\n", + "\n", "- Deep learning based TSCL is a very popular topic, and we are working on bringing\n", "deep learning functionality to `aeon`, first algorithms for [Deep learning] are\n", "COMING SOON\n", @@ -55,13 +60,13 @@ "\n", "\"cd_diag\"\n", "\n" - ], - "metadata": { - "collapsed": false - } + ] }, { "cell_type": "markdown", + "metadata": { + "collapsed": false + }, "source": [ "## References\n", "\n", @@ -141,10 +146,7 @@ "[22] B. Lafabregue, J. Weber, P. Gancarski, and G. Forestier. End-to-end deep\n", "representation learning for time series clustering: a comparative study. Data Mining\n", "and Knowledge Discovery, 36:29—-81, 2022\n" - ], - "metadata": { - "collapsed": false - } + ] } ], "metadata": { From 187e64f7f6fea490aab0c01e718b8c274316553b Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 2 Feb 2025 14:42:23 +0500 Subject: [PATCH 10/25] Updated the aeon distances API reference link to a relative link for version consistency. --- .../clustering/sklearn_clustering_with_aeon_distances.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index eb5b2f36ab..68750c62ac 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -44,7 +44,7 @@ "\n", "Aeon provides a variety of distance measures suitable for time series data. We'll compute the distance matrix using the Dynamic Time Warping (DTW) distance as an example.\n", "\n", - "For a comprehensive overview of all available distance metrics in aeon, see the [aeon distances API reference](https://www.aeon-toolkit.org/en/stable/api_reference/distances.html).\n" + "For a comprehensive overview of all available distance metrics in aeon, see the [aeon distances API reference](../api_reference/distances.html).\n" ] }, { From 60a195097224af474d50fcf24a9e953163d9006e Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 2 Feb 2025 14:48:47 +0500 Subject: [PATCH 11/25] Removed duplicate "Hierarchical Clustering" header to improve clarity and avoid confusion. --- ...klearn_clustering_with_aeon_distances.ipynb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 68750c62ac..1c609cfde3 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -65,8 +65,6 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Hierarchical Clustering**\n", - "\n", "## **Hierarchical Clustering**\n", "\n", "[AgglomerativeClustering](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.AgglomerativeClustering.html) is, as the name suggests, an agglomerative approach that works by merging clusters bottom-up. \n", @@ -83,9 +81,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'sklearn'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[1], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01msklearn\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcluster\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m AgglomerativeClustering\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mmatplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpyplot\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mplt\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mnumpy\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mnp\u001b[39;00m\n", + "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'sklearn'" + ] + } + ], "source": [ "from sklearn.cluster import AgglomerativeClustering\n", "import matplotlib.pyplot as plt\n", From 83862dccc749c0dd4f5c1d491b7ff4ce4a24bd6b Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 2 Feb 2025 15:04:01 +0500 Subject: [PATCH 12/25] Added a reference to the new notebook in the Clustering-with-sklearn.cluster section of sklearn_distances.ipynb. --- examples/distances/sklearn_distances.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/distances/sklearn_distances.ipynb b/examples/distances/sklearn_distances.ipynb index e22579828c..9388cac262 100644 --- a/examples/distances/sklearn_distances.ipynb +++ b/examples/distances/sklearn_distances.ipynb @@ -763,7 +763,8 @@ "collapsed": false }, "source": [ - "## Clustering with sklearn.cluster" + "## Clustering with sklearn.cluster\n", + "[Using aeon Distances with sklearn Clusterers](../clustering/sklearn_clustering_with_aeon_distances.ipynb)" ] }, { From 4e5addec3977e633d7f917c9e047adb9138bd48e Mon Sep 17 00:00:00 2001 From: SebastianSchmidl <10573700+SebastianSchmidl@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:28:53 +0000 Subject: [PATCH 13/25] Automatic `pre-commit` fixes --- ...learn_clustering_with_aeon_distances.ipynb | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 1c609cfde3..fce3530e26 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -30,10 +30,11 @@ "source": [ "# Import & load data\n", "from aeon.datasets import load_unit_test\n", + "\n", "X, y = load_unit_test(split=\"train\")\n", "\n", "print(f\"Data shape: {X.shape}\")\n", - "print(f\"Labels shape: {y.shape}\")\n" + "print(f\"Labels shape: {y.shape}\")" ] }, { @@ -58,7 +59,7 @@ "# Compute the pairwise distance matrix using DTW\n", "distance_matrix = pairwise_distance(X, metric=\"dtw\")\n", "\n", - "print(f\"Distance matrix shape: {distance_matrix.shape}\")\n" + "print(f\"Distance matrix shape: {distance_matrix.shape}\")" ] }, { @@ -97,9 +98,9 @@ } ], "source": [ - "from sklearn.cluster import AgglomerativeClustering\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", + "from sklearn.cluster import AgglomerativeClustering\n", "\n", "# Perform Agglomerative Clustering\n", "agg_clustering = AgglomerativeClustering(\n", @@ -156,7 +157,7 @@ " plt.plot(X[dbscan_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", "plt.title(\"DBSCAN Clustering with DTW Distance\")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { @@ -190,7 +191,7 @@ " plt.plot(X[optics_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", "plt.title(\"OPTICS Clustering with DTW Distance\")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { @@ -207,18 +208,16 @@ "metadata": {}, "outputs": [], "source": [ - "from sklearn.cluster import SpectralClustering\n", - "import numpy as np\n", "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from sklearn.cluster import SpectralClustering\n", "\n", "# Ensure the distance matrix does not contain zeros on the diagonal or elsewhere\n", "# Normalize distance values to [0, 1] and convert to similarities\n", "inverse_distance_matrix = 1 - (distance_matrix / distance_matrix.max())\n", "\n", "# Perform Spectral Clustering with affinity=\"precomputed\"\n", - "spectral = SpectralClustering(\n", - " n_clusters=2, affinity=\"precomputed\", random_state=42\n", - ")\n", + "spectral = SpectralClustering(n_clusters=2, affinity=\"precomputed\", random_state=42)\n", "spectral_labels = spectral.fit_predict(inverse_distance_matrix)\n", "\n", "# Visualising the clustering results\n", @@ -227,7 +226,7 @@ " plt.plot(X[spectral_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", "plt.title(\"Spectral Clustering with Normalized Similarity Matrix\")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { From db354698b2967828bc9ceedd4b91d287a6aa1b26 Mon Sep 17 00:00:00 2001 From: code2x Date: Tue, 4 Feb 2025 21:39:34 +0500 Subject: [PATCH 14/25] Added a reference to the new sklearn clustering notebook in the Clustering section of examples.md. --- docs/examples.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/examples.md b/docs/examples.md index 7817ea24be..457ea40129 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -165,6 +165,17 @@ Partitional TSCL ::: +:::{grid-item-card} +:img-top: examples/clustering/img/sklearn_clustering.png +:class-img-top: aeon-card-image-m +:link: /examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +:link-type: ref +:text-align: center + +Using aeon Distances with sklearn Clusterers + +::: + :::: ## Transformation From d4e57a48de06334bbac3f0fbd6f370bdb4f6659e Mon Sep 17 00:00:00 2001 From: code2x Date: Tue, 18 Feb 2025 23:04:12 +0500 Subject: [PATCH 15/25] Fix: Corrected DTW metric in aeon pairwise_distance to resolve CI jobs issue --- .../sklearn_clustering_with_aeon_distances.ipynb | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index fce3530e26..e4bb44fa86 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -57,7 +57,7 @@ "from aeon.distances import pairwise_distance\n", "\n", "# Compute the pairwise distance matrix using DTW\n", - "distance_matrix = pairwise_distance(X, metric=\"dtw\")\n", + "distance_matrix = pairwise_distance(X, metric=\"dtw_distance\")\n", "\n", "print(f\"Distance matrix shape: {distance_matrix.shape}\")" ] @@ -84,19 +84,7 @@ "cell_type": "code", "execution_count": 1, "metadata": {}, - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'sklearn'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[1], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01msklearn\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcluster\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m AgglomerativeClustering\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mmatplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpyplot\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mplt\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mnumpy\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mnp\u001b[39;00m\n", - "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'sklearn'" - ] - } - ], + "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", From b86069b712e44e568bd40b794044e5671c821fdf Mon Sep 17 00:00:00 2001 From: code2x Date: Tue, 18 Feb 2025 23:47:35 +0500 Subject: [PATCH 16/25] changing matric to method for dtw, trying to resolved the CI Jobs issue. --- .../clustering/sklearn_clustering_with_aeon_distances.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index e4bb44fa86..545fdd8026 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -57,7 +57,7 @@ "from aeon.distances import pairwise_distance\n", "\n", "# Compute the pairwise distance matrix using DTW\n", - "distance_matrix = pairwise_distance(X, metric=\"dtw_distance\")\n", + "distance_matrix = pairwise_distance(X, method='dtw')\n", "\n", "print(f\"Distance matrix shape: {distance_matrix.shape}\")" ] @@ -82,7 +82,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ From da602a4f88f5b776b30c0f0f572b01e56b382465 Mon Sep 17 00:00:00 2001 From: SalmanDeveloperz <151463017+SalmanDeveloperz@users.noreply.github.com> Date: Tue, 18 Feb 2025 18:48:17 +0000 Subject: [PATCH 17/25] Automatic `pre-commit` fixes --- .../clustering/sklearn_clustering_with_aeon_distances.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 545fdd8026..db2cf89d3a 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -57,7 +57,7 @@ "from aeon.distances import pairwise_distance\n", "\n", "# Compute the pairwise distance matrix using DTW\n", - "distance_matrix = pairwise_distance(X, method='dtw')\n", + "distance_matrix = pairwise_distance(X, method=\"dtw\")\n", "\n", "print(f\"Distance matrix shape: {distance_matrix.shape}\")" ] From df7287d8e66c05b55004a573d2a67338288c5073 Mon Sep 17 00:00:00 2001 From: code2x Date: Wed, 19 Feb 2025 00:05:35 +0500 Subject: [PATCH 18/25] Fix AgglomerativeClustering error by replacing 'affinity' with 'metric' to fix CI Job issue. --- .../clustering/sklearn_clustering_with_aeon_distances.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 545fdd8026..85057171be 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -92,17 +92,17 @@ "\n", "# Perform Agglomerative Clustering\n", "agg_clustering = AgglomerativeClustering(\n", - " n_clusters=2, affinity=\"precomputed\", linkage=\"average\"\n", + " n_clusters=2, metric=\"precomputed\", linkage=\"average\"\n", ")\n", "labels = agg_clustering.fit_predict(distance_matrix)\n", "\n", "# Visualize the clustering results\n", "plt.figure(figsize=(10, 6))\n", "for label in np.unique(labels):\n", - " plt.plot(X[labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", + " plt.plot(np.mean(X[labels == label], axis=0), label=f\"Cluster {label}\") # Fix indexing\n", "plt.title(\"Hierarchical Clustering with DTW Distance\")\n", "plt.legend()\n", - "plt.show()" + "plt.show()\n" ] }, { From 566d15df1ae3a0c4900723ee37b0fe989a2c9d34 Mon Sep 17 00:00:00 2001 From: SalmanDeveloperz <151463017+SalmanDeveloperz@users.noreply.github.com> Date: Tue, 18 Feb 2025 19:15:00 +0000 Subject: [PATCH 19/25] Automatic `pre-commit` fixes --- .../clustering/sklearn_clustering_with_aeon_distances.ipynb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 372e659580..59e107fd9b 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -99,10 +99,12 @@ "# Visualize the clustering results\n", "plt.figure(figsize=(10, 6))\n", "for label in np.unique(labels):\n", - " plt.plot(np.mean(X[labels == label], axis=0), label=f\"Cluster {label}\") # Fix indexing\n", + " plt.plot(\n", + " np.mean(X[labels == label], axis=0), label=f\"Cluster {label}\"\n", + " ) # Fix indexing\n", "plt.title(\"Hierarchical Clustering with DTW Distance\")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { From bf350354b02458f8b101438dadb43f9147949afe Mon Sep 17 00:00:00 2001 From: code2x Date: Wed, 19 Feb 2025 20:59:09 +0500 Subject: [PATCH 20/25] Added sklearn clustering example image --- examples/clustering/img/sklearn_clustering.png | Bin 0 -> 42596 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/clustering/img/sklearn_clustering.png diff --git a/examples/clustering/img/sklearn_clustering.png b/examples/clustering/img/sklearn_clustering.png new file mode 100644 index 0000000000000000000000000000000000000000..87463baf437f8767e49c8cf85ba6a4a1c96a720c GIT binary patch literal 42596 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 Date: Wed, 19 Feb 2025 16:06:34 +0000 Subject: [PATCH 21/25] Automatic `pre-commit` fixes --- .../clustering/sklearn_clustering_with_aeon_distances.ipynb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 372e659580..59e107fd9b 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -99,10 +99,12 @@ "# Visualize the clustering results\n", "plt.figure(figsize=(10, 6))\n", "for label in np.unique(labels):\n", - " plt.plot(np.mean(X[labels == label], axis=0), label=f\"Cluster {label}\") # Fix indexing\n", + " plt.plot(\n", + " np.mean(X[labels == label], axis=0), label=f\"Cluster {label}\"\n", + " ) # Fix indexing\n", "plt.title(\"Hierarchical Clustering with DTW Distance\")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { From 145d64fed3c9b64cfca25f869d997d806b19d5e8 Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 9 Mar 2025 08:09:21 +0500 Subject: [PATCH 22/25] Display notebook outputs and improve clustering accuracy - Added outputs for Spectral and Hierarchical Clustering plots. - Fixed oversight per @MatthewMiddlehurst's feedback. - Refined code for more accurate clustering results. --- ...learn_clustering_with_aeon_distances.ipynb | 157 +++++++++++++----- 1 file changed, 118 insertions(+), 39 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 372e659580..9d7687e265 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -24,9 +24,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 106, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Data shape: (20, 1, 24)\n", + "Labels shape: (20,)\n" + ] + } + ], "source": [ "# Import & load data\n", "from aeon.datasets import load_unit_test\n", @@ -50,9 +59,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 107, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Distance matrix shape: (20, 20)\n" + ] + } + ], "source": [ "from aeon.distances import pairwise_distance\n", "\n", @@ -82,26 +99,40 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 134, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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DanaFbJDhw5B7yetr99++63pNum+124LidLXoAenLr2tIVQPfgNx65ce2OsBs7sv9fOZ29ebF3rwrnX8iy++MC00+h2RG7qv5s2bZ/ZB69ats5brbd0fGiL0M6S3tZ543u8+Pj9o+Hj00UdN/Xv33XfN/gpE669+B3z11Vcm+Gtd0RYqDRf6Oe/Vq5dX98Sc3rPnn3/etBDra9XPlHZv1PdJfwDSujd+/Phsz6/r/OlPfzIBSJ9r7969psxaprVr10qzZs2y1tX7NPx///335rP54IMPmu9Pva3P/de//jWrPPp6dBsaZLWLpn429Tv17bffNt9dq1atknPOOSdf9jcQlRwARcL27dsd/UjXq1fPGTZsmN9Lnz59zDr333+/12Pd5boN16ZNm5z4+HjnvPPOc/bt2+e1/pgxY8z648aNy1q2ZMkSs0wv06ZN81vGH3/8MduyXbt2OTVr1nQaNGjgtdy2vZdfftncd+WVVzqpqale9+nt3377Let2u3btzLqXXHKJc/Dgwazl33//vXmNDRs29Hr8m2++adbXv65jx445tWrVcmJjY5358+dnK8/OnTu91v3555+zrbNx40anTJkyzlVXXeX3tep7ZPPTTz+ZdWvXru2Eqm7duuZie+9dWh69T8vnatWqlVOiRAlnz5492db3rCdufdTt+zNlyhRz/9133+0cP348a3laWprTvXt3c98333yTrSxnnHGG87///S/b9gLtQ329uvy6664z23Z99tlnZnnnzp291r/zzjvN8ueee85r+RtvvJFVHz33RyAffvihWff555/PWjZ+/PisOnvmmWd61Vfdpx06dLC+X/7ek7y83kDc/en7XeHr6aefNuvpX3/ceqCfwUD0fdZ1OnbsmLXs119/dWJiYpwRI0aY29dee635bnNlZGQ4FSpUcEqVKuX1OnOi+yYxMTHHdbZt22bKkpSU5LXc9zVoHdRlPXr0yLYN/fwfPnw46PfM3/dienq62R9xcXHOjh07spVFL/379zf7wfX666/7fc9uvPFGs/zJJ5/M9jwpKSnmuZR+Ds866yynbNmyzrp167zW++KLL0xZrrnmGr+vASgu6KoHFDHbtm0zXTL8XbTbVLB0sLSOOdAuZ9qq4Omxxx4zLUbaWuBLu1Ddfffdfrfpdt/ypC0X+qv4Dz/84LcrSKDtaRc7bW3QFhD9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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from sklearn.cluster import AgglomerativeClustering\n", "\n", "# Perform Agglomerative Clustering\n", - "agg_clustering = AgglomerativeClustering(\n", - " n_clusters=2, metric=\"precomputed\", linkage=\"average\"\n", - ")\n", + "agg_clustering = AgglomerativeClustering(n_clusters=2, metric=\"precomputed\", linkage=\"average\")\n", "labels = agg_clustering.fit_predict(distance_matrix)\n", "\n", "# Visualize the clustering results\n", "plt.figure(figsize=(10, 6))\n", "for label in np.unique(labels):\n", - " plt.plot(np.mean(X[labels == label], axis=0), label=f\"Cluster {label}\") # Fix indexing\n", - "plt.title(\"Hierarchical Clustering with DTW Distance\")\n", - "plt.legend()\n", + " cluster_data = X[labels == label] # Ensure correct slicing\n", + " plt.plot(np.mean(cluster_data, axis=0), label=f\"Cluster {label}\", linewidth=2)\n", + "\n", + "plt.title(\"Hierarchical Clustering with DTW Distance\", fontsize=14)\n", + "plt.xlabel(\"Time Steps\")\n", + "plt.ylabel(\"Mean Value\")\n", + "plt.legend(loc=\"upper right\", fontsize=\"small\", ncol=2)\n", + "plt.grid(True)\n", "plt.show()\n" ] }, @@ -125,9 +156,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 136, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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OR0GpUPtXOmBkHXwpgfqU6ZMMQclf/vb39yG+6xYscIMPSptMr4OT8rPzzev5w8NSjq8Tw82R4wYYYYP6nA666DZk8550QNQ3c51WFJZ6IGWHhjrAVhlys3NNXPMcnJyzFBGDU/6+f7nP/8xc6hSUlLMwfl1111nDqR1yJc11Muag3X66aebg8+///3vUr9+ffP5XnvttSYUeQZT/d7089ODWn3N0obnHTp0SIYMGWI+c/2e582bJ/fcc485GNaDYKWBTgPq7t27zfwZ3f/Zs2ebYWh2tI1oyNYhjxq81LfffmvmEekBtu6/HnBrm9NhoNZ799SpUycz/NRzSJwGDH/eS3loKPjLX/4ir7/+uglmGlrLSv9+dPjnsmXLnOt0aKsuuu/6/X/22Wdu8wf1MynLML3S6FDafv36me/I+oy90TCvwUjbpYakvXv3ysKFC80QQr393HPPmfv0M7j//vvNYzS8q02bNpk5eZdeeqkZFqztVH+M0NfVz0nnVrrSoa/6vWu71B8MNNReeeWVbnPI9LV1bqUGOKut6ZBJ/VvR20r3V3800WB87733mnCloUyHuP7rX/8y3xWAEBLoLi8ANVdZhqmlpKQ4evToUWKonudSq1YtxxdffOH22AULFjgiIiLMosOB7r77bseXX37pyM3NddvujjvuMM+xZs2aMu/7jz/+aB6zcOFCc1uHKjVr1sxx2223lTpM6ZxzznE0atTIOfywrEP1ateu7TjxxBPLvH+eQ/Ws19m8ebPbdosWLTLr9VLpZ6C3586dW66hetdee62jcePGZgiW53Av/S6t9229buvWrd2GYnrbJ+v96Lp//vOfznU5OTnms7zkkkuc63QopG738ccfuw0B7NixY4nn9EaHwJ166qnO2xdffLFZtA19/vnnZt3q1avNc33yySc+P2+7oXpleS/+DtWz6HBTz/0ry36pCRMmmPt37NhhbuvQvNjYWLN/8+fPN59Denq6uW/69Olm2++++852n30N1bPo341u8/PPP5vb2k5d91OHquptHTJbnqF62dnZJYaB6mvExMQ4HnnkkRJtr1OnTuY9W6ZNm2bWr1271jl8t1WrVua78BwK7DpsccCAAY5u3bqZ13e9v0+fPo527dqV+l4ABB+G6gEIavrrsbfqevprrf7iq71RWgmvffv25hdp7Qmw6NA77XHS3gPt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JkyYYHpztKT3kiVLZMCAASW2HThwoJmL1LFjRxOyLrnkEud9Gn6GDx9uQtMpp5xihuJZ85wefPBBufTSS82cpmXLlplzLmlBCK2mp9trlT0tK15W2qtVp04dady4sdmH6dOnV0opchXm0JPY1CA67jElJUXS0tIq7MRb5eWc6E+PE8qINgN/0WbgL9oM/EWb8U92drZs3rxZWrVqJbGxsVITFRYWmmNyPRbX3qpAfu7+ZAN6nAAAAADABsEJAAAAAGwQnAAAAADABsEJAAAAAGwQnAAAAADABsEJAAAAAGwQnAAAAADABsEJAAAAgK2zzz5b3nnnHampCE4AAAAAjJkzZ0q3bt0kISFBWrRoIaNHj5YtW7ZU2POHhYXJjh07Kuz55s2bJ6effro5qe3VV18tlYngBAAAAEAeffRRefDBB+XJJ5+UAwcOyG+//SZ9+/aVb775RoJBfn5+iXV16tSRu+66S26++eZKf32CEwAAAFDDHT58WKZOnSovv/yyDB061PTgaK/TDTfcIGPGjCmx/cMPPyzXXXed8/bixYulbdu25vrRo0dlxIgRJtTocuaZZ5r1gwYNMpedOnWSZs2aybfffmtuv/jii9KuXTupV6+e6eE6cuSIWT9r1iw555xzZOzYsZKSkiJvvvlmif3o37+//PWvf5UGDRpIZSM4AQAAADXcihUrJDc3V84///zjfq633nrLhJ+dO3fK3r17TSBTCxYsMJfak6XD9TRQzZ07V2bMmCFfffWVbN++XfLy8uShhx5yPpeGq969e8uhQ4fkqquukkCKDOirAwAAADXcZf+5TPYf3V+pr1Evrp68f/77Pu/XoXna4xMZefzxICoqyjzfpk2bpEuXLs4eJ29ef/11ue+++6Rly5bm9sSJE014e/rpp83tNm3aOOcuxcXFSSARnAAAAIAA0tC0N2tvQPehbt26sn//fjOP6HjD08iRI2Xr1q3yl7/8RXJycuTGG2804cibbdu2maF4rnOUtNfJokP6ggXBCQAAAAgg7Q0K9GvocDjtKfrss8/koosusn2+hIQEM5fJsmfPHuf16OhoeeSRR8zy+++/mzLm+vx66alp06amKMXFF1/sswpfsCA4AQAAAAFU2hC6qlKrVi25//77Tc9PTEyMKcpQUFAgc+bMMfeP8SgQceKJJ8pzzz0nqampEh4eLtOmTXPet2jRIlOsQYtAJCcnmx6siIgIc5+u1/Lm3bt3dz6vzoHS59Nhebt375aff/5ZhgwZUqb91n3UHirtKdPr2dnZ5vUqYsihJ4pDAAAAAJBJkyaZwgwTJkyQ2rVrS4cOHWTJkiUyYMCAEtsOHDjQzEXq2LGjCVmXXHKJ8z4NP8OHDzeh6ZRTTjFD8ax5Tlru/NJLLzVzmpYtW2aq71177bUybNgws32/fv3k119/LfM+v/3222bu0wMPPGBOzqvXtQerMoQ5HA6H1CDp6emmnGFaWpr5cgJJ0/H8+fNNyUftGgXs0GbgL9oM/EWbgb9oM/7RHpHNmzdLq1atTMnvmqiwsNAck+uxuPZWBfJz9ycb0OMEAAAAADYITgAAAABgg+AEAAAAADYITgAAAABgg+AEAAAAVLEaVp+tWnzenMcJAAAAqCJaeVBP6rpv3z6pX79+UJ3gtSqr6uXm5ppKd1VRVU9Dk37e+lkfT+VHghMAAABQRfREsM2aNZMdO3aYE8HWRA6HQ44ePWrOuVRVwVFfRz9360S85UFwAgAAAKpQYmKitGvXzpwDqybKy8uTpUuXyllnnVVl5/7S1zme0KQITgAAAEAV04P44z2QD1URERGSn59vTkQbSidNpjgEAAAAANggOAEAAACADYITAAAAANggOAEAAACADYITAAAAANggOAEAAACADYITAAAAANggOAEAAACADYITAAAAANggOAEAAACADYITAAAAANggOAEAAABAqASnJ554QsLCwuT222/3uc2sWbPMNq5LbGxsle4nAAAAgJonUoLADz/8IK+88op0797ddtvk5GRZv36987aGJwAAAACo1j1OmZmZcuWVV8rMmTOldu3atttrUGrUqJFzadiwYZXsJwAAAICaK+A9TuPGjZNhw4bJueeeK48++miZglbLli2lsLBQevbsKVOnTpUuXbr43D4nJ8cslvT0dHOZl5dnlkCyXj/Q+4HQQZuBv2gz8BdtBv6izSCU24w/+xDmcDgcEiBz5syRxx57zAzV07lKZ599tpx00kny3HPPed1+xYoV8ueff5ohfWlpafL000/L0qVL5ZdffpFmzZp5fczDDz8skydPLrF+9uzZEh8fX+HvCQAAAEBoyMrKkiuuuMJkC50SFJTBafv27XLyySfLwoULnXOb7IKTt4TYqVMnGTFihEyZMqXMPU7N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AAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAAAI5uD0+OOPyymnnCJJSUnSoEEDGT58uKxfv77Ux8yaNUvCwsLcltjY2CrbZwAAAAA1T0CD05IlS2TcuHGycuVKWbhwoeTl5cmgQYPkyJEjpT4uOTlZdu/e7Vy2bt1aZfsMAAAAoOaJDOSLf/HFFyV6k7TnadWqVXLWWWf5fJz2MjVq1KhMr5GTk2MWS3p6urnUkKZLIFmvH+j9QOigzcBftBn4izYDf9FmEMptxp99CGhw8pSWlmYu69SpU+p2mZmZ0rJlSyksLJSePXvK1KlTpUuXLj6HA06ePLnE+gULFkh8fLwEA+1tA/xBm4G/aDPwF20G/qLNIBTbTFZWVpm3DXM4HA4JAhqCLrzwQjl8+LAsW7bM53YrVqyQP//8U7p3726C1tNPPy1Lly6VX375RZo1a1amHqfmzZvL/v37zZC/QCdcbTADBw6UqKiogO4LQgNtBv6izcBftBn4izaDUG4zmg3q1atncoVdNgiaHied67Ru3bpSQ5Pq3bu3WSx9+vSRTp06ySuvvCJTpkwpsX1MTIxZPOmXFOgvKhj3BaGBNgN/0WbgL9oM/EWbQSi2GX9ePyiC09///nf5z3/+Y3qOvPUa2b3ZHj16yIYNGypt/wAAAADUbAGtqqejBDU0ffTRR/LNN99Iq1at/H6OgoICWbt2rTRu3LhS9hEAAAAAIgM9PG/27NnyySefmHM5paammvUpKSkSFxdnro8aNUqaNm1qijyoRx55RE4//XRp27atmQ/11FNPmXLk1113XSDfCgAAAIBqLKDB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6m1G20mfPn0cr732mmP06NGOiy66qIr2FqHYZl5++WVH69atHbm5uVW4lwjlNqPb9u/f323d+PHjHX379q30fUVwERHHRx99VOo2d999t6NLly5u6y677DLH4MGDHcGGHqdKor/QrVq1ygydsoSHh5vb2jPgja533V7pLzq+tkf1Up424ykrK0vy8vKkTp06lbinCPU288gjj0iDBg1M7zZqlvK0mU8//VR69+5thuo1bNhQunbtKlOnTpWCgoIq3HOEUpvp06ePeYw1nG/Tpk1maOfQoUOrbL8ROlaE0PFvZKB3oLrav3+/+Y+K/kfGld7+/fffvT4mNTXV6/a6HtVfedqMp3vuuceMKfb8BwjVU3nazLJly8ywGR0OgZqnPG1GD3q/+eYbufLKK83B74YNG+Tmm282P9LoUCxUb+VpM1dccYV53BlnnKEjmyQ/P19uvPFGhurBr+Pf9PR0OXr0qJknFyzocQKqiSeeeMJM9v/oo4/M5F3AU0ZGhowcOdLMT6lXr16gdwchorCw0PRQvvrqq9KrVy+57LLL5P7775cZM2YEetcQpHT+rfZKvvTSS2ZO1IcffiifffaZTJkyJdC7BhwXepwqiR6UREREyJ49e9zW6+1GjRp5fYyu92d7VC/laTOWp59+2gSnr776Srp3717Je4pQbTMbN240E/y12pHrQbGKjIw0k/7btGlTBXuOUPp3RivpRUVFmcdZOnXqZH4l1mFc0dHRlb7fCK0288ADD5gfaXSCv9IqwVow4IYbbjChW4f6AXbHv8nJyUHV26RouZVE/0Oiv8x9/fXXbgcoelvHinuj6123VwsXLvS5PaqX8rQZ9Y9//MP8ivfFF1/IySefXEV7i1BsM3qqg7Vr15phetZy4YUXOisZaVVGVG/l+Xemb9++ZnieFbLVH3/8YQIVoan6K0+b0fm2nuHICt5F9QKAED3+DXR1iupszpw5jpiYGMesWbMcv/76q+OGG25w1KpVy5GammruHzlypOPee+91bv/dd985IiMjHU8//bTjt99+czz00EOOqKgox9q1awP4LhDMbeaJJ55wREdHO+bNm+fYvXu3c8nIyAjgu0AwtxlPVNWrefxtM9u2bTPVOv/+97871q9f7/jPf/7jaNCggePRRx8N4LtAMLcZPX7RNvPee+85Nm3a5FiwYIGjTZs2pnowqr+MjAzHmjVrzKJR4//+7//M9a1bt5r7ta1om7FoG4mPj3dMmDDBHP+++OKLjoiICMcXX3zhCDYEp0r2wgsvOFq0aGEObrWc58qVK5339evXzxy0uPrggw8c7du3N9tracbPPvssAHuNUGkzLVu2NP8oeS76Hy3UHP7+O+OK4FQz+dtmli9fbk6PoQfPWpr8scceM2XtUXP402by8vIcDz/8sAlLsbGxjubNmztuvvlmx6FDhwK096hKixYt8npsYrURvdQ24/mYk046ybQv/TfmzTffdASjMP2fQPd6AQAAAEAwY44TAAAAANggOAEAAACADYITAAAAANggOAEAAACADYITAAAAANggOAEAAACADYITAAAAANggOAEAAACADYITACDgrr76ahk+fHigdwMAAJ8ITgCAShUWFlbq8vDDD8u0adNk1qxZAdm/mTNnyoknniiJiYlSq1Yt6dGjhzz++OPO+wl1AAAVyccAAKhMu3fvdl5///335cEHH5T169c712lg0SUQ3njjDbn99tvl+eefl379+klOTo7873//k3Xr1gVkfwAAwYseJwBApWrUqJFzSUlJMb1Mrus0NHn26px99tlyyy23mFBTu3ZtadiwoekZOnLkiFxzzTWSlJQkbdu2lc8//9zttTTwnHfeeeY59TEjR46U/fv3+9y3Tz/9VP72t7/Jtddea56vS5cuMmLECHnsscfM/dob9tZbb8knn3zi7CFbvHixuW/79u3msdpLVadOHbnoootky5Ytzue23tPkyZOlfv36kpycLDfeeKPk5uY6t5k3b55069ZN4uLipG7dunLuueea9wgACD4EJwBAUNLAUq9ePfn+++9NiLrpppvk0ksvlT59+sjq1atl0KBBJhhlZWWZ7Q8fPiz9+/c3Q+1+/PFH+eKLL2TPnj0m3PiiwW3lypWydetWr/ffdddd5vFDhgwxPWe66Ovn5eXJ4MGDTYD79ttv5bvvvjNhTbdzDUZff/21/PbbbyZsvffee/Lhhx+aIKX0uTSkjRkzxrnNxRdfLA6Ho8I/SwDA8Qtz8C80AKCK6Dwm7UXSkONKe2d03ccff+zscSooKDChROl17a3SYPHPf/7TrEtNTZXGjRvLihUr5PTTT5dHH33UbP/ll186n3fHjh3SvHlzMzSwffv2JfZHw4s+p4Ynvb93794ydOhQ+etf/yrh4eFe902988475vU08GgvlNLApL1Pup2GOn3cv//9b9MzFR8fb7aZMWOGTJgwQdLS0uSnn36SXr16mV6qli1bVsKnDQCoSPQ4AQCCUvfu3Z3XIyIizFA2HdZm0aF4au/eveby559/lkWLFjnnTOnSsWNHc9/GjRu9voYVvNauXSu33Xab5Ofny+jRo03PUWFhoc9909fasGGD6XGyXkuH62VnZ7u9lhadsEKT0mCWmZlpwpTeN2DAAPOetCdNhyIeOnTouD4zAEDloTgEACAoRUVFud3Wnh3XdVZPjxVwNJBccMEF8uSTT3oNSKXp2rWrWW6++WYzD+nMM8+UJUuWyDnnnON1e30t7S169913S9yn85nKQsPgwoULZfny5bJgwQJ54YUX5P7775f//ve/0qpVqzI9BwCg6hCcAADVQs+ePeVf//qXnHDCCRIZWf7/vHXu3NlcWkUaoqOjzVBBz9fSCoENGjQwRR9K65k6evSoKf6gdEig9k7p8EEr/PXt29csWm1Qh+x99NFHMn78+HLvPwCgcjBUDwBQLYwbN04OHjxoCi788MMPZsicznfSKnyewceiBSemTJliijtogQgNNqNGjTK9RjqsTmkQ0xLlOk9KK/RpYYgrr7zSFK7QSno6r2rz5s2muMOtt95q5lVZdN6TVuz79ddfZf78+fLQQw/J3//+dzN/SnuWpk6dagpZbNu2zRSO2Ldvn3Tq1KnKPjMAQNkRnAAA1UKTJk1MANKQpMUZdO6QFqLQgg1WoQdPWv5bw5LOMdLiEJdcconExsaaang6p0pdf/310qFDBzn55JNNoNLX0HlLS5culRYtWpjiEhp2NCDpHCfXHiidw9SuXTs566yz5LLLLpMLL7zQlDhXup0+hxaj0NeeNGmSPPPMM6acOgAg+FBVDwCASuCtGh8AIHTR4wQAAAAANghOAAAAAGCDoXoAAAAAYIMeJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAABsEJwAAAACwQXACAAAAACnd/wPU+7gnX5U/jQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "from sklearn.cluster import DBSCAN\n", "\n", @@ -138,14 +180,19 @@ "# Visualize the clustering results\n", "plt.figure(figsize=(10, 6))\n", "for label in np.unique(dbscan_labels):\n", + " cluster_data = X[np.where(dbscan_labels == label)] # Fix indexing\n", + " \n", " if label == -1:\n", - " # Noise points\n", - " plt.plot(X[dbscan_labels == label].mean(axis=0), label=\"Noise\", linestyle=\"--\")\n", + " plt.plot(cluster_data.mean(axis=0), label=\"Noise\", linestyle=\"--\", linewidth=2)\n", " else:\n", - " plt.plot(X[dbscan_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", + " plt.plot(cluster_data.mean(axis=0), label=f\"Cluster {label}\", linewidth=2)\n", + "\n", "plt.title(\"DBSCAN Clustering with DTW Distance\")\n", - "plt.legend()\n", - "plt.show()" + "plt.xlabel(\"Time Steps\")\n", + "plt.ylabel(\"Mean Value\")\n", + "plt.legend(loc=\"upper right\", fontsize=\"small\")\n", + "plt.grid(True)\n", + "plt.show()\n" ] }, { @@ -159,9 +206,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 137, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAy0AAAIQCAYAAACMg4HBAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAikNJREFUeJzt3QmcHFW59/Fn9plMMlnIBiSEBAg7siObgIBsV4Wr6FUUVHBjExAV8CqbCAjI9SoCold8LwoqgnpBQVAQQVEEUZQlO0nIAiHr7Fu/n/+ZqZ7qmu6ZPj1Ld039vtpkprqmu6rr6e566pzznLJUKpUyAAAAAChR5cXeAAAAAAAYCEkLAAAAgJJG0gIAAACgpJG0AAAAAChpJC0AAAAAShpJCwAAAICSRtICAAAAoKSRtAAAAAAoaSQtAAAAAEoaSQsADMGdd95pZWVltmzZMouj7bff3j7ykY/YWHy9g3X/+te/jsq2xdWRRx7pbgBQykhaAPTzr3/9yz70oQ/ZtttuazU1NbbNNtvYaaed5pbnOjEMbrW1tTZ//nw799xzbe3atekT4/A6uW56LNHP+vuozZs325VXXmlvectbbPz48VZXV2d77LGHfeELX7BVq1ZlrPt///d/dsQRR9j06dNt3LhxNm/ePHvf+95nDz30UF6vQVdXl33/+993J3NTpkxxr4P246Mf/eiongT/6le/siuuuGLUni+Ovv3tb6djZzjpdQ/Hp+Jou+22s3e+850uNtra2tLrPv7443nFuG4/+clP3L/3339/v+dUbOu+xx57rN99eu5DDjlkwG1WAhp+Lr1PFPvvfe977Wc/+5l1d3cPy2vzxz/+0b0+GzduHJbHA4DBVA66BoBEue++++wDH/iAO1E/88wzbe7cue6q9ve+9z2799577Z577rFTTjml399dddVVbt3W1lZ78skn7dZbb3Un3P/85z/tv/7rv6yxsTG9rpbffffddvPNN9vUqVPTywc6IVuyZIkdc8wxtnz5cjv11FPtE5/4hFVXV9s//vEPt206AVywYIFb98Ybb7TPfe5zLmm59NJL3cnmokWL7NFHH3Xbf/zxxw/4GrS0tNi///u/uwTnbW97m1122WXu9dDroBPOH/zgB247Zs2aZSNNr9Utt9wyYonLK6+8YuXl8bl+9eEPf9j+4z/+wyWR4aRFcTRSLUaKZZ38K0l57bXX7OGHH7aPfexjLq4feOABmz17tu266672v//7vxl/p9jT333xi1/MWH7YYYe5f/U+Cb+XlJTr/VJZWWlPPfWUHXXUUen7VqxY4W7a98Hotfnud7+bjuVXX33VJfFKXJSE/+IXv7CGhob0+r/5zW8KSlp0AUGv+aRJk7z/HgC8pQCg16JFi1Ljxo1L7bLLLqnXX38947433njDLa+vr08tXrw4vfz73/9+Sh8lzzzzTMb6F110kVv+ox/9qN/z3HDDDe6+pUuXZt0O3XfOOeekf+/o6Ei95S1vcdv2hz/8od/6mzZtSl122WXpdRsaGlLHHnts1sdeu3btoK+DnlvbcPPNN/e7r7Oz023/ihUrMvY/174MVbAtw6m7uzvV3NycGit233331BFHHNFvea7YzNfll1/u/l6xH3XXXXelysvLUwcddJD3dsncuXNTBx54YMayhx56KFVWVpb6wAc+kDruuOMy7tP7SNvyi1/8YsBtPuOMM9x7NJtrr73WPcb73ve+1FAN9h4GgOEWn8trAEbcDTfcYM3Nzfad73zHpk2blnGfrmTffvvt1tTUZF/72tcGfay3v/3t7t+lS5cOebvUreXvf/+7u2IdXKUO01Xja665xv28bt06d8X60EMPzfpY6i42kJUrV7r9PPbYY+2CCy7od39FRYVdfPHFA7ayqFtOtpaR6PiRjo4Od7V6p512ct3qttpqK7d/jzzyiLtf66qVJXjM4BZQVx9d7d99993d38+YMcM++clP2oYNG/o977/927+5FoL999/fdavTPmbbpqC7n670X3TRRS4O6uvrXYvAG2+8kfG4en7tp7oPqjVLLQMvvvhiXuNk9t13X9eaFbbnnnu651brWeDHP/6xW/bSSy9lHdOi51K3xd///vfp1yc6PkMtJIPtiy91lzzrrLPsz3/+c/p4+dBx/tvf/uZaQgJ6zXUsTzjhBHv66aczunLpPu1brrjOxyWXXGLveMc77Kc//Wm6VTLXmJZvfvObblt0XCdPnuzi5kc/+pG7T8dcLZmi1tXgdQ+OibrO6f2v95pafXbbbTfXWhUVxKVanA488EAXw+rK9v/+3//rt666oV144YXub/SYev+dfvrp7v0ePs6XX3657bjjjm4dtYB9/vOfz+jGByC+SFoApKkLiU4KDj/88Kz3q6uU7n/wwQcHfazFixe7f3UiPlS//OUv012DBqMTJZ2Ua1/Wr1/v/Vy//vWvrbOzM6/nGiqd/Clp0cn+t771LZeUadzCc8895+5XAqLkSdT1KLgFdL9OHnUi+41vfMONt/nhD39oxx13nEuIot3A1O1Pj6d199577wG37bzzznOJok4CP/3pT7vXMzrOSN2ftP06oVXCq+RLz63EdjCKMZ2sBnSslHyoq9of/vCH9HL9rGRD3a+yUdKmE9hddtkl/fpEu2Plsy+FCGKkkO5VSlp0jJT0hBMTdZHUbdOmTa6rWPg+7eNQ30/aZjVmDpRo3XHHHXb++ee7ZEOvr46x4iXYViWbiiVRF8/gdQ8udChBmTNnjutWedNNN7nk4eyzz04n4GHqtqlua4pLrasESQlvePycupYqXpRIKelS/H7qU5+yl19+2V1kECV473rXu1zXUI050ronn3yy2773v//9Q3rNAJSIYW+7ARBLGzdudN093v3udw+43rve9S633ubNmzO64Dz66KOuG426Td1zzz2prbbaKlVXV5dauXLlkLuH7bPPPqmJEyfmvS9f/vKX3WOom8wJJ5yQuuaaa1LPPvtsXn974YUXur/929/+ltf62bqH6Xd1LYqaM2eO674TUJe3k046qaDuYeomp+U//OEP+3Uxii7X82qZ7htsm4L9OeaYY1w3svDrUlFR4eJE1qxZk6qsrEydfPLJGY93xRVXuL8PP2Y2P/3pT916L774ovv9l7/8ZaqmpsbF1/vf//70envttVfqlFNOGfD1Hqx72GD7Ukj3MNmwYYO7P7x9+XYP+9e//uX+9uqrr053a1S8/uAHP3C/z5gxI3XLLbe4n/Ve0/Z+/OMfTw1moO5horjW8+o1CGgbw9upzwBt+0AGeg9n63qo7m7z5s3LWBbE5RNPPJFepm6pioPPfvaz/d7P9913X7/HDY7r//7v/7ruetHuo7fddpv726eeemrA/QFQ+mhpAeBs2bLF/TthwoQB1wvuVxesMA2S15VWXVXVYGENQNbgeFUgGyo912DbFaYrw+rKss8++7guUbryvt9++7kuSUE3o4GeS3yer1AawKwrygsXLvT+W3XxmThxortCrS4ywU37qdc+Wn1K3XjUCpIvFToId0XTlW5VVNOgbvntb3/rWqR0BT3aqpGPoDXviSeeSLeoHHDAAW5/gpYWdQlSa0Ou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yPM9/vjjLgnauHGjjZT169fbaaedZg0NDTZp0iQ788wzrbGxcUSeK4kxg8IRL0hKzCS6ephUVib+JYAnYga+khQzy5Yts0MPPdSd2N9www225557WkdHhz388MN2zjnn2Msvv2ylSrNDa2BqtuOlhGX16tX2yCOPuP356Ec/ap/4xCfsRz/60YhsS5JiBkNHvCAJMROvFGsEBiEtXLgwloORUBzEDHwlLWbOPvts1+rxl7/8xd7znvfY/Pnzbffdd7eLLrrInn766bxbSp5//nm3TEmQvPrqq661ZvLkyVZfX+8e81e/+pW7/6ijjnLr6D79zUc+8hH3u17za6+91l1RrKurs7e85S1277339nveX//617bffvu5VqEnn3yy3/a99NJL9tBDD9l3v/tdO+igg+ywww6zb37zm3bPPffYqlWrhv01TFrMYGiIFyQlZuKXZgFAAqkVoK2zOF8wNZXl7uQ+ny5UOrm/5pprXGIRpdaXQqmVpr293Z544gn32C+++KKbZ0Bdz372s5+5BOmVV15x3beUoIgSlrvuustuu+0222mnndzffuhDH7Jp06bZEUcckX7sSy65xG688UbXnU2JT9Sf/vQnt+37779/etkxxxzjulb8+c9/tlNOOaXg/QIA5IekBQBiQAnLOT98rijPfctp+1ptVcWg6y1atMglV7vsssuwb8Py5ctdYqLuZqIEIzBlyhT37/Tp09OJUVtbm331q1+1Rx991A4++OD036gl5fbbb89IWq666io79thjBxyjo8eOdq3Q8+o+AMDII2kBAAwLJSwj5fzzz7dPf/rT9pvf/Ma1ciiB2WuvvQZMoJqbm/slI2qt2WeffTKWhVtQAAClKdFJi5r21WUgbtUTUDzEDIoVM+qipRaPYtBz50P7qW5kvoPtg9cmnPRosHvYWWedZccdd5w9+OCDLnFR16+bbrrJVSnLJqjspfW33XbbzP2pqcn4PVtXtrCZM2fa66+/nrGss7PTdYfTfcONzxn4IF6QlJiJ19aOAH3xAD6IGRQjZpQMqItWMW75jGcRdZdSYnHLLbdYU1NTv/tzlSTWGBNRda7wQPwojV/51Kc+Zffdd5999rOftTvuuMMtr66udv+q8ldgt912c8mJupXtuOOOGTc9jg91L9O2P/vss+llv/vd79wgVg3MHwl8zsAH8YIkxEyiW1r0hbN06VKXbVZUDN5fGyBm4CtpMaOERSWPDzzwQDdWRF249OWoUsG33nqrq8QVFSQSV1xxhRvEv2DBAteKEnbBBRfYCSec4KqRbdiwwR577DHbdddd3X1z5sxxidUDDzxgJ554ohuIP2HCBLv44ovtwgsvdMdAFb82bdpkTz31lBusf8YZZ+S9T3qe448/3j7+8Y+7Qf1qBTr33HPtP/7jP2ybbbax4Za0mMHQEC8I6+zqtsa2TtvSGtw63L89yzpss5a1tNuKtW/aGUfsagfOm2pxkeikBQAwvDTY/bnnnnPJh1pD1HqilhSVFFbSkk1VVZXdfffdbsyKkpwDDjjAvvKVr9ipp56aXketKKogtnLlSpd0KIm4+eab3X3q/nXllVe6KmCaP+X000+3O++8066++mr33OpKtmTJEjdIf99997XLLrvMe79++MMfukTl6KOPdl0qNKbmv//7v4fwSgHA4Dq6unuSjtZO29ybgCj56EtMepe1ddrmlg5rae9rcc5FXXGbmjptfVO7xUlZaiRHTmaxefNmmzhxorvipS+eYtKXoOpUc3UC+SJmMFox09ra6q6eao6R2traEd1GDL+hHD8+Z+CDeImX9s7udIuHEpH0z70tIeGkRMtb80hCotSjt76m0ibU6lbV92/vsvrqclu/dpUdtOd822pCT4n4Yso3N0h8S0vcBiGh+IgZ+CJm4IuYgQ/ipbjzZ2W0eERaP6KJSFuH/3xb6v46wSUeuRORYNl43aorrby8bMBEd3HXBps0rmc8YFwkOmnRFQn1jwbyRczAFzEDX8QMfBAvw5uEtHR09XbFCrV4tGS2fqTHibR2uu5bvirKy1xy0RAkGjWV1lDX97MSkIbeRETr1VfnXxBlLMdMopOWnj59Ta7c5XAGA8YuYga+iBn4Imbgg3gZ5LVp70lC0oPQsyQiW3rHi2i9rm7/URNVFeUuuQhaPBrCyUddZiKi9eo8qjKOhFRMY6Yy6RU3NKiTfqDIFzEDX8QMfBEz8JGkeOnuTlljezAWpH83LCUijW3hblqdBU16W1NVnk40cnXDCv+suazidPLfHdOYSXTSAgAAgOJQq0ZQFStbNazweBD929SmJMT/eWqrKzJaP4KEw3XLCnXDCn6uznNCXYwukhYAAAAMyxwh6VaOjBaPzG5YwfLmtsImOBwXtHpEB6GHkhKNFwm6bKn7FuIv0UmLmvI0k3KcmvRQXMQMfBEz8EXMoFTiReV5e8Z/dGRPRCItIvnMEdJ/+83GVfckFxqMntH6kaVLlpZVkoQk8jOmMuklAjURGpAvYga+iBn4ImYwUvHSqspY0W5Y6QHqffOGBAlKYeV5rf94kN6EI9z6kW4dGaQ8L4ZfeUw/YxKdtGhwliay0YQ2ccs2URzEDHwRM/BFzCDfOGnt6LbNLe22et0GS1XVZUlIMn8vpDyvEoq+rlj9E5HovCHDXZ4Xwy8V08+YRCctqp6wZs0amzBhQqyqJ6B4iBn4Imay0xfl/fffbyeffHKxN6XkEDPJPZFsbu/qafFo62v9CLphhceCBMs1kN23fG1lhZKQzG5YwaSEwbwh4USk2OV5Mfy6Y/oZk+ikBQAw/PRleM0119iDDz5or732mk2fPt323ntvu+CCC+zoo48e9ud7/PHH7aijjrINGzbYpEmTbCQE+/P888+7vuAbN24ckefB2KFkoq/lIzMR6Zs3pHdcSO/YEJX09aVKV5V1FTZr6jibUFudsxtWsDxu5XmBAEkLAGDYLFu2zA499FCXPNxwww225557WkdHhz388MN2zjnn2Msvv2ylfJLZ1dVllZX9vxrb29vt1FNPtYMPPti+973vFWX7UALleUODzsM/b86SiDQWWp63qiI06Lx/y0e0WlZVudnChQtjN+cG4CvRSYuuNMRtNlAUFzEDX0mLmbPPPtvt61/+8he334Hdd9/dPvaxj+XdUqIWjX322ceWLl1q22+/vb366qt27rnn2pNPPukSCC1TUrTbbru5v5XJkye7f8844wy78847XReI66+/3r7zne+41p/58+fbl770JXvve9+b8by/+tWv7D//8z/thRdesN/85jd25JFH9tvGK6+80v2rxx1pSYuZYpbnjc6G3r9CVl9i0txeWBJSV10RmSU9V5esni5bvnOEKM6JFyThM6Yy6dUTZs+eXezNQIwQMyhazOhsqbPNiqKypqck0CDWr19vDz30kOtKFU5YAkPpuqVWGiUrTzzxhHvsF1980caPH+9e25/97Gf2nve8x1555RVraGiwuro69zfXXnut3XXXXXbbbbe5q9D62w996EM2bdo0O+KII9KPfckll9iNN97oqukEiU8x8TlTGA0yD7peKQnJSERCrSM9XbQ6CirPK/U12cZ/aKB6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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "from sklearn.cluster import OPTICS\n", "\n", @@ -171,15 +229,32 @@ "\n", "# Visualize the clustering results\n", "plt.figure(figsize=(10, 6))\n", + "colors = plt.colormaps[\"tab10\"]\n", + "\n", "for label in np.unique(optics_labels):\n", + " cluster_data = X[optics_labels == label]\n", + "\n", + " if cluster_data.size == 0:\n", + " continue # Skip empty clusters\n", + "\n", + " # Ensure correct shape for plotting\n", + " cluster_data = np.squeeze(cluster_data)\n", + " if cluster_data.ndim == 1: \n", + " cluster_data = cluster_data[:, np.newaxis] # Convert to 2D if needed\n", + "\n", + " # Compute mean representation of each cluster\n", + " cluster_mean = cluster_data.mean(axis=0) \n", + "\n", + " # Plot noise separately\n", " if label == -1:\n", - " # Noise points\n", - " plt.plot(X[optics_labels == label].mean(axis=0), label=\"Noise\", linestyle=\"--\")\n", + " plt.plot(cluster_mean, linestyle=\"--\", color=\"gray\", alpha=0.5, label=\"Noise\")\n", " else:\n", - " plt.plot(X[optics_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", + " plt.plot(cluster_mean, color=colors(label % colors.N), alpha=0.7, label=f\"Cluster {label}\")\n", + "\n", "plt.title(\"OPTICS Clustering with DTW Distance\")\n", "plt.legend()\n", - "plt.show()" + "plt.grid(True, linestyle=\"--\", alpha=0.5) # Light grid for better readability\n", + "plt.show()\n" ] }, { @@ -192,35 +267,39 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 138, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAy0AAAIQCAYAAACMg4HBAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAX4tJREFUeJzt3QmYXGWV//HT+5JespCVJE0iSyAhiGzDoihLEJERZHR0kE1ERRYjMqPIXwEFooO7g2w6gOMgjgjogGwigQFkF2TfAkmAhI5ZutPppNNL/Z/fW96mulLd6equqvvee7+f52mKrqpU3bp1q/o99z3nvGWpVCplAAAAAOCp8rA3AAAAAACGQtACAAAAwGsELQAAAAC8RtACAAAAwGsELQAAAAC8RtACAAAAwGsELQAAAAC8RtACAAAAwGsELQAAAAC8RtACYIDzzz/fysrKCvqYr7/+unvMa665xqLoxBNPtO22286iIp/9Hdz3u9/9bkm2LQ7vvfaXPidR/lwW4zO5ePFi95i6LPZnJ4z3wCfap9q3QJIQtAA5PP300/ZP//RP1tLSYrW1tbbtttvaoYceaj/5yU/C3jTr7Ox0f6wzBwZh0nZ89KMftSlTplh1dbVNmjTJjjzySLvxxhtLtg3PPfec2ycaiCG3P/zhD0UZ5AUDVf08/vjjW9yugVVDQ0PBnxeD+9///V878MAD3Wexvr7eZs+ebR//+Mft9ttvt7h68MEH3fG9bt26gj7u+9//fnds77DDDjlvv+uuu/qP/xtuuCHvx+e7Cxi+yjzuCySC/vh94AMfsJkzZ9opp5ziBuPLly+3hx56yH70ox/ZGWecEXrQcsEFF/T/QQ3TeeedZ9/85jfdH/TPfe5zLshbvXq1GyAfc8wx9t///d/2L//yL0XfDv3h1z7R/ijGWd2rrrrK+vr6LCr0PmzcuNGqqqr6r9N7cumllxb17LQeWwPmuNO+raz088+nZsz+9V//1QUt55xzjgtaXnnlFfvjH/9o119/vX3wgx8c9BgZrfe9733uMXXyotTvgb639R2gIHns2LEFfS6duNI+fOSRR2zvvfcecJu+43T7pk2bSvrd9eKLL1p5OeedkSx+fusCIbrooousubnZHn300S3++LW2tlrUbNiwwcaMGVPwx9VZRQUsmpG67rrrBgx+NGi64447rLu726Is2HeFHNiVgs76aiBVSu9+97vtlltusSeeeMLe8573FDVo10A8TKXet8PV09Nj3/rWt9ys8J133rnF7ZnfX8U4RjSILua+0YmDzZs3u+co5Xvwrne9y+3bX/3qVwOCFgUqN910kx1xxBH229/+tujbkUql3HPW1dVZTU1N0Z8P8A1hOpDl1Vdftblz5+Y8W6d0i0z6w3/66ae7s2077bST+0O6xx572H333bfFv33zzTft05/+tE2ePNn9wdFz/Od//ucW99MfJZ2x3nHHHd3jTZ061aVfabuUQjBx4kR3P52dC9ISgrPnQSqO7vuhD33IGhsb7dhjj3W3/d///Z997GMfczNIev4ZM2bYl770JXfGciS+/vWv2/jx491ryDWoP+yww+zDH/7woP9eZxZzzRTlyoHXGWLtV72epqYm23XXXd2slygnX69LNEMW7JPM9LnbbrvN3vve97oARI+hQcazzz67xfMOtu+ytymzDuTKK690gxrt07322ssFu9l+85vf2C677OLez3nz5rmBznBy/c866yybMGGCG6wENNOn5/7xj3/cf93bb7/trrvsssty1ivouTTLIsH+yVUfMZzXMhht17hx44Y9k/PTn/7UfQb0XNOmTbPTTjtti9QeHR/aX0o701l8BStf+9rXBux/vS6lP+m2BQsWuFlR7S8N3qdPn+4GeB/5yEdszZo1Ax77d7/7nTsO9NzaBr1u/Zve3t6tbnvmZy7YlsF+Mj388MNupkMnRbS9mg154IEHtnj8+++/3+1/HS/ariuuuGJY+/Rvf/ubtbe32/7775/z9szvr1w1LcFnYNmyZe6zq/9Xamxw7Cht9qCDDnKfI83U6GTF1mpactH7tt9++7ljW++PPtu5Uqsyv1+DYyVIcct8D3SpEyUya9as/n2v16h9vNtuu+XcDn1n63tqOD75yU/ar3/96wEzrppVVBCt1LtsS5cutS984QvuOfQa9Vr1PZWZBra17y59P+h90AmgPffc0z1OcCxk1rToeNe/19+GzMBUAZ6+K3UM6QQMEHXMtABZ9Mf4z3/+sz3zzDNuwLQ19957r/tjduaZZ7o/qhqMaWCiVILg32tQ+Q//8A/9f4T1x0UD6ZNPPtkNMhYuXOjupwGT/kjdfffd9olPfMK++MUv2vr1613etLbnkEMOcQPTU0891Y4++mgXzMj8+fP7t0dn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D1VVVVZRURH2ZgAAACCGvAtaFKy89tprLnBBtIwdO9amTJnC+jsAAACIb9CixWVWrFjhztir9dlQC8zAr/ets7PTWltb3e9Tp04Ne5MAAAAQI14FLT09PW7wqxUx6+vrw94c5KGurs5dKnCZNGkSqWIAAAAoGK+mMnp7e91ldXV12JuCEQgCze7u7rA3BQAAADHiVdASoCYimnjfAAAAkJigBQAAAAACBC0lnom4+eabw94MAAAAIFIIWgpk5cqVdsYZZ9js2bOtpqbGdT878sgj7e677y7K8y1evNgFQevWrbNiWbNmjR177LHW1NTk2hmffPLJ1tHRUbTnAwAAALzvHlYofX0pe6l1vbV1dltzfZXtOKnRysuLV2/x+uuv2/777+8G9pdccontuuuurhj9jjvusNNOO81eeOEF87ldsRogVFZueSgoYFEL6rvuusu9npNOOsk++9nP2nXXXRfKtgIAACCZYjfT8vjSNbbw10/aWb9+ys696Wl3qd91fbF84QtfcLMejzzyiB1zzDG244472ty5c+2ss86yhx56aNgzJU8++aS7TkGQLF261M3WjBs3zsaMGeMe8w9/+IO7/QMf+IC7j27TvznxxBPd71qUc9GiRTZr1izXhni33XazG264YYvnve2222yPPfZws0L333//Ftv3/PPP2+23324/+9nPbJ999rEDDjjAfvKTn9j1119vb731VsH3IQAAQF60EPnbz5q9/kD6koXJYy1WMy0KTC669Xlb19ltkxprrLaqxjZ199qzb7W56889Ymfbo2V8wVOoNLi/6KKLXGCRTbMvI6VZms2bN9t9993nHvu5556zhoYGl3r229/+1gVIL774okvfCtZJUcDyy1/+0i6//HLbYYcd3L/91Kc+ZRMnTrQDDzyw/7G/+tWv2ne/+12XzqbAJ9uf//xnt+177rln/3WHHHKIW/Dz4YcftqOPPnrErwsAAGBUlj1s9siVZn970ayny6yyxmybncz2/qzZzH3C3joUQWWcUsKufXCpC1i2m1Df3353TE2l1VdX2NI1nfaLB5fa7jPGFTRV7JVXXnEpVnPmzLFCW7ZsmQtMlG4mCjAC48engy8t5BgERl1dXXbxxRfbH//4R9t33337/41mUq644ooBQcs3v/lNO/TQQ4es0dFjZ1IKmZ5XtwEAAIQWsNx5rtnGdWaNk80q68x6Npqt+Gv6+gUXEbjEUGyCFtWwvNLa4WZYstcL0e8TG2rs5dYOd785U5oK9rwKWIrlzDPPtFNPPdXuvPNON8uhAGb+/PlDBlCdnZ1bBCOardl9990HXJc5gwIAABAJSgHTDIsClvGzNchLX1/dYDZ+jNma18wevcps+l5m5bGrgki02LybKrrf3NNrtVUVOW/X9bpd9yskpWApKMq32F5pVtlBT/ZK8p/5zGdsyZIldtxxx9nTTz/tAg3VlQwm6Ox16623uvqY4EdpZZl1LZIrlS3TlClTrLW1dcB1PT09Lh1OtwEAAJTcqufTKWGaYcle1Fq/N04yW/VC+n6IldgELeoSVl1Z4WpYctH1ul33KySlSx122GF26aWX2oYNG7a4fbCWxKoxEXXnCijAyKb6lc9//vN244032pe//GW76qqr3PXV1dXuUp2/ArvssosrrFda2fbbbz/gR4+TD6WXadsff/zx/uv+9Kc/uUJ/FeYDAACUnGZYXA1LupZ3Cy5VrCt9P8RKbIIWtTXeflKDrero2iJlS7/r+h0mNbj7FZoCFgUPe++9tyuQf/nll133rR//+Mf9tSXZgkDi/PPPd/fX7Mj3vve9AfdZuHCha5v82muv2RNPPGH33HOP7bzzzu62lpYWN8Nzyy232KpVq9wsS2Njo5199tn2pS99ya699lp79dVX3b/T7Ix+z4ee54Mf/KCdcsoprivaAw88YKeffrp94hOfsGnTpo1ibwEAAIxQ3dh00b1qWHLR9bpd90OsxCZoUXH9Cfu1WHNdlSu639DVY719KXep33X98fu1FGW9FhW7KzhQG2LNhsybN8/VlWhhycsuuyznv6mqqrJf/epXLq1MdSrf+c537MILLxxwHwVC6iAWBBBqpfzTn/7U3bbtttvaBRdc4LqATZ482QUU8q1vfcu+/vWvuy5iwb9TQKQWyPn67//+b9dg4OCDD7YPfehDru3xlVdeOaJ9BAAAMGoTd053CVvfqrPSA2/T77p+4pz0/RArZaliVpLn0N7ebs3NzdbW1uZa9WbatGmTm1XQALu2tnbEbY/VRUxF+aphUUqYZlgUsBS63TGs4O8fAADA8LqHtaVrWILuYQpYNMOy4EK6h0XIULFBLLuHBRSYqK2xuoSp6F41LEoJK8YMCwAAAEpMAYnaGvev09KaTgmbtpvZXqcQsMRU7IIWUYBSyLbGAAAA8IgCE7U1VpcwFd1rhkUpYbQ5jq1YBi0AAACIOQUok+eGvRUoEcJRAAAAAPEKWt5880371Kc+ZRMmTLC6ujrbdddd7bHHHivO1gEAAABIvLzSw9auXWv777+/a+172223uQUStcbIuHHjireFAAAAABItr6BFa4loQcSrr766/7qRrP8BAABQcH19FGYDMZVX0PL73//eDjvsMPvYxz5m9957r1vg8Atf+IJbNR0AACDUtTv6W+B2pVvgahHCvT9LC1wgBvI6/bBkyRK3wvsOO+xgd9xxh5166ql25pln2rXXXjvov+nq6nKLxmT+AAAAFHyxwRVPmdU2m41tSV+u+Gv6et0OIDlBS19fn73nPe+xiy++2HbffXf77Gc/62ZZLr/88kH/zaJFi9wql8GP0suSqqyszG6++eawNwMAgHilhGmGRSlh42ebVTeYlVekL8fPSq+a/uhV6fsBSEbQMnXqVNtll10GXLfzzjvbsmXLBv0355xzjrW1tfX/LF++3OJo5cqVdsYZZ9js2bOtpqbGBWdHHnmk3X333UV5vsWLF7sgaN26dVYsF110ke23335WX19vY8eOLdrzAAAwYqphUUpY42SdHRx4m35vnGS26oX0/QAko6ZFncNefPHFAde99NJL1tLSMui/0QBeP3EuxHv99dfdvtHA/pJLLnFtoLu7u10K3WmnnWYvvPCC+SqVSllvb69VVm55KGzevNnVL+27777285//PJTtAwBgSPpb72pY6nLfrut7WtP3A4aDhg5eyusd+NKXvmQPPfSQSw975ZVX7LrrrrMrr7zSDcy9obzVG08xu+lzZrcsTF/q9yLms6oZgWY9HnnkETvmmGNsxx13tLlz59pZZ53l9tdwZ0qefPJJd52CIFm6dKmbrVFL6TFjxrjH/MMf/uBuV9tp0W36NyeeeGJ/Cp9S8tTVTevo7LbbbnbDDTds8bxqWb3HHnu4gPL+++/PuY0XXHCBe88VhAEA4CUNKlV037Mx9+26Xrfrfhj+oP3tZ81efyB9maTUuhDGkSjCTMtee+1lN910k0v5+uY3v+kGxj/84Q/t2GOPNa8K8RQZa5rYnV3Z+E4h3oKLCt5BZM2aNXb77be7VCoFFtlGk1alYFCzHffdd5977Oeee84aGhpc6tlvf/tbFyBp5qupqckFKKKA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sqOOOspefPHFsDcLHrjsssts/vz5/Yt/7bvvvnbbbbeFvVnw0Le//W33t2XhwoVhbwo8cP7557vjIfNnzpw5YW8WPPHmm2/apz71KZswYYLV1dXZrrvuao899pglCUHLEDZs2GC77babXXrppWFvCjxz77332mmnnWYPPfSQ3XXXXdbd3W0LFixwxwySbfr06W4w+vjjj7s/KAcddJB95CMfsWeffTbsTYNHHn30UbviiitcgAsE5s6daytWrOj/uf/++8PeJHhg7dq1tv/++1tVVZU7Cfbcc8/Z9773PRs3bpwlSWXYG+Czww8/3P0A2W6//fYBv19zzTVuxkUD1fe9732hbRfCp9nZTBdddJGbfVGAqwEJ0NHRYccee6xdddVVduGFF4a9OfBIZWWlTZkyJezNgGe+853v2IwZM+zqq6/uv27WrFmWNMy0AAXQ1tbmLsePHx/2psAjvb29dv3117sZOKWJAaJZ2iOOOMIOOeSQsDcFnnn55ZddSvrs2bNdYLts2bKwNwke+P3vf2977rmnfexjH3MnSHfffXd30iNpmGkBRqmvr8/lpGvqdt68eWFvDjzw9NNPuyBl06ZN1tDQYDfddJPtsssuYW8WPKAg9oknnnDpYUCmffbZx83a77TTTi417IILLrD3vve99swzz7j6SSTXkiVL3Iz9WWedZV/72tfc98eZZ55p1dXVdsIJJ1hSELQABThrqj8q5B4joEHHk08+6WbgbrjhBvdHRXVQBC7Jtnz5cvviF7/o6uBqa2vD3hx4JjMdXbVOCmJaWlrsf/7nf+zkk08OddsQ/snRPffc0y6++GL3u2ZaNO64/PLLExW0kB4GjMLpp59ut9xyi91zzz2uABsQnf3afvvtbY899nCd5tTQ40c/+lHYm4WQqeattbXV3vOe97jaBf0omP3xj3/s/l/phEBg7NixtuOOO9orr7wS9qYgZFOnTt3ipNfOO++cuPRBZlqAEUilUnbGGWe4tJ/FixcnsiAO+Z0l6+rqCnszELKDDz7YpQ5mOumkk1xb26985StWUVER2rbBz4YNr776qh133HFhbwpCpvTzF7OWVXjppZfcTFySELRs5Qsj8wzHa6+95lI+VGw9c+bMULcN4aeEXXfddfa73/3O5RqvXLnSXd/c3Oz6pyO5zjnnHJfmoe+I9evXu+NEge0dd9wR9qYhZPquyK57GzNmjFt3gXo4nH322a77oAaib731lp133nkukP3kJz8Z9qYhZF/60pdsv/32c+lhH//4x+2RRx6xK6+80v0kCUHLELTGwgc+8IH+31UAJcofVLEckksFcfL+979/wPVqR3jiiSeGtFXwgdJ/jj/+eFdIqyBWuekKWA499NCwNw2Ax9544w0XoKxevdomTpxoBxxwgGuVrv9Hsmkx65tuusmdFPvmN7/psjt++MMfug5zSVKWUp4LAAAAAHiKQnwAAAAAXiNoAQAAAOA1ghYAAAAAXiNoAQAAAOA1ghYAAAAAXiNoAQAAAOA1ghYAAAAAXiNoAQAAAOA1ghYAAAAAXiNoAQAAAOA1ghYAAAAAXiNoAQAAAGA++/+2L3RY83yeZQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from sklearn.cluster import SpectralClustering\n", + "from sklearn.metrics import pairwise_distances\n", "\n", - "# Ensure the distance matrix does not contain zeros on the diagonal or elsewhere\n", - "# Normalize distance values to [0, 1] and convert to similarities\n", + "X = np.vstack((np.random.normal(loc=[2, 2], scale=0.5, size=(50, 2)), \n", + " np.random.normal(loc=[5, 5], scale=0.5, size=(50, 2))))\n", + "distance_matrix = pairwise_distances(X, metric='euclidean')\n", "inverse_distance_matrix = 1 - (distance_matrix / distance_matrix.max())\n", - "\n", - "# Perform Spectral Clustering with affinity=\"precomputed\"\n", "spectral = SpectralClustering(n_clusters=2, affinity=\"precomputed\", random_state=42)\n", "spectral_labels = spectral.fit_predict(inverse_distance_matrix)\n", - "\n", - "# Visualising the clustering results\n", "plt.figure(figsize=(10, 6))\n", "for label in np.unique(spectral_labels):\n", - " plt.plot(X[spectral_labels == label].mean(axis=0), label=f\"Cluster {label}\")\n", + " plt.scatter(X[spectral_labels == label, 0], X[spectral_labels == label, 1], label=f\"Cluster {label}\", alpha=0.7)\n", "plt.title(\"Spectral Clustering with Normalized Similarity Matrix\")\n", "plt.legend()\n", "plt.show()" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] } ], "metadata": { From 68860e6895153484484eb9c9f4c208b530040ab7 Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 9 Mar 2025 08:30:45 +0500 Subject: [PATCH 23/25] resolve conflict --- .../clustering/sklearn_clustering_with_aeon_distances.ipynb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 412ec83d5e..256aab95bb 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -125,7 +125,6 @@ "# Visualize the clustering results\n", "plt.figure(figsize=(10, 6))\n", "for label in np.unique(labels):\n", -<<<<<<< HEAD " cluster_data = X[labels == label] # Ensure correct slicing\n", " plt.plot(np.mean(cluster_data, axis=0), label=f\"Cluster {label}\", linewidth=2)\n", "\n", @@ -134,15 +133,13 @@ "plt.ylabel(\"Mean Value\")\n", "plt.legend(loc=\"upper right\", fontsize=\"small\", ncol=2)\n", "plt.grid(True)\n", - "plt.show()\n" -======= + "plt.show()\n", " plt.plot(\n", " np.mean(X[labels == label], axis=0), label=f\"Cluster {label}\"\n", " ) # Fix indexing\n", "plt.title(\"Hierarchical Clustering with DTW Distance\")\n", "plt.legend()\n", "plt.show()" ->>>>>>> fb45d2921c7f2c8ca58b871275140d14e02c6956 ] }, { From 50ca0e859d225ab316a30da385f455b580db5e1b Mon Sep 17 00:00:00 2001 From: code2x Date: Sun, 9 Mar 2025 08:39:23 +0500 Subject: [PATCH 24/25] git commit -m "Fix IndentationError in sklearn_clustering_with_aeon_distances.ipynb" --- .../sklearn_clustering_with_aeon_distances.ipynb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 256aab95bb..7cac1408dc 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -99,7 +99,7 @@ }, { "cell_type": "code", - "execution_count": 134, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -133,12 +133,6 @@ "plt.ylabel(\"Mean Value\")\n", "plt.legend(loc=\"upper right\", fontsize=\"small\", ncol=2)\n", "plt.grid(True)\n", - "plt.show()\n", - " plt.plot(\n", - " np.mean(X[labels == label], axis=0), label=f\"Cluster {label}\"\n", - " ) # Fix indexing\n", - "plt.title(\"Hierarchical Clustering with DTW Distance\")\n", - "plt.legend()\n", "plt.show()" ] }, From bc8d54b535d71fde7bc4d9211509eda5539fb4c7 Mon Sep 17 00:00:00 2001 From: code2x Date: Fri, 11 Apr 2025 15:14:55 +0500 Subject: [PATCH 25/25] Re-applied Spectral clustering on time series data using Aeon --- ...learn_clustering_with_aeon_distances.ipynb | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb index 7cac1408dc..bf24b1ba5c 100644 --- a/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb +++ b/examples/clustering/sklearn_clustering_with_aeon_distances.ipynb @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": 106, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -59,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": 107, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -267,7 +267,7 @@ }, { "cell_type": "code", - "execution_count": 138, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -284,18 +284,15 @@ "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "from sklearn.cluster import SpectralClustering\n", - "from sklearn.metrics import pairwise_distances\n", - "\n", - "X = np.vstack((np.random.normal(loc=[2, 2], scale=0.5, size=(50, 2)), \n", - " np.random.normal(loc=[5, 5], scale=0.5, size=(50, 2))))\n", - "distance_matrix = pairwise_distances(X, metric='euclidean')\n", + "X, _ = load_basic_motions(split=\"train\", return_X_y=True)\n", + "flat_X = np.array([flatten(ts) for ts in X])\n", + "distance_matrix = pairwise_distances(flat_X, metric=\"euclidean\")\n", "inverse_distance_matrix = 1 - (distance_matrix / distance_matrix.max())\n", "spectral = SpectralClustering(n_clusters=2, affinity=\"precomputed\", random_state=42)\n", - "spectral_labels = spectral.fit_predict(inverse_distance_matrix)\n", + "labels = spectral.fit_predict(inverse_distance_matrix)\n", "plt.figure(figsize=(10, 6))\n", - "for label in np.unique(spectral_labels):\n", - " plt.scatter(X[spectral_labels == label, 0], X[spectral_labels == label, 1], label=f\"Cluster {label}\", alpha=0.7)\n", + "for label in np.unique(labels):\n", + " plt.plot(flat_X[labels == label].T, alpha=0.5, label=f\"Cluster {label}\")\n", "plt.title(\"Spectral Clustering with Normalized Similarity Matrix\")\n", "plt.legend()\n", "plt.show()"