Repository: aeon-toolkit/aeon
Pull request #478 (2023-06-08 10:20:27)

[ENH] Data downloaders for classification/regression and forecasting
#### Reference Issues/PRs

removed the option to return_X_y as one data structure for these loaders, see https://github.com/aeon-toolkit/aeon/issues/383

does not have a writer yet, see #469 

part of #451 

Known problem not addressed here #479 

#### What does this implement/fix? Explain your changes.

Introduces functions to download classification, regression and forecasting problems from 
https://timeseriesclassification.org/
https://forecastingdata.org/
http://tseregression.org/
store them locally and load them into memory. Changes are

1. Unify data lists into separate files in datasets/
2. introduce three loaders in data_loaders.py that pull the data down into ts or tsf format if necessary, load it into memory and return
    "load_classification",
    "load_forecasting",
    "load_regression",
    "download_all_regression",

Not finished yet, but putting it up as draft to get any input. Forecasting repo maintained by @rakshitha123, regression by @ChangWeiTan, we maintain the classification one.

Note some of the tser problems have time stamps, which we cant currently handle. Will adapt code from here to do so
https://github.com/ChangWeiTan/TS-Extrinsic-Regression/blob/master/utils/data_loader.py#L36

The code is a bit convoluted, because of the need to deal with different use cases. Also not tested, since it relies on external sites.  Tested it locally like this 

```python
from aeon.datasets import download_all_regression, load_forecasting, load_regression,\
    load_classification
import urllib
import os
# Use case 1: download new data with just problem name
# Expected: saves the file to aeon/datasets/local_data/<name>/<name>
# Use case 2: load existing problem with just problem name
# Expected: loads the file to aeon/datasets/local_data/<name>/<name>
#           Should work off line
# Use case 3: download new data to a specified path
# Expected: saves the file to path/<name>/<name>
# Use case 4: load existing problem to a specified path
# Expected: Loads the file to path/<name>/<name>
#           Should work off line
# Use case 4: relative file names should work
use_case=3
if use_case == 1:
    # Use case 1: download new data with just problem name
    X, meta=load_forecasting("m1_yearly_dataset")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
    X, y, meta = load_regression("FloodModeling1")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
    X, y, meta = load_classification("Chinatown")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
elif use_case == 2:
# Use case 2: Do offline after 1: load existing problem with just problem name
    X, meta=load_forecasting("m1_yearly_dataset")
    print(" Type of X2 = ", type(X))
    print("Meta = ", meta)
    X, y, meta = load_regression("FloodModeling1")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
    X, y, meta = load_classification("Chinatown")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
elif use_case == 3:
    X, meta=load_forecasting("m1_yearly_dataset", extract_path="Temp/")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
    X, y, meta = load_regression("FloodModeling1",extract_path="Temp/")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
    X, y, meta = load_classification("Chinatown",extract_path="C://Temp/")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
elif use_case == 4:
    # Use case 4: Do offline after 3: load existing problem with just problem name
    X, meta=load_forecasting("m1_yearly_dataset", extract_path="C:/Temp/")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
    X, y, meta = load_regression("FloodModeling1",extract_path="C:/Temp/")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
    X, y, meta = load_classification("Chinatown")
    print(" Type of X = ", type(X))
    print("Meta = ", meta)
```




TonyBagnall: close temporarily for notebook
review-notebook-app[bot]: Check out this pull request on&nbsp; <a href="https://app.reviewnb.com/aeon-toolkit/aeon/pull/478"><img align="absmiddle"  alt="ReviewNB" height="28" class="BotMessageButtonImage" src="https://raw.githubusercontent.com/ReviewNB/support/master/images/button_reviewnb.png"/></a> 

 See visual diffs & provide feedback on Jupyter Notebooks. 

---

 <i>Powered by <a href='https://www.reviewnb.com/?utm_source=gh'>ReviewNB</a></i>

Patch:
diff --git a/aeon/benchmarking/results_loaders.py b/aeon/benchmarking/results_loaders.py
index d45fae5c..5f959199 100644
--- a/aeon/benchmarking/results_loaders.py
+++ b/aeon/benchmarking/results_loaders.py
@@ -11,7 +11,7 @@ __author__ = ["TonyBagnall"]
 import numpy as np
 import pandas as pd
 
-from aeon.datasets.tsc_dataset_names import univariate as UCR
+from aeon.datasets.tsc_data_lists import univariate as UCR
 
 VALID_RESULT_TYPES = ["accuracy", "auroc", "balancedaccuracy"]
 VALID_TASK_TYPES = ["classification", "clustering", "regression"]
@@ -118,7 +118,7 @@ def get_estimator_results(
         list of estimators to search for.
     datasets: list of string default = UCR.
         list of problem names to search for. Default is to look for the 112 UCR
-        datasets listed in aeon.datasets.tsc_dataset_names
+        datasets listed in aeon.datasets.tsc_data_lists
     default_only: boolean, default = True
         whether to recover just the default test results, or 30 resamples
     path: string default https://timeseriesclassification.com/results/ReferenceResults/
@@ -195,7 +195,7 @@ def get_estimator_results_as_array(
         list of estimators to search for.
     datasets: list of string default = UCR.
         list of problem names to search for. Default is to look for the 112 UCR
-        datasets listed in aeon.datasets.tsc_dataset_names
+        datasets listed in aeon.datasets.tsc_data_lists
     default_only: boolean, default = True
         whether to recover just the default test results, or 30 resamples. If false,
         values are averaged to get a 2D array.
diff --git a/aeon/classification/deep_learning/resnet.py b/aeon/classification/deep_learning/resnet.py
index 006ddbae..980d87b9 100644
--- a/aeon/classification/deep_learning/resnet.py
+++ b/aeon/classification/deep_learning/resnet.py
@@ -145,13 +145,11 @@ class ResNetClassifier(BaseDeepClassifier):
     ):
         _check_dl_dependencies(severity="error")
         super(ResNetClassifier, self).__init__(last_file_name=last_file_name)
-        optimizer = (None,)
         self.n_residual_blocks = n_residual_blocks
         self.n_conv_per_residual_block = n_conv_per_residual_block
         self.n_filters = n_filters
         self.kernel_size = kernel_size
         self.padding = padding
-        self.activation = activation
         self.strides = strides
         self.dilation_rate = dilation_rate
         self.n_epochs = n_epochs
@@ -204,12 +202,11 @@ class ResNetClassifier(BaseDeepClassifier):
         output : a compiled Keras Model
         """
         import tensorflow as tf
-        from tensorflow import keras
 
         tf.random.set_seed(self.random_state)
 
         self.optimizer_ = (
-            keras.optimizers.Adam(learning_rate=0.01)
+            tf.keras.optimizers.Adam(learning_rate=0.01)
             if self.optimizer is None
             else self.optimizer
         )
@@ -221,11 +218,11 @@ class ResNetClassifier(BaseDeepClassifier):
 
         input_layer, output_layer = self._network.build_network(input_shape, **kwargs)
 
-        output_layer = keras.layers.Dense(
-            units=n_classes, activation=self.activation, use_bias=self.use_bias
+        output_layer = tf.keras.layers.Dense(
+            units=n_classes, activation="softmax", use_bias=self.use_bias
         )(output_layer)
 
-        model = keras.models.Model(inputs=input_layer, outputs=output_layer)
+        model = tf.keras.models.Model(inputs=input_layer, outputs=output_layer)
         model.compile(
             loss=self.loss,
             optimizer=self.optimizer_,
diff --git a/aeon/datasets/__init__.py b/aeon/datasets/__init__.py
index d714dd24..0a98ab67 100644
--- a/aeon/datasets/__init__.py
+++ b/aeon/datasets/__init__.py
@@ -2,12 +2,15 @@
 """Functions to load and write datasets."""
 
 __all__ = [
-    # Load functions
+    # Load/download functions
     "load_from_tsfile",
     "load_from_tsf_file",
     "load_from_arff_file",
     "load_from_tsv_file",
-    "load_from_tsc_website",
+    "load_classification",
+    "load_forecasting",
+    "load_regression",
+    "download_all_regression",
     # Write functions
     "write_to_tsfile",
     "write_results_to_uea_format",
@@ -49,11 +52,14 @@ from aeon.datasets._data_generators import (
     make_example_multi_index_dataframe,
 )
 from aeon.datasets._data_loaders import (
+    download_all_regression,
+    load_classification,
+    load_forecasting,
     load_from_arff_file,
-    load_from_tsc_website,
     load_from_tsf_file,
     load_from_tsfile,
     load_from_tsv_file,
+    load_regression,
 )
 from aeon.datasets._data_writers import write_results_to_uea_format, write_to_tsfile
 from aeon.datasets._dataframe_loaders import (
diff --git a/aeon/datasets/_data_loaders.py b/aeon/datasets/_data_loaders.py
index b7651163..89cae58e 100644
--- a/aeon/datasets/_data_loaders.py
+++ b/aeon/datasets/_data_loaders.py
@@ -2,6 +2,7 @@
 import os
 import shutil
 import tempfile
+import urllib
 import zipfile
 from datetime import datetime
 from distutils.util import strtobool
@@ -11,7 +12,10 @@ import numpy as np
 import pandas as pd
 
 from aeon.datasets._dataframe_loaders import DIRNAME, MODULE
-from aeon.datasets.tsc_dataset_names import _list_available_datasets
+from aeon.datasets.dataset_collections import (
+    list_downloaded_tsc_tsr_datasets,
+    list_downloaded_tsf_datasets,
+)
 from aeon.datatypes import MTYPE_LIST_HIERARCHICAL, convert
 
 __all__ = [  # Load functions
@@ -19,7 +23,10 @@ __all__ = [  # Load functions
     "load_from_tsf_file",
     "load_from_arff_file",
     "load_from_tsv_file",
-    "load_from_tsc_website",
+    "load_classification",
+    "load_forecasting",
+    "load_regression",
+    "download_all_regression",
 ]
 
 
@@ -89,6 +96,8 @@ def _load_header_info(file):
                     else:
                         raise IOError("invalid class label value")
                     meta_data["class_values"] = [token.strip() for token in tokens[2:]]
+        if meta_data["targetlabel"]:
+            meta_data["classlabel"] = False
     return meta_data
 
 
@@ -231,60 +240,7 @@ def load_from_tsfile(
     return data, y
 
 
-def load_from_tsc_website(
-    name, split=None, return_X_y=True, return_type=None, extract_path=None
-):
-    """Load dataset from tsml archives on timeseriesclassification.com.
-
-    Downloads and extracts dataset if not already downloaded. Data is assumed to be
-    in the standard .ts format: each row is a (possibly multivariate) time series.
-    Each dimension is separated by a colon, each value in a series is comma
-    separated. For examples see aeon.datasets.data.tsc. ArrowHead is an example of
-    a univariate equal length problem, BasicMotions an equal length multivariate
-    problem.
-
-    Parameters
-    ----------
-    name : str
-        Name of data set. If a dataset that is listed in tsc_dataset_names is given,
-        this function will look in the extract_path first, and if it is not present,
-        attempt to download the data from www.timeseriesclassification.com, saving it to
-        the extract_path.
-    split : None or str{"train", "test"}, optional (default=None)
-        Whether to load the train or test partition of the problem. By default it
-        loads both into a single dataset, otherwise it looks only for files of the
-        format <name>_TRAIN.ts or <name>_TEST.ts.
-    return_X_y : bool, optional (default=False)
-        it returns two objects, if False, it appends the class labels to the dataframe.
-    return_type : str, optional, default = None
-        "numpy3D"/"numpy3d"/"np3D": recommended for equal length series
-        "numpy2D"/"numpy2d"/"np2d": can be used for univariate equal length series,
-        although we recommend numpy3d, because some transformers do not work with
-        numpy2d. If None will load 3D numpy or list of numpy
-        There other options, see datatypes.SCITYPE_REGISTER, but these
-        will not necessarily be supported longterm.
-        Exception is raised if the data cannot be stored in the requested type.
-    extract_path : str, optional (default=None)
-        the path to look for the data. If no path is provided, the function
-        looks in `aeon/datasets/data/`. If a path is given, it can be absolute,
-        e.g. C:/Temp or relative, e.g. Temp or ./Temp.
-
-    Returns
-    -------
-    X: np.ndarray or list
-    y: numpy array
-        The class labels for each case in X, returned separately if return_X_y is
-        True, or appended to X if False
-
-    Examples
-    --------
-    >>> from aeon.datasets import load_from_tsc_website
-    >>> X, y = load_from_tsc_website(name="ArrowHead")
-    """
-    return _load_dataset(name, split, return_X_y, return_type, extract_path)
-
-
-def _load_provided_dataset(
+def _load_saved_dataset(
     name,
     split=None,
     return_X_y=True,
@@ -435,7 +391,9 @@ def _download_and_extract(url, extract_path=None):
         )
 
 
-def _load_dataset(name, split, return_X_y=True, return_type=None, extract_path=None):
+def _load_tsc_dataset(
+    name, split, return_X_y=True, return_type=None, extract_path=None, return_meta=False
+):
     """Load time series classification datasets (helper function).
 
     Parameters
@@ -480,12 +438,12 @@ def _load_dataset(name, split, return_X_y=True, return_type=None, extract_path=N
 
     if not os.path.exists(os.path.join(local_module, local_dirname)):
         os.makedirs(os.path.join(local_module, local_dirname))
-    if name not in _list_available_datasets(extract_path):
+    if name not in list_downloaded_tsc_tsr_datasets(extract_path):
         if extract_path is None:
             local_dirname = "local_data"
         if not os.path.exists(os.path.join(local_module, local_dirname)):
             os.makedirs(os.path.join(local_module, local_dirname))
-        if name not in _list_available_datasets(
+        if name not in list_downloaded_tsc_tsr_datasets(
             os.path.join(local_module, local_dirname)
         ):
             # Dataset is not already present in the datasets directory provided.
@@ -508,8 +466,14 @@ def _load_dataset(name, split, return_X_y=True, return_type=None, extract_path=N
                     f"https://timeseriesclassification.com/.",
                 ) from e
 
-    return _load_provided_dataset(
-        name, split, return_X_y, return_type, local_module, local_dirname
+    return _load_saved_dataset(
+        name,
+        split=split,
+        return_X_y=return_X_y,
+        return_type=return_type,
+        local_module=local_module,
+        local_dirname=local_dirname,
+        return_meta=return_meta,
     )
 
 
@@ -542,9 +506,11 @@ def load_tsf_to_dataframe(
         - "tsf_default" = container that faithfully mirrors tsf format from the original
             implementation in: https://github.com/rakshitha123/TSForecasting/
             blob/master/utils/data_loader.py.
-        - other valid return type strings are Panel or Hierarchical  data types in
-            datatypes.MTYPE_REGISTER. If Panel or Hierarchical types str is given, a
-            conversion to that type will be attempted
+        - other valid mtype strings are Panel or Hierarchical mtypes in
+            datatypes.MTYPE_REGISTER. If Panel or Hierarchical mtype str is given, a
+            conversion to that mtype will be attempted
+        For tutorials and detailed specifications, see
+        examples/AA_datatypes_and_datasets.ipynb
 
     Returns
     -------
@@ -792,7 +758,7 @@ def load_from_arff_file(
                             raise ValueError(
                                 f" Number of channels not equal in "
                                 f"dataset, first case had {n_channels} "
-                                f"but case number {n_cases+1} has "
+                                f"but {n_cases+1} case hase "
                                 f"{len(channels)}"
                             )
                         inst = np.zeros(shape=(n_channels, n_timepoints))
@@ -1094,3 +1060,268 @@ def load_from_tsf_file(
             )
         )
         return loaded_data, metadata
+
+
+def load_forecasting(name, extract_path=None, return_metadata=True):
+    """Download/load forecasting problem from https://forecastingdata.org/.
+
+    Parameters
+    ----------
+    name : string, file name to load from
+    extract_path : optional (default = None)
+        Path of the location for the data file. If none, data is written to
+        os.path.dirname(__file__)/data/
+    return_metadata : boolean, default = True
+        If True, returns a tuple (data, metadata)
+
+    Raises
+    ------
+    Raise ValueException if the requested return type is not supported
+
+    Returns
+    -------
+    X: Data stored in a dataframe, each column a series
+    metadata: optional
+        returns the following meta data
+        frequency,forecast_horizon,contain_missing_values,contain_equal_length
+
+    Example
+    -------
+    >>> from aeon.datasets import load_forecasting
+    >>> X, meta=load_forecasting("m1_yearly_dataset") #DOCTEST +skip
+    """
+    # Allow user to have non standard extract path
+    from aeon.datasets.tsf_data_lists import tsf_all
+
+    if extract_path is not None:
+        local_module = os.path.dirname(extract_path)
+        local_dirname = ""
+    else:
+        local_module = MODULE
+        local_dirname = "data"
+
+    if not os.path.exists(os.path.join(local_module, local_dirname)):
+        os.makedirs(os.path.join(local_module, local_dirname))
+    # Check if data already in extract path or, if extract_path None,
+    # in datasets/data directory
+    if name not in list_downloaded_tsf_datasets(extract_path):
+        if extract_path is None:
+            local_dirname = "local_data"
+        if not os.path.exists(os.path.join(local_module, local_dirname)):
+            os.makedirs(os.path.join(local_module, local_dirname))
+        if name not in list_downloaded_tsc_tsr_datasets(
+            os.path.join(local_module, local_dirname)
+        ):
+            # Dataset is not already present in the datasets directory provided.
+            # If it is not there, download and install it.
+            if name in tsf_all.keys():
+                id = tsf_all[name]
+            else:
+                raise ValueError(
+                    f"File name {name} is not in the list of valid files to download"
+                )
+            url = f"https://zenodo.org/record/{id}/files/{name}.zip"
+            file_save = f"{local_module}/{local_dirname}/{name}.zip"
+            if not os.path.exists(file_save):
+                try:
+                    urllib.request.urlretrieve(url, file_save)
+                except Exception:
+                    raise ValueError(
+                        f"Invalid dataset name ={name} is not available on extract path"
+                        f" {extract_path}.\n Nor is it available on "
+                        f"https://forecastingdata.org/ via path {url}",
+                    )
+            if not os.path.exists(
+                f"{local_module}/{local_dirname}/{name}/" f"{name}.tsf"
+            ):
+                z = zipfile.ZipFile(file_save, "r")
+                z.extractall(f"{local_module}/{local_dirname}/{name}/")
+    full_name = f"{local_module}/{local_dirname}/{name}/{name}.tsf"
+    data, meta = load_from_tsf_file(full_file_path_and_name=full_name)
+    if return_metadata:
+        return data, meta
+    return data
+
+
+def load_regression(name, split=None, extract_path=None, return_metadata=True):
+    """Download/load forecasting problem from https://forecastingdata.org/.
+
+    Parameters
+    ----------
+    name : string, file name to load from
+    extract_path : optional (default = None)
+        Path of the location for the data file. If none, data is written to
+        os.path.dirname(__file__)/data/<name>/
+    split : None or str{"train", "test"}, default=None
+        Whether to load the train or test partition of the problem. By default it
+        loads both into a single dataset, otherwise it looks only for files of the
+        format <name>_TRAIN.ts or <name>_TEST.ts.
+    return_metadata : boolean, default = True
+        If True, returns a tuple (X, y, metadata)
+
+    Raises
+    ------
+    Raise ValueException if the requested return type is not supported
+
+    Returns
+    -------
+    X: np.ndarray or list of np.ndarray
+    y: numpy array
+        The target response variable for each case in X
+    metadata: optional
+        returns the following meta data
+        'problemname',timestamps, missing,univariate,equallength.
+        targetlabel should be true, and classlabel false
+
+    Example
+    -------
+    >>> from aeon.datasets import load_regression
+    >>> X, y, meta=load_regression("FloodModeling1") #DOCTEST +Skip
+    """
+    from aeon.datasets.tser_data_lists import tser_all
+
+    if extract_path is not None:
+        local_module = os.path.dirname(extract_path)
+        local_dirname = ""
+    else:
+        local_module = MODULE
+        local_dirname = "data"
+
+    if not os.path.exists(os.path.join(local_module, local_dirname)):
+        os.makedirs(os.path.join(local_module, local_dirname))
+    if name not in list_downloaded_tsc_tsr_datasets(extract_path):
+        if extract_path is None:
+            local_dirname = "local_data"
+        if not os.path.exists(os.path.join(local_module, local_dirname)):
+            os.makedirs(os.path.join(local_module, local_dirname))
+        if name not in list_downloaded_tsc_tsr_datasets(
+            os.path.join(local_module, local_dirname)
+        ):
+            if name in tser_all.keys():
+                id = tser_all[name]
+            else:
+                raise ValueError(
+                    f"File name {name} is not in the list of valid files to download"
+                )
+            # Dataset is not already present in the datasets directory provided.
+            # If it is not there, download and install it.
+            url_train = f"https://zenodo.org/record/{id}/files/{name}_TRAIN.ts"
+            url_test = f"https://zenodo.org/record/{id}/files/{name}_TEST.ts"
+            if not os.path.exists(f"{local_module}/{local_dirname}/{name}"):
+                os.makedirs(f"{local_module}/{local_dirname}/{name}")
+
+            train_save = f"{local_module}/{local_dirname}/{name}/{name}_TRAIN.ts"
+            test_save = f"{local_module}/{local_dirname}/{name}/{name}_TEST.ts"
+            try:
+                urllib.request.urlretrieve(url_train, train_save)
+                urllib.request.urlretrieve(url_test, test_save)
+            except Exception:
+                raise ValueError(
+                    f"Invalid dataset name ={name} one or both of TRAIN and TEST is "
+                    f"not available on path ={local_module}/{local_dirname}/{name}.\n "
+                    f"Nor is it available on tseregression.org via path {url_train} "
+                    f"or {url_test}"
+                )
+    #            zipfile.ZipFile(file_save, "r").extractall(f"{extract_path}/{name}/")
+    return _load_saved_dataset(
+        name=name,
+        split=split,
+        local_module=local_module,
+        local_dirname=local_dirname,
+        return_meta=return_metadata,
+    )
+
+
+def load_classification(name, split=None, extract_path=None, return_metadata=True):
+    """Load a classification dataset.
+
+    Loads a TSC dataset from extract_path, or from timeseriesclassification.com,
+    if not on extract path.
+
+    Data is assumed to be in the standard .ts format: each row is a (possibly
+    multivariate) time series.
+    Each dimension is separated by a colon, each value in a series is comma
+    separated. For examples see aeon.datasets.data.tsc. ArrowHead is an example of
+    a univariate equal length problem, BasicMotions an equal length multivariate
+    problem.
+
+    Data is stored in extract_path/name/name.ts, extract_path/name/name_TRAIN.ts and
+    extract_path/name/name_TEST.ts.
+
+    Parameters
+    ----------
+    name : str
+        Name of data set. If a dataset that is listed in tsc_data_lists is given,
+        this function will look in the extract_path first, and if it is not present,
+        attempt to download the data from www.timeseriesclassification.com, saving it to
+        the extract_path.
+    split : None or str{"train", "test"}, default=None
+        Whether to load the train or test partition of the problem. By default it
+        loads both into a single dataset, otherwise it looks only for files of the
+        format <name>_TRAIN.ts or <name>_TEST.ts.
+    extract_path : str, default=None
+        the path to look for the data. If no path is provided, the function
+        looks in `aeon/datasets/data/`. If a path is given, it can be absolute,
+        e.g. C:/Temp/ or relative, e.g. Temp/ or ./Temp/.
+    return_metadata : boolean, default = True
+        If True, returns a tuple (X, y, metadata)
+
+    Returns
+    -------
+    X: np.ndarray or list of np.ndarray
+    y: numpy array
+        The class labels for each case in X
+    metadata: optional
+        returns the following meta data
+        'problemname',timestamps, missing,univariate,equallength, class_values
+        targetlabel should be false, and classlabel true
+
+    Examples
+    --------
+    >>> from aeon.datasets import load_classification
+    >>> X, y, meta = load_classification(name="ArrowHead") #DOCTEST +Skip
+    """
+    return _load_tsc_dataset(
+        name,
+        split,
+        return_X_y=True,
+        extract_path=extract_path,
+        return_meta=return_metadata,
+    )
+
+
+def download_all_regression(extract_path=None):
+    """Download and unpack all of the Monash TSER datasets.
+
+    Arguments
+    ---------
+    extract_path: str or None, default = None
+        where to download the fip file. If none, it goes in
+    """
+    if extract_path is not None:
+        local_module = os.path.dirname(extract_path)
+        local_dirname = ""
+    else:
+        local_module = MODULE
+        local_dirname = "data"
+
+    if not os.path.exists(os.path.join(local_module, local_dirname)):
+        os.makedirs(os.path.join(local_module, local_dirname))
+    url = (
+        "https://zenodo.org/record/4632512/files/Monash_UEA_UCR_Regression_Archive.zip"
+    )
+    if extract_path is None:
+        local_dirname = "local_data"
+    if not os.path.exists(os.path.join(local_module, local_dirname)):
+        os.makedirs(os.path.join(local_module, local_dirname))
+
+    file_save = f"{local_module}/{local_dirname}/Monash_UEA_UCR_Regression_Archive.zip"
+    # Check if it already exists at this location, to avoid repeated download
+    if not os.path.exists(file_save):
+        try:
+            urllib.request.urlretrieve(url, file_save)
+        except Exception:
+            raise ValueError(
+                f"Unable to download {file_save} from {url}",
+            )
+    zipfile.ZipFile(file_save, "r").extractall(f"{local_module}/{local_dirname}/")
diff --git a/aeon/datasets/_single_problem_loaders.py b/aeon/datasets/_single_problem_loaders.py
index bbbf3fd4..9a7feb3d 100644
--- a/aeon/datasets/_single_problem_loaders.py
+++ b/aeon/datasets/_single_problem_loaders.py
@@ -47,7 +47,7 @@ from warnings import warn
 import numpy as np
 import pandas as pd
 
-from aeon.datasets._data_loaders import _load_dataset, _load_provided_dataset
+from aeon.datasets._data_loaders import _load_saved_dataset, _load_tsc_dataset
 from aeon.datasets._dataframe_loaders import load_tsf_to_dataframe
 from aeon.utils.validation._dependencies import _check_soft_dependencies
 
@@ -98,7 +98,7 @@ def load_gunpoint(split=None, return_X_y=True, return_type="numpy3d"):
     Number of classes:  2
     Details: http://timeseriesclassification.com/description.php?Dataset=GunPoint
     """
-    return _load_dataset("GunPoint", split, return_X_y, return_type=return_type)
+    return _load_tsc_dataset("GunPoint", split, return_X_y, return_type=return_type)
 
 
 def load_osuleaf(split=None, return_X_y=True, return_type="numpy3d"):
@@ -144,7 +144,7 @@ def load_osuleaf(split=None, return_X_y=True, return_type="numpy3d"):
     Number of classes:  6
     Details: http://www.timeseriesclassification.com/description.php?Dataset=OSULeaf
     """
-    return _load_dataset("OSULeaf", split, return_X_y, return_type=return_type)
+    return _load_tsc_dataset("OSULeaf", split, return_X_y, return_type=return_type)
 
 
 def load_italy_power_demand(split=None, return_X_y=True, return_type="numpy3d"):
@@ -192,7 +192,7 @@ def load_italy_power_demand(split=None, return_X_y=True, return_type="numpy3d"):
     Details:http://timeseriesclassification.com/description.php?Dataset=ItalyPowerDemand
     """
     name = "ItalyPowerDemand"
-    return _load_dataset(name, split, return_X_y, return_type=return_type)
+    return _load_tsc_dataset(name, split, return_X_y, return_type=return_type)
 
 
 def load_unit_test(split=None, return_X_y=True, return_type="numpy3d"):
@@ -245,7 +245,7 @@ def load_unit_test(split=None, return_X_y=True, return_type="numpy3d"):
     Details: http://timeseriesclassification.com/description.php?Dataset=Chinatown
     for the full dataset
     """
-    return _load_provided_dataset("UnitTest", split, return_X_y, return_type)
+    return _load_saved_dataset("UnitTest", split, return_X_y, return_type)
 
 
 def load_arrow_head(split=None, return_X_y=True, return_type="numpy3d"):
@@ -292,7 +292,7 @@ def load_arrow_head(split=None, return_X_y=True, return_type="numpy3d"):
     Number of classes:  3
     Details: http://timeseriesclassification.com/description.php?Dataset=ArrowHead
     """
-    return _load_provided_dataset(
+    return _load_saved_dataset(
         name="ArrowHead", split=split, return_X_y=return_X_y, return_type=return_type
     )
 
@@ -340,7 +340,7 @@ def load_acsf1(split=None, return_X_y=True, return_type="numpy3d"):
     Number of classes:  10
     Details: http://www.timeseriesclassification.com/description.php?Dataset=ACSF1
     """
-    return _load_dataset("ACSF1", split, return_X_y, return_type=return_type)
+    return _load_tsc_dataset("ACSF1", split, return_X_y, return_type=return_type)
 
 
 def load_basic_motions(split=None, return_X_y=True, return_type="numpy3d"):
@@ -389,7 +389,7 @@ def load_basic_motions(split=None, return_X_y=True, return_type="numpy3d"):
             f"array, but cannot because it is a multivariate problem. Use "
             f"numpy3d instead"
         )
-    return _load_provided_dataset(
+    return _load_saved_dataset(
         name="BasicMotions", split=split, return_X_y=return_X_y, return_type=return_type
     )
 
@@ -435,7 +435,7 @@ def load_plaid(split=None, return_X_y=True, return_type="np-list"):
     >>> from aeon.datasets import load_plaid
     >>> X, y = load_plaid()
     """
-    return _load_dataset("PLAID", split, return_X_y, return_type=return_type)
+    return _load_tsc_dataset("PLAID", split, return_X_y, return_type=return_type)
 
 
 def load_japanese_vowels(split=None, return_X_y=True, return_type="np-list"):
@@ -475,7 +475,9 @@ def load_japanese_vowels(split=None, return_X_y=True, return_type="np-list"):
     Number of classes:  9
     Details: http://timeseriesclassification.com/description.php?Dataset=JapaneseVowels
     """
-    return _load_dataset("JapaneseVowels", split, return_X_y, return_type=return_type)
+    return _load_tsc_dataset(
+        "JapaneseVowels", split, return_X_y, return_type=return_type
+    )
 
 
 # forecasting data sets
@@ -1091,11 +1093,11 @@ def load_covid_3month(split=None, return_X_y=True, return_type="numpy3d"):
     """
     name = "Covid3Month"
     if return_X_y:
-        X, y = _load_dataset(name, split, return_X_y, return_type)
+        X, y = _load_tsc_dataset(name, split, return_X_y, return_type)
         y = y.astype(float)
         return X, y
     else:
-        X = _load_dataset(name, split, return_X_y, return_type)
+        X = _load_tsc_dataset(name, split, return_X_y, return_type)
         return X
 
 
@@ -1148,9 +1150,9 @@ def load_cardano_sentiment(split=None, return_X_y=True, return_type="numpy3d"):
     """
     name = "CardanoSentiment"
     if return_X_y:
-        X, y = _load_dataset(name, split, return_X_y, return_type)
+        X, y = _load_tsc_dataset(name, split, return_X_y, return_type)
         y = y.astype(float)
         return X, y
     else:
-        X = _load_dataset(name, split, return_X_y, return_type)
+        X = _load_tsc_dataset(name, split, return_X_y, return_type)
         return X
diff --git a/aeon/datasets/data/dataset_lists.py b/aeon/datasets/data/dataset_lists.py
deleted file mode 100644
index 6c471685..00000000
--- a/aeon/datasets/data/dataset_lists.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Lists of datasets provided in this directory."""
-
-classification_data = [
-    "ACSF1",
-    "ArrowHead",
-    "BasicMotions",
-    "ItalyPowerDemand",
-    "OSULeaf",
-    "PLAID",
-]
diff --git a/aeon/datasets/dataset_collections.py b/aeon/datasets/dataset_collections.py
new file mode 100644
index 00000000..7c1b0e6e
--- /dev/null
+++ b/aeon/datasets/dataset_collections.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+"""
+List of datasets available for classification, regression and forecasting archives.
+
+The data can also be used for clustering.
+
+Classification data can be downloaded directly from the timeseriesclassification.com
+archive.
+
+Regression data is and forecasting
+
+
+Classification/Regression
+-------------------------
+Classification data available are listed in tsc_data_lists.py. Regression problems
+are in tser_data_lists.py. The data can be downloaded and loaded with
+>>> from aeon.datasets import load_from_tsfile
+
+If the data is already stored on disk, you can just load it directly
+Metadata is loaded from the file header, and return is optional
+
+into 3D numpy arrays (n_cases, n_channels, n_timepoints) if equal length
+
+Forecasting
+-----------
+
+
+"""
+
+__author__ = ["Tony Bagnall"]
+__all__ = [
+    "list_downloaded_tsc_tsr_datasets",
+    "list_downloaded_tsf_datasets",
+    "list_available_tser_datasets",
+    "list_available_tsf_datasets",
+]
+import os
+
+from aeon.datasets._dataframe_loaders import MODULE
+from aeon.datasets.tsc_data_lists import multivariate, univariate
+from aeon.datasets.tser_data_lists import tser_all
+from aeon.datasets.tsf_data_lists import tsf_all
+
+
+def list_available_tser_datasets(name=None):
+    """List available tser data."""
+    if name is None:  # List them all
+        return sorted(list(tser_all))
+    if name in tser_all:
+        return True
+    return False
+
+
+def list_available_tsf_datasets(name=None):
+    """List available tsf data."""
+    if name is None:  # List them all
+        return sorted(list(tsf_all))
+    if name in tsf_all:
+        return True
+    return False
+
+
+def list_available_tsc_datasets(name=None):
+    """List available tsf data.
+
+    Parameters
+    ----------
+    name: str or None, default = None
+        query dataset name
+
+    Returns
+    -------
+    if name is None
+        return combined list of multivariate and univaraite
+    else
+        return True if name is in either multivariate or univaraite
+    """
+    if name is None:  # List them all
+        merged_set = univariate.union(multivariate)
+        return sorted(list(merged_set))
+    if name in univariate or name in multivariate:
+        return True
+    return False
+
+
+def list_downloaded_tsc_tsr_datasets(extract_path=None):
+    """Return a list of all the currently downloaded datasets.
+
+    To count as available, each directory in extract_path <dir_name> in the
+    extract_path must contain  files called <dir_name>_TRAIN.ts and <dir_name>_TEST.ts.
+
+    Parameters
+    ----------
+    extract_path: string, default None
+        root directory where to look for files, if None defaults to aeon/datasets/data
+
+    Returns
+    -------
+    datasets : List
+        List of the names of datasets downloaded
+
+    """
+    if extract_path is None:
+        data_dir = os.path.join(MODULE, "data")
+    else:
+        data_dir = extract_path
+    datasets = []
+    for name in os.listdir(data_dir):
+        sub_dir = os.path.join(data_dir, name)
+        if os.path.isdir(sub_dir):
+            all_files = os.listdir(sub_dir)
+            if name + "_TRAIN.ts" in all_files and name + "_TEST.ts" in all_files:
+                datasets.append(name)
+    return datasets
+
+
+def list_downloaded_tsf_datasets(extract_path=None):
+    """Return a list of all the currently downloaded datasets.
+
+    To count as available, each directory in extract_path <dir_name> in the
+    extract_path must contain  files called <dir_name>_TRAIN.ts and <dir_name>_TEST.ts.
+
+    Parameters
+    ----------
+    extract_path: string, default None
+        root directory where to look for files, if None defaults to aeon/datasets/data
+
+    Returns
+    -------
+    datasets : List
+        List of the names of datasets downloaded
+
+    """
+    if extract_path is None:
+        data_dir = os.path.join(MODULE, "data")
+    else:
+        data_dir = extract_path
+    datasets = []
+    for name in os.listdir(data_dir):
+        sub_dir = os.path.join(data_dir, name)
+        if os.path.isdir(sub_dir):
+            all_files = os.listdir(sub_dir)
+            if name + ".tsf" in all_files:
+                datasets.append(name)
+    return datasets
diff --git a/aeon/datasets/tsc_dataset_names.py b/aeon/datasets/tsc_data_lists.py
similarity index 84%
rename from aeon/datasets/tsc_dataset_names.py
rename to aeon/datasets/tsc_data_lists.py
index 5b96fa5a..658992ed 100644
--- a/aeon/datasets/tsc_dataset_names.py
+++ b/aeon/datasets/tsc_data_lists.py
@@ -1,7 +1,10 @@
 # -*- coding: utf-8 -*-
+"""Datasets in the UCR/tsml data archives from https://timeseriesclassification.com.
 
-"""
-List of datasets available from the timeseriesclassification.com archive.
+Lists of data available from timeseriesclassification.com. Data is available in .ts
+format, and for some problems, in .arff and .tsv format. For any issues with these
+data, please see
+https://github.com/time-series-machine-learning/tsml-repo
 
 There are four main distinctions: univariate/multivariate equal/unequal length.
 Array univariate lists the 128 UCR problems, as described in [1].
@@ -18,23 +21,17 @@ The UEA  multivariate  time  series  classification  archive, 2018. ArXiv e-prin
 arXiv:1811.00075, 2018
 [3] A. Bagnall, M. Flynn, J. Large, J. Lines and M. Middlehurst.
 On the Usage and Performance of the Hierarchical Vote Collective of Transformation-Based
-Ensembles Version 1.0
-(HIVE-COTE v1.0). Lecture Notes in Computer Science. in proc. 5th Advanced Analytics and
-Learning on Temporal Data
+Ensembles Version 1.0 (HIVE-COTE v1.0). Lecture Notes in Computer Science. in proc.
+5th Advanced Analytics and Learning on Temporal Data
 [4] A. Pasos Ruiz, M. Flynn, J. Large, M. Middlehurst and A. Bagnall.
     The great multivariate time series classification bake off: a review and
     experimental evaluation of recent algorithmic advances,
     Data Mining and Knowledge Discovery, 2020.
-"""
-
-__author__ = ["Tony Bagnall"]
-
-import os
 
-from aeon.datasets._dataframe_loaders import MODULE
+"""
 
-""" 128 UCR univariatetime series classification problems [1]"""
-univariate = [
+""" 128 UCR univariate time series classification problems [1]"""
+univariate = {
     "ACSF1",
     "Adiac",
     "AllGestureWiimoteX",
@@ -162,11 +159,10 @@ univariate = [
     "WordSynonyms",
     "Worms",
     "WormsTwoClass",
-    "Yoga",
-]
+}
 
 """ 33 UEA multivariate time series classification problems [2]"""
-multivariate = [
+multivariate = {
     "ArticularyWordRecognition",
     "AsphaltObstaclesCoordinates",
     "AsphaltPavementTypeCoordinates",
@@ -200,10 +196,10 @@ multivariate = [
     "SpokenArabicDigits",
     "StandWalkJump",
     "UWaveGestureLibrary",
-]
+}
 
-"""113 equal length/no missing univariate time series classification problems [3]"""
-univariate_equal_length = [
+"""112 equal length/no missing univariate time series classification problems [3]"""
+univariate_equal_length = {
     "ACSF1",
     "Adiac",
     "ArrowHead",
@@ -243,7 +239,6 @@ univariate_equal_length = [
     "FordB",
     "FreezerRegularTrain",
     "FreezerSmallTrain",
-    "Fungi",
     "GunPoint",
     "GunPointAgeSpan",
     "GunPointMaleVersusFemale",
@@ -317,10 +312,10 @@ univariate_equal_length = [
     "Worms",
     "WormsTwoClass",
     "Yoga",
-]
+}
 
 """11 variable length univariate time series classification problems [3]"""
-univariate_variable_length = [
+univariate_variable_length = {
     "AllGestureWiimoteX",
     "AllGestureWiimoteY",
     "AllGestureWiimoteZ",
@@ -332,18 +327,18 @@ univariate_variable_length = [
     "PickupGestureWiimoteZ",
     "PLAID",
     "ShakeGestureWiimoteZ",
-]
+}
 
 """4 fixed length univariate time series classification problems with missing values"""
-univariate_missing_values = [
+univariate_missing_values = {
     "DodgerLoopDay",
     "DodgerLoopGame",
     "DodgerLoopWeekend",
     "MelbournePedestrian",
-]
+}
 
 """26 equal length multivariate time series classification problems [4]"""
-multivariate_equal_length = [
+multivariate_equal_length = {
     "ArticularyWordRecognition",
     "AtrialFibrillation",
     "BasicMotions",
@@ -370,10 +365,10 @@ multivariate_equal_length = [
     "SelfRegulationSCP2",
     "StandWalkJump",
     "UWaveGestureLibrary",
-]
+}
 
 """7 variable length multivariate time series classification problems [4]"""
-multivariate_unequal_length = [
+multivariate_unequal_length = {
     "AsphaltObstaclesCoordinates",
     "AsphaltPavementTypeCoordinates",
     "AsphaltRegularityCoordinates",
@@ -381,35 +376,4 @@ multivariate_unequal_length = [
     "InsectWingbeat",
     "JapaneseVowels",
     "SpokenArabicDigits",
-]
-
-
-def _list_available_datasets(extract_path):
-    """Return a list of all the currently downloaded datasets.
-
-    To count as available, each directory <dir_name> in the extract_path must contain
-    files called <dir_name>_TRAIN.ts and <dir_name>_TEST.ts.
-
-    Parameters
-    ----------
-    extract_path: string
-        root directory where to look for files, if None defaults to aeon/datasets/data
-
-    Returns
-    -------
-    datasets : List
-        List of the names of datasets downloaded
-
-    """
-    if extract_path is None:
-        data_dir = os.path.join(MODULE, "data")
-    else:
-        data_dir = extract_path
-    datasets = []
-    for name in os.listdir(data_dir):
-        sub_dir = os.path.join(data_dir, name)
-        if os.path.isdir(sub_dir):
-            all_files = os.listdir(sub_dir)
-            if name + "_TRAIN.ts" in all_files and name + "_TEST.ts" in all_files:
-                datasets.append(name)
-    return datasets
+}
diff --git a/aeon/datasets/tser_data_lists.py b/aeon/datasets/tser_data_lists.py
new file mode 100644
index 00000000..964531b8
--- /dev/null
+++ b/aeon/datasets/tser_data_lists.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+"""Datasets in the Monash tser data archives."""
+
+
+tser_all = {
+    "AppliancesEnergy": 3902637,
+    "HouseholdPowerConsumption1": 3902704,
+    "HouseholdPowerConsumption2": 3902706,
+    "BenzeneConcentration": 3902673,
+    "BeijingPM25Quality": 3902671,
+    "BeijingPM10Quality": 3902667,
+    "LiveFuelMoistureContent": 4632439,
+    "FloodModeling1": 3902694,
+    "FloodModeling2": 3902696,
+    "FloodModeling3": 3902698,
+    "AustraliaRainfall": 3902654,
+    "PPGDalia": 3902728,
+    "IEEEPPG": 3902710,
+    "BIDMCRR": 4001463,
+    "BIDMCHR": 4001456,
+    "BIDMCSpO2": 4001464,
+    "NewsHeadlineSentiment": 3902718,
+    "NewsTitleSentiment": 3902726,
+    "Covid3Month": 3902690,
+}
diff --git a/aeon/datasets/tsf_data_lists.py b/aeon/datasets/tsf_data_lists.py
new file mode 100644
index 00000000..5e80475a
--- /dev/null
+++ b/aeon/datasets/tsf_data_lists.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+"""Datasets in the Monash tser data archives."""
+
+
+tsf_all = {
+    "nn5_daily_dataset_with_missing_values": 4656110,
+    "nn5_daily_dataset_without_missing_values": 4656117,
+    "nn5_weekly_dataset": 4656125,
+    "m1_yearly_dataset": 4656193,
+    "m1_quarterly_dataset": 4656154,
+    "m1_monthly_dataset": 4656159,
+    "m3_yearly_dataset": 4656222,
+    "m3_quarterly_dataset": 4656262,
+    "m3_monthly_dataset": 4656298,
+    "m3_other_dataset": 4656335,
+    "m4_yearly_dataset": 4656379,
+    "m4_quarterly_dataset": 4656410,
+    "m4_monthly_dataset": 4656480,
+    "m4_weekly_dataset": 4656522,
+    "m4_daily_dataset": 4656548,
+    "m4_hourly_dataset": 4656589,
+    "tourism_yearly_dataset": 4656103,
+    "tourism_quarterly_dataset": 4656093,
+    "tourism_monthly_dataset": 4656096,
+    "car_parts_dataset_with_missing_values": 4656022,
+    "car_parts_dataset_without_missing_values": 4656021,
+    "hospital_dataset": 4656014,
+    "weather_dataset": 4654822,
+    "dominick_dataset": 4654802,
+    "fred_md_dataset": 4654833,
+    "solar_10_minutes_dataset": 4656144,
+    "solar_weekly_dataset": 4656151,
+    "solar_4_seconds_dataset": 4656027,
+    "wind_4_seconds_dataset": 4656032,
+    "sunspot_dataset_with_missing_values": 4654773,
+    "sunspot_dataset_without_missing_values": 4654722,
+    "wind_farms_minutely_dataset_with_missing_values": 4654909,
+    "wind_farms_minutely_dataset_without_missing_values": 4654858,
+    "elecdemand_dataset": 4656069,
+    "us_births_dataset": 4656049,
+    "saugeenday_dataset": 4656058,
+    "covid_deaths_dataset": 4656009,
+    "cif_2016_dataset": 4656042,
+    "london_smart_meters_dataset_with_missing_values": 4656072,
+    "london_smart_meters_dataset_without_missing_values": 4656091,
+    "kaggle_web_traffic_dataset_with_missing_values": 4656080,
+    "kaggle_web_traffic_dataset_without_missing_values": 4656075,
+    "kaggle_web_traffic_weekly_dataset": 4656664,
+    "traffic_hourly_dataset": 4656132,
+    "traffic_weekly_dataset": 4656135,
+    "electricity_hourly_dataset": 4656140,
+    "electricity_weekly_dataset": 4656141,
+    "pedestrian_counts_dataset": 4656626,
+    "kdd_cup_2018_dataset_with_missing_values": 4656719,
+    "kdd_cup_2018_dataset_without_missing_values": 4656756,
+    "australian_electricity_demand_dataset": 4659727,
+    "covid_mobility_dataset_with_missing_values": 4663762,
+    "covid_mobility_dataset_without_missing_values": 4663809,
+}
diff --git a/aeon/networks/resnet.py b/aeon/networks/resnet.py
index 230e587a..9d8e0f21 100644
--- a/aeon/networks/resnet.py
+++ b/aeon/networks/resnet.py
@@ -67,7 +67,7 @@ class ResNetNetwork(BaseDeepNetwork):
 
     """
 
-    _tags = {"python_dependencies": ["tensorflow", "keras-self-attention"]}
+    _tags = {"python_dependencies": ["tensorflow"]}
 
     def __init__(
         self,
diff --git a/build_tools/run_examples.sh b/build_tools/run_examples.sh
index 9b9755b7..31bea315 100755
--- a/build_tools/run_examples.sh
+++ b/build_tools/run_examples.sh
@@ -5,8 +5,17 @@ set -euxo pipefail
 
 CMD="jupyter nbconvert --to notebook --inplace --execute --ExecutePreprocessor.timeout=600"
 
+excluded=("examples/datasets/benchmarking_data.ipynb")
+
+# Loop over all notebooks in the examples directory.
 find "examples/" -name "*.ipynb" -print0 |
-  while IFS= read -r -d '' notebook; do
-    echo "Running: $notebook"
-    $CMD "$notebook"
+  while IFS= read -r -d "" notebook; do
+    # Skip notebooks in the excluded list.
+    if printf "%s\0" "${excluded[@]}" | grep -Fxqz -- "$notebook"; then
+      echo "Skipping: $notebook"
+    # Run the notebook.
+    else
+      echo "Running: $notebook"
+      $CMD "$notebook"
+    fi
   done
diff --git a/examples/benchmarking/benchmarking.ipynb b/examples/benchmarking/benchmarking.ipynb
index f2798644..25b1102a 100644
--- a/examples/benchmarking/benchmarking.ipynb
+++ b/examples/benchmarking/benchmarking.ipynb
@@ -28,7 +28,21 @@
    "execution_count": 1,
    "id": "c1bd1038",
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "ename": "ModuleNotFoundError",
+     "evalue": "No module named 'aeon.datasets.tsc_dataset_names'",
+     "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;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mbenchmarking\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mforecasting\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m ForecastingBenchmark\n\u001B[0;32m      2\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mdatasets\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m load_airline\n\u001B[0;32m      3\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mforecasting\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mmodel_selection\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m ExpandingWindowSplitter\n",
+      "File \u001B[1;32mC:\\Code\\aeon\\aeon\\benchmarking\\__init__.py:11\u001B[0m\n\u001B[0;32m      3\u001B[0m __all__ \u001B[38;5;241m=\u001B[39m [\n\u001B[0;32m      4\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mplot_critical_difference\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      5\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mget_available_estimators\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      6\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mget_estimator_results\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      7\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mget_estimator_results_as_array\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      8\u001B[0m ]\n\u001B[0;32m     10\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mbenchmarking\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01m_critical_difference\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m plot_critical_difference\n\u001B[1;32m---> 11\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mbenchmarking\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mresults_loaders\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m (\n\u001B[0;32m     12\u001B[0m     get_available_estimators,\n\u001B[0;32m     13\u001B[0m     get_estimator_results,\n\u001B[0;32m     14\u001B[0m     get_estimator_results_as_array,\n\u001B[0;32m     15\u001B[0m )\n",
+      "File \u001B[1;32mC:\\Code\\aeon\\aeon\\benchmarking\\results_loaders.py:14\u001B[0m\n\u001B[0;32m     11\u001B[0m \u001B[38;5;28;01mimport\u001B[39;00m \u001B[38;5;21;01mnumpy\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m \u001B[38;5;21;01mnp\u001B[39;00m\n\u001B[0;32m     12\u001B[0m \u001B[38;5;28;01mimport\u001B[39;00m \u001B[38;5;21;01mpandas\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m \u001B[38;5;21;01mpd\u001B[39;00m\n\u001B[1;32m---> 14\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mdatasets\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mtsc_dataset_names\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m univariate \u001B[38;5;28;01mas\u001B[39;00m UCR\n\u001B[0;32m     16\u001B[0m VALID_RESULT_TYPES \u001B[38;5;241m=\u001B[39m [\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124maccuracy\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mauroc\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mbalancedaccuracy\u001B[39m\u001B[38;5;124m\"\u001B[39m]\n\u001B[0;32m     17\u001B[0m VALID_TASK_TYPES \u001B[38;5;241m=\u001B[39m [\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mclassification\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mclustering\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mregression\u001B[39m\u001B[38;5;124m\"\u001B[39m]\n",
+      "\u001B[1;31mModuleNotFoundError\u001B[0m: No module named 'aeon.datasets.tsc_dataset_names'"
+     ]
+    }
+   ],
    "source": [
     "from aeon.benchmarking.forecasting import ForecastingBenchmark\n",
     "from aeon.datasets import load_airline\n",
diff --git a/examples/benchmarking/results_loading.ipynb b/examples/benchmarking/results_loading.ipynb
index f2019861..06279aa3 100644
--- a/examples/benchmarking/results_loading.ipynb
+++ b/examples/benchmarking/results_loading.ipynb
@@ -30,12 +30,16 @@
    "execution_count": 1,
    "outputs": [
     {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      " Returns an array with each column an estimator, shape (data_names, classifiers)\n",
-      " By default recovers the default test split results for 112 equal length UCR datasets from ACSF1 to Yoga\n",
-      " Or specify data sets for result recovery. 4 For example, HIVECOTEV2 accuracy ItalyPowerDemand = 0.9698736637512148\n"
+     "ename": "ModuleNotFoundError",
+     "evalue": "No module named 'aeon.datasets.tsc_dataset_names'",
+     "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;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mbenchmarking\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m plot_critical_difference\n\u001B[0;32m      2\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mbenchmarking\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mresults_loaders\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m (\n\u001B[0;32m      3\u001B[0m     get_estimator_results,\n\u001B[0;32m      4\u001B[0m     get_estimator_results_as_array,\n\u001B[0;32m      5\u001B[0m )\n\u001B[0;32m      7\u001B[0m classifiers \u001B[38;5;241m=\u001B[39m [\n\u001B[0;32m      8\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mFreshPRINCEClassifier\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      9\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mHIVECOTEV2\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m     10\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mInceptionTimeClassifier\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m     11\u001B[0m ]\n",
+      "File \u001B[1;32mC:\\Code\\aeon\\aeon\\benchmarking\\__init__.py:11\u001B[0m\n\u001B[0;32m      3\u001B[0m __all__ \u001B[38;5;241m=\u001B[39m [\n\u001B[0;32m      4\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mplot_critical_difference\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      5\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mget_available_estimators\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      6\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mget_estimator_results\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      7\u001B[0m     \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mget_estimator_results_as_array\u001B[39m\u001B[38;5;124m\"\u001B[39m,\n\u001B[0;32m      8\u001B[0m ]\n\u001B[0;32m     10\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mbenchmarking\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01m_critical_difference\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m plot_critical_difference\n\u001B[1;32m---> 11\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mbenchmarking\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mresults_loaders\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m (\n\u001B[0;32m     12\u001B[0m     get_available_estimators,\n\u001B[0;32m     13\u001B[0m     get_estimator_results,\n\u001B[0;32m     14\u001B[0m     get_estimator_results_as_array,\n\u001B[0;32m     15\u001B[0m )\n",
+      "File \u001B[1;32mC:\\Code\\aeon\\aeon\\benchmarking\\results_loaders.py:14\u001B[0m\n\u001B[0;32m     11\u001B[0m \u001B[38;5;28;01mimport\u001B[39;00m \u001B[38;5;21;01mnumpy\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m \u001B[38;5;21;01mnp\u001B[39;00m\n\u001B[0;32m     12\u001B[0m \u001B[38;5;28;01mimport\u001B[39;00m \u001B[38;5;21;01mpandas\u001B[39;00m \u001B[38;5;28;01mas\u001B[39;00m \u001B[38;5;21;01mpd\u001B[39;00m\n\u001B[1;32m---> 14\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01maeon\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mdatasets\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mtsc_dataset_names\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m univariate \u001B[38;5;28;01mas\u001B[39;00m UCR\n\u001B[0;32m     16\u001B[0m VALID_RESULT_TYPES \u001B[38;5;241m=\u001B[39m [\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124maccuracy\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mauroc\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mbalancedaccuracy\u001B[39m\u001B[38;5;124m\"\u001B[39m]\n\u001B[0;32m     17\u001B[0m VALID_TASK_TYPES \u001B[38;5;241m=\u001B[39m [\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mclassification\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mclustering\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mregression\u001B[39m\u001B[38;5;124m\"\u001B[39m]\n",
+      "\u001B[1;31mModuleNotFoundError\u001B[0m: No module named 'aeon.datasets.tsc_dataset_names'"
      ]
     }
    ],
@@ -90,17 +94,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Keys =  dict_keys(['FreshPRINCEClassifier', 'HIVECOTEV2', 'InceptionTimeClassifier'])\n",
-      " Accuracy of HIVECOTEV2 on ItalyPowerDemand =  0.9698736637512148\n"
-     ]
-    }
-   ],
+   "execution_count": null,
+   "outputs": [],
    "source": [
     "hash_table = get_estimator_results(estimators=classifiers)\n",
     "print(\"Keys = \", hash_table.keys())\n",
@@ -127,17 +122,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      " Results are averaged over 30 stratified resamples. \n",
-      " HIVECOTEV2 train test of  Beef = 0.8333333333333334 and averaged over 30 resamples = 0.7655555555555557\n"
-     ]
-    }
-   ],
+   "execution_count": null,
+   "outputs": [],
    "source": [
     "resamples_all, data_names = get_estimator_results_as_array(\n",
     "    estimators=classifiers, default_only=False\n",
@@ -170,17 +156,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
-   "outputs": [
-    {
-     "data": {
-      "text/plain": "<Figure size 1000x160 with 1 Axes>",
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAABCYAAAC0CAYAAABISi1kAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABBH0lEQVR4nO3dd1QU19sH8O/SBSkiIggiir2DoBh7R0Ux9hJRsMSILaLRn7FGE3uNsUYFWwxqjMYOKChgQ8USQI3YFcSChV7u+4dn93XdXbqO5fs5Z48y996ZZ2ZnYffZO8/IhBACREREREREREQS0JI6ACIiIiIiIiL6cjExQURERERERESSYWKCiIiIiIiIiCTDxAQRERERERERSYaJCSIiIiIiIiKSDBMTRERERERERCQZJiaIiIiIiIiISDJMTBARERERERGRZJiYICIiIiIiIiLJMDFBRERERERERJJhYoKIiIiIiIiIJMPEBBERERERERFJhokJIiIiIiIiIpIMExNEREREREREJBkmJoiIiIiIiIhIMkxMEBEREREREZFkmJggIiIiIiIiIskwMUFEREREREREkmFigoiIiIiIiIgkw8QEEREREREREUmGiQkiIiIiIiIikgwTE0REREREREQkGSYmiIiIiIiIiEgyTEwQERERERERkWSYmCAiIiIiIiIiyTAxQURERERERESSYWKCiIiIiIiIiCTDxAQRERERERERSYaJCSIiIiIiIiKSDBMTRJRv27Ztg6enJ+rVqwdLS0vo6urC1NQUDRs2xNy5c/H69WupQySiIsjMzERwcDAmTpwIFxcXmJmZQVdXF1ZWVujatSsOHDggdYhEVAyuXbuGX3/9FYMHD0adOnWgo6MDmUyGOXPmSB0aEX2hZEIIIXUQRPRpaNq0KSIiIlCjRg2UL18e5ubmSEhIwKlTp5CamorKlSsjNDQU5cqVkzpUIiqEoKAgtGvXDgBgZWWFBg0awMjICNHR0bh69SoAYPjw4VizZg1kMpmUoRJREYwbNw7Lly9XWT579mxMnTpVgoiI6EunI3UARPTpWLx4MapUqQJzc3Ol5U+fPkW3bt0QFhYGX19f/PHHHxJFSERFoaWlhR49emDs2LFo1qyZUtuff/6JAQMGYN26dWjSpAk8PT0lipKIiqp27dqYMGECHB0d4eTkhF9++QVbtmyROiwi+oJxxgQRFYuTJ0+iefPmMDc3x9OnT6UOh4jeg6FDh2LDhg1o06YNgoKCpA6HiIrJ4MGD4e/vzxkTRCQZ1pggomKho/NmApa+vr7EkRDR++Lo6AgAuHfvnsSREBER0eeEiQkiKrJXr15h5syZAICuXbtKGwwRvTc3btwAAFhbW0scCREREX1OWGOCiArs6NGj2L59O3JychTFL1+9egU3NzfMnz9f6vCI6D2Ij4+Hn58fAKBHjx7SBkNERESfFSYmiKjAoqOj4e/vr7Ssf//+WLJkCUxNTSWKiojel6ysLHzzzTd48eIF6tSpg2+//VbqkIiIiOgzwks5iKjAxo0bByEEMjIy8N9//2Hx4sU4dOgQatasiRMnTkgdHhEVsxEjRiA4OBilS5fGrl27oKenJ3VIRERE9BlhYoKICk1XVxcODg4YP348Dh06hOfPn+Obb75Bamqq1KERUTEZO3YsNmzYgFKlSiEwMBBVq1aVOiQiIiL6zDAxQUTFolGjRqhZsybu3buHyMhIqcMhomLg6+uLFStWwMzMDEePHlXclYOIiIioODExQUTFxsjICADw+PFjiSMhoqL64YcfFHVjjh49CmdnZ6lDIiIios8UExNEVCyePHmCS5cuAQCnehN94iZPnoyFCxfC1NQUgYGBcHFxkTokIiIi+owxMUFE+RIdHY1t27YhLS1Npe369evo1asX0tPT4erqijp16kgQIREVh6lTp2L+/PkwMzNjUoKIiIg+CJkQQkgdBBF9/EJCQtCqVSsYGRnB0dERtra2yMjIwN27d3HhwgXk5OSgRo0aOHz4MOzs7KQOl4gKYd++ffDw8AAAODs7o1atWmr7WVhYYNGiRR8yNCIqRhcuXMDIkSMVP9+8eRNPnjyBra0tbGxsFMv37NkDa2trKUIkoi8MExNElC+JiYlYv349Tp48idjYWCQmJiIzMxPm5uaoU6cOunfvDi8vL+jr60sdKhEVkp+fH7y8vPLsV6FCBdy+ffv9B0RE74X8y4a83Lp1C/b29u8/ICL64jExQURERERERESSYY0JIiIiIiIiIpIMExNEREREREREJBkmJoiIiIiIiIhIMkxMEBEREREREZFkmJggIiIiIiIiIskwMUFEREREREREkmFigoiIiIiIiIgkw8QEERWKs7MzbG1t4ezsLHUoRPSe8HVO9Pnj65yIPgY6UgdARJ+m+Ph4PHjwQOowiOg94uuc6PPH1zkRfQw4Y4KIiIiIiIiIJMPEBBERERERERFJhokJIiIiIiIiIpIMExNEREREREREJBkmJoiIiIiIiIhIMkxMEBEREREREZFkmJggIqJ84b3uiT5/fJ0TEZEUdKQOgIiIPg281z3R54+vcyIikgJnTBARERERERGRZJiYICIiIiIiIiLJMDFBRERERERERJJhYoKIiIiIiIiIJMPEBBERERERERFJRiaEEFIHQUSfHj09PWRmZkJLSwvW1tZSh0MfwKNHj5CTk/NJPeePHz9GdnY2tLW1YWlpKXU4kinscfgUn/PPhVTnLp/zL4/8OdfV1UVGRobU4RDRF4qJCSIqFG1tbeTk5EgdBhERERUDLS0tZGdnSx0GEX2hdKQOgIg+TQYGBkhLS/viv4n+knyKsw/47e8bhT0On+Jz/rmQ6tzlc/7lkT/nBgYGUodCRF8wzpggIqLPlq2tLR48eAAbGxvcv39f6nAkw+Pw6eFzRkREXxIWvyQiIiIiIiIiyTAxQURERERERESSYWKCiIiIiIiIiCTDxAQRERERERERSYaJCSIiIiIiIiKSDBMTRERERERERCQZJiaIiIiIiIiISDJMTBARERERERGRZJiYICIiIiIiIiLJMDFBRERERERERJJhYoKIiIiIiIiIJMPEBBERERERERFJhokJIiIiIiIiIpIMExNEREREREREJBkmJoiIiIiIiIhIMkxMEBEREREREZFkmJggIiIiIiIiIskwMUFEREREREREkmFigoiIiIiIiIgkoyN1AERERMVl2LBhuHr1quLnx48fK/5t3LixVGFJTt1xqF27NtavXy9lWEREREQAmJggIqLPyNWrV3H69GmV5ZmZmWqXf2l4HIiIiOhjxEs5iIiIiIiIiEgyTEwQERERERERkWSYmCAiIiIiIiIiybDGBNEXau7cufjrr78QGxuLEiVK4KuvvsL8+fNRrVo1jWP++usv/PLLL/jvv/+QmZmJKlWqwNfXFwMHDgTw5vr1qVOn4uDBg4iLi4OpqSnatm2LefPmoVy5cor1/Pzzzzhw4ACioqKgp6eHpKQkjdt8+vQp6tWrhwcPHuD58+cwMzMrrkNAn6HatWsr/Xz+/HlkZmZCV1cXDRo0kCgq6ak7Du8eKyL6eJw4cQILFy7E+fPn8ejR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uHnzJkaPHo1Tp04p7n7yti5dumDmzJlwcXFBXFwc/vrrL4SEhMDU1BSTJ0/G1atXUb9+fUX/n3/+Gd999x3MzMxw+vRp7Ny5E9HR0WjUqBH8/f1x+PDh95IMeFu5cuVw+vRprFmzBg0bNsS1a9ewa9cuxayTESNG4MiRI0ozhYqTTHws5WSJiIiIiIgkNHPmTMyaNQszZszAzJkzpQ6H6IvBGRNEREREREREJBkmJoiIiIiIiIhIMkxMEBEREREREZFkWGOCiIiIiIiIiCTDGRNEREREREREJBkmJoiIiIiIiIhIMkxMEBEREREREZFkmJggIiIiIiIiIskwMUFEREREREREkmFigoiIiIiIiIgkw8QEEREREREREUmGiQkiIiIiIiIikgwTE0REREREREQkGSYmiIiIiIiIiEgyTEwQERERERERkWSYmCAiIiIiIiIiyTAxQURERERERESSYWKCiIiIiIiIiCTDxAQRERERERERSYaJCSIiIiIiIiKSDBMTRERERERERCQZJiaIiIiIiIiISDJMTBARERERERGRZJiYICIiIiIiIiLJMDFBRERERERERJJhYoKIiIiIiIiIJMPEBBERERERERFJhokJIiIiIiIiIpIMExNEREREREREJBkmJoiIiIiIiIhIMkxMEBEREREREZFkmJggIiIiIiIiIskwMUFEREREREREkmFigoiIiIiIiIgkw8QEEREREREREUmGiQkiIiIiIiIikgwTE0REREREREQkGSYmiIiIiIiIiEgyTEwQERERERERkWT+D3HSiGeri1MIAAAAAElFTkSuQmCC"
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
+   "execution_count": null,
+   "outputs": [],
    "source": [
     "plot_critical_difference(default_split_all, classifiers)"
    ],
@@ -221,29 +198,8 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "  FreshPRINCE\n",
-      "0         HC2\n",
-      "1    Hydra-MR\n",
-      "2  InceptionT\n",
-      "3          PF\n",
-      "4        RDST\n",
-      "5       RSTSF\n",
-      "6    WEASEL_D\n",
-      "Empty DataFrame\n",
-      "Columns: [FreshPRINCE]\n",
-      "Index: []\n",
-      "Empty DataFrame\n",
-      "Columns: [KMeans]\n",
-      "Index: []\n"
-     ]
-    }
-   ],
+   "execution_count": null,
+   "outputs": [],
    "source": [
     "from aeon.benchmarking import get_available_estimators\n",
     "\n",
diff --git a/examples/datasets/benchmarking_data.ipynb b/examples/datasets/benchmarking_data.ipynb
new file mode 100644
index 00000000..8ff708c8
--- /dev/null
+++ b/examples/datasets/benchmarking_data.ipynb
@@ -0,0 +1,352 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "source": [
+    "# Downloading and loading benchmarking datasets\n",
+    "\n",
+    "It is common to use standard collections of data to compare different estimators for\n",
+    "classification, clustering, regression and forecasting. Some of these datasets are\n",
+    "shipped with aeon in the datasets/data directory. However, the files are far too\n",
+    "big to include them all. aeon p[rovides tools to download these data to use in benchmarking experiments.\n",
+    "Classification and regression data are stored in .ts format. Forecasting\n",
+    "data are stored in the equivalent .tsf format. See the [data formats notebook](examples/data_formats.ipynb) for more info.\n",
+    "\n",
+    "Classification and regression are loaded into 3D numpy arrays of shape `(n_cases, n_channels, n_timepoints)` if equal length\n",
+    "or a list of `[n_cases]` of 2D numpy if `n_timepoints` is different for different\n",
+    "cases. Forecasting data are loaded into pd.DataFrame. For more information on\n",
+    "aeon data types see the [data storage notebook](examples/data_storage.ipynb).\n",
+    "\n",
+    "Note that this notebook is dependent on external websites, so will not function if\n",
+    "you are not online or the associated website is down. We use the following three\n",
+    "functions"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "outputs": [],
+   "source": [
+    "from aeon.datasets import load_classification, load_forecasting, load_regression"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## Time Series Classification Archive\n",
+    "\n",
+    "[UCR/TSML Time Series Classification Archive](https://timeseriesclassification.com)\n",
+    "hosts the UCR univariate TSC archive [1], also available from [UCR](ucrweb) and\n",
+    "the multivariate archive [2] (previously called the UEA archive, soon to change). We\n",
+    "provide seven of these in the datasets/data directort: ACSF1, ArrowHead, BasicMotions,\n",
+    "GunPoint, ItalyPowerDemand, JapaneseVowels and PLAID. The archive is much bigger. The\n",
+    " last batch release was for 128 univariate [1] and 33 multivariate [2]. If you just\n",
+    " want to download them all, please go to the [website]\n",
+    " (https://timeseriesclassification.com)"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Univariate length =  127\n",
+      "Multivariate length =  33\n"
+     ]
+    }
+   ],
+   "source": [
+    "from aeon.datasets.tsc_data_lists import multivariate, univariate\n",
+    "\n",
+    "# This file also contains sub lists by type, e.g. unequal length\n",
+    "print(\"Univariate length = \", len(univariate))\n",
+    "print(\"Multivariate length = \", len(multivariate))"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "A default train and test split is provided for this data. The file structure for a\n",
+    "problem such as Chinatown is\n",
+    "\n",
+    "        <extract_path>/Chinatown/Chinatown_TRAIN.ts\n",
+    "        <extract_path>/Chinatown/Chinatown_TEST.ts\n",
+    "\n",
+    "You can load these problems directly from TSC.com and load them into memory. Note by\n",
+    "default, these functions return the data and associated metadata. This usage combines\n",
+    " the train and test splits and loads them into one `X` and one `y` array."
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Shape of X =  (363, 1, 24)\n",
+      "First case =  [ 573.  375.  301.  212.   55.   34.   25.   33.  113.  143.  303.  615.\n",
+      " 1226. 1281. 1221. 1081.  866. 1096. 1039.  975.  746.  581.  409.  182.]  has label =  1\n",
+      "\n",
+      "Meta data =  {'problemname': 'chinatown', 'timestamps': False, 'missing': False, 'univariate': True, 'equallength': True, 'classlabel': True, 'targetlabel': False, 'class_values': ['1', '2']}\n"
+     ]
+    }
+   ],
+   "source": [
+    "X, y, meta = load_classification(\"Chinatown\")\n",
+    "print(\"Shape of X = \", X.shape)\n",
+    "print(\"First case = \", X[0][0], \" has label = \", y[0])\n",
+    "print(\"\\nMeta data = \", meta)"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "If you look in aeon/datasets you should see a directory called `local_data`\n",
+    "containing the Chinatown datasets. All of the zips have `.ts` files. Some also have\n",
+    "`.arff` and `.txt` files. If you load again, it will not download again if the file is\n",
+    "already there. If you want to store data somewhere else, you can specify a file path.\n",
+    " Also, you can load the train and test separately. This code will download the data\n",
+    " to Temp once, and load into separate train/test splits. The split argument is not\n",
+    " case sensitive. Once downloaded, `load_classification` is a equivalent to a call to\n",
+    " `load_from_tsfile`"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Train shape =  (20, 1, 512)\n",
+      "Test shape =  (20, 1, 512)\n",
+      "Loaded directly shape =  (20, 1, 512)\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": "array([1.7400873, 1.7331051, 1.7091917, 1.6333304, 1.5405759])"
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "X_train, y_train = load_classification(\n",
+    "    \"BeetleFly\", extract_path=\"C://Temp/\", split=\"TRAIN\", return_metadata=False\n",
+    ")\n",
+    "X_test, y_test = load_classification(\n",
+    "    \"BeetleFly\", extract_path=\"C://Temp/\", split=\"test\", return_metadata=False\n",
+    ")\n",
+    "print(\"Train shape = \", X_train.shape)\n",
+    "print(\"Test shape = \", X_test.shape)\n",
+    "from aeon.datasets import load_from_tsfile\n",
+    "\n",
+    "X_train, y_train = load_from_tsfile(\n",
+    "    full_file_path_and_name=\"C://Temp/BeetleFly/BeetleFLY_TRAIN\"\n",
+    ")\n",
+    "print(\"Loaded directly shape = \", X_train.shape)\n",
+    "\n",
+    "X_test[0][0][:5]"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## Time Series (Extrinsic) Regression\n",
+    "\n",
+    "[The Monash Time Series Extrinsic Regression Archive]() [3] repo (called extrinsic to\n",
+    " diffentiate if from sliding window based regression) currently contains 19\n",
+    " regression problems in .ts format. One of these, Covid3Month, is in `datasets\\data`.\n",
+    "  The usage of `load_regression` is identical to `load_classification`\n"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['AppliancesEnergy',\n 'AustraliaRainfall',\n 'BIDMCHR',\n 'BIDMCRR',\n 'BIDMCSpO2',\n 'BeijingPM10Quality',\n 'BeijingPM25Quality',\n 'BenzeneConcentration',\n 'Covid3Month',\n 'FloodModeling1',\n 'FloodModeling2',\n 'FloodModeling3',\n 'HouseholdPowerConsumption1',\n 'HouseholdPowerConsumption2',\n 'IEEEPPG',\n 'LiveFuelMoistureContent',\n 'NewsHeadlineSentiment',\n 'NewsTitleSentiment',\n 'PPGDalia']"
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from aeon.datasets.dataset_collections import list_available_tser_datasets\n",
+    "\n",
+    "list_available_tser_datasets()"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Shape of X =  (673, 1, 266)\n"
+     ]
+    }
+   ],
+   "source": [
+    "X, y, meta = load_regression(\"FloodModeling1\")\n",
+    "print(\"Shape of X = \", X.shape)"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## Time Series Forecasting\n",
+    "\n",
+    "The [Monash time series forecasting](https://forecastingdata.org/) repo contains a\n",
+    "large number of forecasting data, including competition data such as M1, M3 and M4.\n",
+    "Usage is the same as the other problems, although there is no provided train/test\n",
+    "splits.\n"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['australian_electricity_demand_dataset',\n 'car_parts_dataset_with_missing_values',\n 'car_parts_dataset_without_missing_values',\n 'cif_2016_dataset',\n 'covid_deaths_dataset',\n 'covid_mobility_dataset_with_missing_values',\n 'covid_mobility_dataset_without_missing_values',\n 'dominick_dataset',\n 'elecdemand_dataset',\n 'electricity_hourly_dataset',\n 'electricity_weekly_dataset',\n 'fred_md_dataset',\n 'hospital_dataset',\n 'kaggle_web_traffic_dataset_with_missing_values',\n 'kaggle_web_traffic_dataset_without_missing_values',\n 'kaggle_web_traffic_weekly_dataset',\n 'kdd_cup_2018_dataset_with_missing_values',\n 'kdd_cup_2018_dataset_without_missing_values',\n 'london_smart_meters_dataset_with_missing_values',\n 'london_smart_meters_dataset_without_missing_values',\n 'm1_monthly_dataset',\n 'm1_quarterly_dataset',\n 'm1_yearly_dataset',\n 'm3_monthly_dataset',\n 'm3_other_dataset',\n 'm3_quarterly_dataset',\n 'm3_yearly_dataset',\n 'm4_daily_dataset',\n 'm4_hourly_dataset',\n 'm4_monthly_dataset',\n 'm4_quarterly_dataset',\n 'm4_weekly_dataset',\n 'm4_yearly_dataset',\n 'nn5_daily_dataset_with_missing_values',\n 'nn5_daily_dataset_without_missing_values',\n 'nn5_weekly_dataset',\n 'pedestrian_counts_dataset',\n 'saugeenday_dataset',\n 'solar_10_minutes_dataset',\n 'solar_4_seconds_dataset',\n 'solar_weekly_dataset',\n 'sunspot_dataset_with_missing_values',\n 'sunspot_dataset_without_missing_values',\n 'tourism_monthly_dataset',\n 'tourism_quarterly_dataset',\n 'tourism_yearly_dataset',\n 'traffic_hourly_dataset',\n 'traffic_weekly_dataset',\n 'us_births_dataset',\n 'weather_dataset',\n 'wind_4_seconds_dataset',\n 'wind_farms_minutely_dataset_with_missing_values',\n 'wind_farms_minutely_dataset_without_missing_values']"
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from aeon.datasets.dataset_collections import list_available_tsf_datasets\n",
+    "\n",
+    "list_available_tsf_datasets()"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(23000, 3)\n",
+      "{'frequency': 'yearly', 'forecast_horizon': 6, 'contain_missing_values': False, 'contain_equal_length': False}\n",
+      "  series_name     start_timestamp  \\\n",
+      "0          T1 1979-01-01 12:00:00   \n",
+      "1          T2 1979-01-01 12:00:00   \n",
+      "2          T3 1979-01-01 12:00:00   \n",
+      "3          T4 1979-01-01 12:00:00   \n",
+      "4          T5 1979-01-01 12:00:00   \n",
+      "\n",
+      "                                        series_value  \n",
+      "0  [5172.1, 5133.5, 5186.9, 5084.6, 5182.0, 5414....  \n",
+      "1  [2070.0, 2104.0, 2394.0, 1651.0, 1492.0, 1348....  \n",
+      "2  [2760.0, 2980.0, 3200.0, 3450.0, 3670.0, 3850....  \n",
+      "3  [3380.0, 3670.0, 3960.0, 4190.0, 4440.0, 4700....  \n",
+      "4  [1980.0, 2030.0, 2220.0, 2530.0, 2610.0, 2720....  \n"
+     ]
+    }
+   ],
+   "source": [
+    "X, metadata = load_forecasting(\"m4_yearly_dataset\")\n",
+    "print(X.shape)\n",
+    "print(metadata)\n",
+    "data = X.head()\n",
+    "print(data)"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## References\n",
+    "[1] Dau et. al, The UCR time series archive, IEEE/CAA Journal of Automatica Sinica, 2019\n",
+    "[2] Ruiz et. al, The great multivariate time series classification bake off: a review\n",
+    " and experimental evaluation of recent algorithmic advances, Data Mining and\n",
+    " Knowledge Discovery 35(2), 2021\n",
+    "[3] Tan et. al, Time Series Extrinsic Regression, Data Mining and Knowledge\n",
+    "Discovery, 2021\n",
+    "[4] Godahewa et. al, Monash Time Series Forecasting Archive,Neural Information\n",
+    "Processing Systems Track on Datasets and Benchmarks, 2021\n"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 2
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython2",
+   "version": "2.7.6"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
diff --git a/examples/datasets/data_loading.ipynb b/examples/datasets/data_loading.ipynb
index fccb3fec..6dd0b657 100644
--- a/examples/datasets/data_loading.ipynb
+++ b/examples/datasets/data_loading.ipynb
@@ -305,7 +305,7 @@
     "You can also load `.ts` data directly from [tsc.com] (https://timeseriesclassification\n",
     ".com) using the function\n",
     "\n",
-    "    def load_from_tsc_website(\n",
+    "    def load_classification(\n",
     "        name, split=None, return_X_y=True, return_type=None, extract_path=None\n",
     "    ):\n",
     "\n",
@@ -320,23 +320,25 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": 1,
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      " Shape of X =  (211, 1, 251)\n"
+      " Shape of X =  (211, 1, 251)\n",
+      " Meta data =  {'problemname': 'arrowhead', 'timestamps': False, 'missing': False, 'univariate': True, 'equallength': True, 'classlabel': True, 'targetlabel': False, 'class_values': ['0', '1', '2']}\n"
      ]
     }
    ],
    "source": [
-    "from aeon.datasets import load_from_tsc_website\n",
+    "from aeon.datasets import load_classification\n",
     "\n",
     "# This will not download, because Arrowhead is already in the directory.\n",
     "# Change the extract path or name to downloads\n",
-    "X, y = load_from_tsc_website(\"ArrowHead\")\n",
-    "print(\" Shape of X = \", X.shape)"
+    "X, y, meta_data = load_classification(\"ArrowHead\")\n",
+    "print(\" Shape of X = \", X.shape)\n",
+    "print(\" Meta data = \", meta_data)"
    ],
    "metadata": {
     "collapsed": false
diff --git a/examples/datasets/provided_data.ipynb b/examples/datasets/provided_data.ipynb
index 8f2f24fc..5ab55004 100644
--- a/examples/datasets/provided_data.ipynb
+++ b/examples/datasets/provided_data.ipynb
@@ -225,10 +225,6 @@
     "\n",
     "Uschange\n",
     "\n",
-    "### Loading other datasets\n",
-    "\n",
-    "ADD LOAD M4\n",
-    "\n",
     "## Machine Learning\n",
     "\n",
     "### Provided datasets\n",


Test patch:
diff --git a/aeon/datasets/tests/test_data_loaders.py b/aeon/datasets/tests/test_data_loaders.py
index 46f9835f..5d47e003 100644
--- a/aeon/datasets/tests/test_data_loaders.py
+++ b/aeon/datasets/tests/test_data_loaders.py
@@ -26,7 +26,7 @@ from aeon.datasets._data_generators import (
     _convert_tsf_to_hierarchical,
     make_example_long_table,
 )
-from aeon.datasets._data_loaders import DIRNAME, MODULE, _load_provided_dataset
+from aeon.datasets._data_loaders import DIRNAME, MODULE, _load_saved_dataset
 from aeon.datatypes import check_is_mtype
 
 
@@ -38,10 +38,10 @@ def test_load_provided_dataset(return_X_y, return_type):
     Check all possibilities of return_X_y and return_type.
     """
     if return_X_y:
-        X, y = _load_provided_dataset("UnitTest", "TRAIN", return_X_y, return_type)
+        X, y = _load_saved_dataset("UnitTest", "TRAIN", return_X_y, return_type)
         assert isinstance(y, np.ndarray)
     else:
-        X = _load_provided_dataset("UnitTest", "TRAIN", return_X_y, return_type)
+        X = _load_saved_dataset("UnitTest", "TRAIN", return_X_y, return_type)
     if not return_X_y or return_type == "nested_univ":
         assert isinstance(X, pd.DataFrame)
     elif return_type == "numpy3D":
@@ -471,7 +471,7 @@ def test_convert_tsf_to_multiindex(freq):
 
 def test_load_from_ucr_tsv():
     """Test that GunPoint is the same when loaded from .ts and .tsv"""
-    X, y = _load_provided_dataset("GunPoint", split="TRAIN")
+    X, y = _load_saved_dataset("GunPoint", split="TRAIN")
     data_path = MODULE + "/" + DIRNAME + "/GunPoint/GunPoint_TRAIN.tsv"
     X2, y2 = load_from_tsv_file(data_path)
     y = y.astype(float)
@@ -481,7 +481,7 @@ def test_load_from_ucr_tsv():
 
 def test_load_from_arff():
     """Test that GunPoint is the same when loaded from .ts and .arff"""
-    X, y = _load_provided_dataset("GunPoint", split="TRAIN")
+    X, y = _load_saved_dataset("GunPoint", split="TRAIN")
     data_path = MODULE + "/" + DIRNAME + "/GunPoint/GunPoint_TRAIN.arff"
     X2, y2 = load_from_arff_file(data_path)
     np.testing.assert_array_almost_equal(X, X2, decimal=4)
diff --git a/aeon/tests/_config.py b/aeon/tests/_config.py
index 0cbad741..4864ce8a 100644
--- a/aeon/tests/_config.py
+++ b/aeon/tests/_config.py
@@ -26,7 +26,6 @@ EXCLUDE_ESTIMATORS = [
     # tapnet based estimators fail stochastically for unknown reasons, see #3525
     "TapNetRegressor",
     "TapNetClassifier",
-    "ResNetClassifier",  # known ResNetClassifier sporafic failures, see #3954
 ]
 
 EXCLUDED_TESTS = {