Skill Tracer
Skills › Scientific Agent Skills › aeon › datasets_benchmarking.md

datasets_benchmarking.md

176 lines · skills/aeon/references/datasets_benchmarking.md at 5f2bc03

Open on GitHub
1# Datasets and Benchmarking
2
3Targets aeon 1.6. Generic archive loaders may download data on first use; use an explicit writable `extract_path` to control caching. Bundled helpers such as `load_gunpoint`, `load_covid_3month`, and `load_airline` are convenient for offline checks. Archive download examples below are illustrative and were not executed in this review.
4

Datasets and Benchmarking

Targets aeon 1.6. Generic archive loaders may download data on first use; use an explicit writable extract_path to control caching. Bundled helpers such as load_gunpoint, load_covid_3month, and load_airline are convenient for offline checks. Archive download examples below are illustrative and were not executed in this review.

Raw lines 1 to 4
5## Classification and regression
6
7```python
8from aeon.datasets import load_classification, load_regression
9
10X_train, y_train = load_classification(
11 "GunPoint", split="train", extract_path="data/aeon"
13X_test, y_test = load_classification(
14 "GunPoint", split="test", extract_path="data/aeon"
16X_reg, y_reg, metadata = load_regression(
17 "Covid3Month", split="train", extract_path="data/aeon", return_metadata=True
19```
21Equal-length collections normally have shape `(n_cases, n_channels, n_timepoints)`; unequal-length data use lists of 2D arrays. Check the returned metadata and estimator capabilities before padding, imputing, or normalizing. `Covid3Month` is a time-series **regression** benchmark with a target per case, not an API for rolling COVID forecasts.
23```python
24from aeon.datasets import load_gunpoint, load_covid_3month, load_airline
26X_train, y_train = load_gunpoint(split="train")
27X_test, y_test = load_gunpoint(split="test")
28X_reg, y_reg = load_covid_3month(split="train")
29y_airline = load_airline()
30```
32Aeon 1.6 classification/regression loaders resolve published TSML records on Zenodo. They inspect record metadata and download the record's files; a requested dataset can therefore entail more than a single small file. `download_all_regression(extract_path=...)` explicitly downloads the full archive and is unsuitable for a smoke test.

Classification and regression

from aeon.datasets import load_classification, load_regression

X_train, y_train = load_classification(
    "GunPoint", split="train", extract_path="data/aeon"
)
X_test, y_test = load_classification(
    "GunPoint", split="test", extract_path="data/aeon"
)
X_reg, y_reg, metadata = load_regression(
    "Covid3Month", split="train", extract_path="data/aeon", return_metadata=True
)

Equal-length collections normally have shape (n_cases, n_channels, n_timepoints); unequal-length data use lists of 2D arrays. Check the returned metadata and estimator capabilities before padding, imputing, or normalizing. Covid3Month is a time-series regression benchmark with a target per case, not an API for rolling COVID forecasts.

from aeon.datasets import load_gunpoint, load_covid_3month, load_airline

X_train, y_train = load_gunpoint(split="train")
X_test, y_test = load_gunpoint(split="test")
X_reg, y_reg = load_covid_3month(split="train")
y_airline = load_airline()

Aeon 1.6 classification/regression loaders resolve published TSML records on Zenodo. They inspect record metadata and download the record's files; a requested dataset can therefore entail more than a single small file. download_all_regression(extract_path=...) explicitly downloads the full archive and is unsuitable for a smoke test.

Raw lines 5 to 33
34## Forecasting and anomaly archives
36```python
37from aeon.datasets import load_forecasting
39# Returns a dataframe and metadata, not (y, exogenous_X).
40frame, metadata = load_forecasting(
41 "m1_yearly_dataset", extract_path="data/aeon", return_metadata=True
43y = frame.iloc[0]["series_value"]
44```
46`load_forecasting` uses names from `aeon.datasets.tsf_datasets.tsf_all`, not arbitrary dataset nicknames; the `return_X_y` argument is unsupported. The default dataframe represents TSF records, with each series stored in its `series_value` field. Respect per-series forecast horizons/frequency from metadata.
48```python
49from aeon.datasets import load_anomaly_detection
51X, labels = load_anomaly_detection(
52 ("KDD-TSAD", "001_UCR_Anomaly_DISTORTED1sddb40"),
53 split="test", extract_path="data/aeon",
55```
57The anomaly loader requires `(collection_name, dataset_name)`. It downloads a whole TimeEval collection ZIP when necessary; some datasets have no training split. Returned multivariate data are **timepoints by channels**, and labels are one binary indicator per timepoint. Pass `axis=0` to compatible series estimators. A test label file must not enter training or threshold calibration.

Forecasting and anomaly archives

from aeon.datasets import load_forecasting

# Returns a dataframe and metadata, not (y, exogenous_X).
frame, metadata = load_forecasting(
    "m1_yearly_dataset", extract_path="data/aeon", return_metadata=True
)
y = frame.iloc[0]["series_value"]

load_forecasting uses names from aeon.datasets.tsf_datasets.tsf_all, not arbitrary dataset nicknames; the return_X_y argument is unsupported. The default dataframe represents TSF records, with each series stored in its series_value field. Respect per-series forecast horizons/frequency from metadata.

from aeon.datasets import load_anomaly_detection

X, labels = load_anomaly_detection(
    ("KDD-TSAD", "001_UCR_Anomaly_DISTORTED1sddb40"),
    split="test", extract_path="data/aeon",
)

The anomaly loader requires (collection_name, dataset_name). It downloads a whole TimeEval collection ZIP when necessary; some datasets have no training split. Returned multivariate data are timepoints by channels, and labels are one binary indicator per timepoint. Pass axis=0 to compatible series estimators. A test label file must not enter training or threshold calibration.

Raw lines 34 to 58
59## Local file I/O
61File examples are templates; supply your own paths. `.ts` writing and reading were tested with temporary synthetic data.
63```python
64from pathlib import Path
65from aeon.datasets import (
66 load_from_ts_file, load_from_tsf_file, load_from_arff_file,
67 load_from_tsv_file, load_from_timeeval_csv_file, save_to_ts_file,
70X, y = load_from_ts_file("data/example.ts")
71frame, metadata = load_from_tsf_file("data/example.tsf")
72X_arff, y_arff = load_from_arff_file("data/example.arff")
73X_tsv, y_tsv = load_from_tsv_file("data/example.tsv")
74X_time, anomaly_labels = load_from_timeeval_csv_file(Path("data/timeeval.csv"))
76save_to_ts_file(
77 X, y, label_type="classification", path="output", problem_name="MyDataset"
79# Writes output/MyDataset.ts; use label_type="regression" for continuous targets.
80```
82`save_to_ts_file` requires `label_type` when labels are provided, and `path` is a directory. There is no public `write_to_ts_file` or `write_to_arff_file` in 1.6.

Local file I/O

File examples are templates; supply your own paths. .ts writing and reading were tested with temporary synthetic data.

from pathlib import Path
from aeon.datasets import (
    load_from_ts_file, load_from_tsf_file, load_from_arff_file,
    load_from_tsv_file, load_from_timeeval_csv_file, save_to_ts_file,
)

X, y = load_from_ts_file("data/example.ts")
frame, metadata = load_from_tsf_file("data/example.tsf")
X_arff, y_arff = load_from_arff_file("data/example.arff")
X_tsv, y_tsv = load_from_tsv_file("data/example.tsv")
X_time, anomaly_labels = load_from_timeeval_csv_file(Path("data/timeeval.csv"))

save_to_ts_file(
    X, y, label_type="classification", path="output", problem_name="MyDataset"
)
# Writes output/MyDataset.ts; use label_type="regression" for continuous targets.

save_to_ts_file requires label_type when labels are provided, and path is a directory. There is no public write_to_ts_file or write_to_arff_file in 1.6.

Raw lines 59 to 83
84## Dataset metadata and discovery
86The metadata service returns a dataframe, with case-sensitive column names:
88```python
89from aeon.datasets import get_dataset_meta_data
91metadata = get_dataset_meta_data(data_names=["GunPoint"])
92print(metadata[["Dataset", "TrainSize", "TestSize", "Length", "Channels"]])
93all_metadata = get_dataset_meta_data()
94univariate_names = all_metadata.loc[all_metadata["Channels"] == 1, "Dataset"].tolist()
95```
97This fetches `https://timeseriesclassification.com/aeon-toolkit/metadata.csv`. Use archive-specific public lists in `aeon.datasets.tsc_datasets`, `tser_datasets`, and `tsf_datasets`; `get_available_datasets("classification")` is not an aeon API. Metadata describes the published archive and is not a substitute for checking the loaded arrays.

Dataset metadata and discovery

The metadata service returns a dataframe, with case-sensitive column names:

from aeon.datasets import get_dataset_meta_data

metadata = get_dataset_meta_data(data_names=["GunPoint"])
print(metadata[["Dataset", "TrainSize", "TestSize", "Length", "Channels"]])
all_metadata = get_dataset_meta_data()
univariate_names = all_metadata.loc[all_metadata["Channels"] == 1, "Dataset"].tolist()

This fetches https://timeseriesclassification.com/aeon-toolkit/metadata.csv. Use archive-specific public lists in aeon.datasets.tsc_datasets, tser_datasets, and tsf_datasets; get_available_datasets("classification") is not an aeon API. Metadata describes the published archive and is not a substitute for checking the loaded arrays.

Raw lines 84 to 98
99## Published results
101```python
102from aeon.benchmarking.results_loaders import (
103 get_available_estimators, get_estimator_results,
106names = get_available_estimators(task="classification", as_list=True)
107results = get_estimator_results(
108 estimators="ROCKET", datasets=["GunPoint"], task="classification",
109 measure="accuracy", num_resamples=1,
111# Nested mapping: results[estimator][dataset] is a score for one resample,
112# or an array when multiple resamples were requested.
113```
115The loader reads published CSVs under `https://timeseriesclassification.com/results/ReferenceResults`; task, metric, estimator alias and available resamples determine the file. These are public file downloads, without credentials or pagination. Missing dataset scores may be absent from the mapping. Match splits, resampling protocol, metric direction, hyperparameters, and compute budget before comparing your score to published results.

Published results

from aeon.benchmarking.results_loaders import (
    get_available_estimators, get_estimator_results,
)

names = get_available_estimators(task="classification", as_list=True)
results = get_estimator_results(
    estimators="ROCKET", datasets=["GunPoint"], task="classification",
    measure="accuracy", num_resamples=1,
)
# Nested mapping: results[estimator][dataset] is a score for one resample,
# or an array when multiple resamples were requested.

The loader reads published CSVs under https://timeseriesclassification.com/results/ReferenceResults; task, metric, estimator alias and available resamples determine the file. These are public file downloads, without credentials or pagination. Missing dataset scores may be absent from the mapping. Match splits, resampling protocol, metric direction, hyperparameters, and compute budget before comparing your score to published results.

Raw lines 99 to 116
117## Resampling and leakage
119Preserve an archive's original split for a directly comparable benchmark. For a protocol explicitly requiring resamples, use:
121```python
122from aeon.benchmarking.resampling import stratified_resample_data
124X_res_train, y_res_train, X_res_test, y_res_test = stratified_resample_data(
125 X_train, y_train, X_test, y_test, random_state=42
127```
129This combines train and test, then makes a new split preserving original set sizes and class counts; it is not an ordinary training-only validation split. Never use it to tune against a test set that must remain untouched. Use sklearn validation tools inside training data instead, with group or temporal splitting for repeated subjects or overlapping windows. Keep supervised feature selection and augmentation inside each training fold.

Resampling and leakage

Preserve an archive's original split for a directly comparable benchmark. For a protocol explicitly requiring resamples, use:

from aeon.benchmarking.resampling import stratified_resample_data

X_res_train, y_res_train, X_res_test, y_res_test = stratified_resample_data(
    X_train, y_train, X_test, y_test, random_state=42
)

This combines train and test, then makes a new split preserving original set sizes and class counts; it is not an ordinary training-only validation split. Never use it to tune against a test set that must remain untouched. Use sklearn validation tools inside training data instead, with group or temporal splitting for repeated subjects or overlapping windows. Keep supervised feature selection and augmentation inside each training fold.

Raw lines 117 to 130
131## Metrics
133```python
134from aeon.benchmarking.metrics.anomaly_detection import (
135 range_roc_auc_score,
137from aeon.benchmarking.metrics.clustering import clustering_accuracy_score
138from aeon.benchmarking.metrics.segmentation import count_error, hausdorff_error
140auc = range_roc_auc_score(y_true, y_scores) # continuous anomaly scores
142# Arbitrary cluster IDs are optimally matched to class IDs.
143accuracy = clustering_accuracy_score(class_labels, cluster_labels)
145# Supply change-point locations, not dense state labels.
146count_err = count_error(true_change_points, predicted_change_points)
147hausdorff_err = hausdorff_error(true_change_points, predicted_change_points)
148```
150`range_precision`, `range_recall`, and `range_f_score` require `prts`; its current NumPy<2 requirement conflicts with aeon 1.6. Those APIs were source-checked but not executed; a standard resolver cannot install the combination. F-score uses `p_alpha`/`r_alpha`, whereas precision and recall use `alpha`.
152Range metric tolerance/weighting can change conclusions: report buffer size and threshold-selection policy; report alpha, bias and cardinality if using range precision/recall in a separately validated environment. AUC requires both anomalous and normal targets for a meaningful evaluation. Handle empty change-point sets explicitly before Hausdorff evaluation.

Metrics

from aeon.benchmarking.metrics.anomaly_detection import (
    range_roc_auc_score,
)
from aeon.benchmarking.metrics.clustering import clustering_accuracy_score
from aeon.benchmarking.metrics.segmentation import count_error, hausdorff_error

auc = range_roc_auc_score(y_true, y_scores)  # continuous anomaly scores

# Arbitrary cluster IDs are optimally matched to class IDs.
accuracy = clustering_accuracy_score(class_labels, cluster_labels)

# Supply change-point locations, not dense state labels.
count_err = count_error(true_change_points, predicted_change_points)
hausdorff_err = hausdorff_error(true_change_points, predicted_change_points)

range_precision, range_recall, and range_f_score require prts; its current NumPy<2 requirement conflicts with aeon 1.6. Those APIs were source-checked but not executed; a standard resolver cannot install the combination. F-score uses p_alpha/r_alpha, whereas precision and recall use alpha.

Range metric tolerance/weighting can change conclusions: report buffer size and threshold-selection policy; report alpha, bias and cardinality if using range precision/recall in a separately validated environment. AUC requires both anomalous and normal targets for a meaningful evaluation. Handle empty change-point sets explicitly before Hausdorff evaluation.

Raw lines 131 to 153
154## Statistical comparisons across datasets
156Aeon's `wilcoxon_test` accepts a matrix `(n_datasets, n_estimators)` plus estimator names and returns an **upper-triangular matrix of one-sided p-values**, not `(statistic, p_value)`. Only entries above the diagonal are pairwise tests; lower-triangle zeros are placeholders. Nemenyi takes ordered average ranks and a dataset count; it does not take raw score arrays.
158```python
159import numpy as np
160from scipy.stats import rankdata
161from aeon.benchmarking.stats import check_friedman, nemenyi_test, wilcoxon_test
163# Illustrative scores: rows are independent datasets, columns are estimators.
164scores = np.array([[.81, .77, .75], [.72, .75, .68], [.92, .88, .85],
165 [.69, .66, .70], [.83, .81, .79], [.76, .73, .71]])
166ranks = rankdata(-scores, axis=1) # smaller rank = higher accuracy
167friedman_p = check_friedman(ranks.T)
168avg_ranks = ranks.mean(axis=0)
169order = np.argsort(avg_ranks)
170cliques = nemenyi_test(avg_ranks[order], n_datasets=len(scores), alpha=0.05)
171p_values = wilcoxon_test(scores, ["A", "B", "C"], lower_better=False)
172```
174This code demonstrates API semantics, not evidence that any algorithm is superior. Check the omnibus test and pre-specified post-hoc protocol, account for multiplicity, and report effect sizes. Do not treat repeated resamples of the same dataset as independent datasets. Use `scipy.stats.wilcoxon(a, b, alternative="two-sided")` for a two-sided pairwise statistic and p-value.
176Sources: [datasets API](https://www.aeon-toolkit.org/en/stable/api_reference/datasets.html), [dataset source](https://github.com/aeon-toolkit/aeon/blob/v1.6.0/aeon/datasets/_data_loaders.py), [results loaders](https://github.com/aeon-toolkit/aeon/blob/v1.6.0/aeon/benchmarking/results_loaders.py), [statistical tests](https://github.com/aeon-toolkit/aeon/blob/v1.6.0/aeon/benchmarking/stats.py). Archive data downloads were source-verified only; the metadata/results CSVs were also fetched read-only. Local I/O, resampling and metric examples were exercised with synthetic data.

Statistical comparisons across datasets

Aeon's wilcoxon_test accepts a matrix (n_datasets, n_estimators) plus estimator names and returns an upper-triangular matrix of one-sided p-values, not (statistic, p_value). Only entries above the diagonal are pairwise tests; lower-triangle zeros are placeholders. Nemenyi takes ordered average ranks and a dataset count; it does not take raw score arrays.

import numpy as np
from scipy.stats import rankdata
from aeon.benchmarking.stats import check_friedman, nemenyi_test, wilcoxon_test

# Illustrative scores: rows are independent datasets, columns are estimators.
scores = np.array([[.81, .77, .75], [.72, .75, .68], [.92, .88, .85],
                   [.69, .66, .70], [.83, .81, .79], [.76, .73, .71]])
ranks = rankdata(-scores, axis=1)  # smaller rank = higher accuracy
friedman_p = check_friedman(ranks.T)
avg_ranks = ranks.mean(axis=0)
order = np.argsort(avg_ranks)
cliques = nemenyi_test(avg_ranks[order], n_datasets=len(scores), alpha=0.05)
p_values = wilcoxon_test(scores, ["A", "B", "C"], lower_better=False)

This code demonstrates API semantics, not evidence that any algorithm is superior. Check the omnibus test and pre-specified post-hoc protocol, account for multiplicity, and report effect sizes. Do not treat repeated resamples of the same dataset as independent datasets. Use scipy.stats.wilcoxon(a, b, alternative="two-sided") for a two-sided pairwise statistic and p-value.

Sources: datasets API, dataset source, results loaders, statistical tests. Archive data downloads were source-verified only; the metadata/results CSVs were also fetched read-only. Local I/O, resampling and metric examples were exercised with synthetic data.

Raw lines 154 to 176