mcpField
A
aeon

aeon

github.com/jaechang-hitsデータ・データベース38469 回インストール1 週間前に更新
リポジトリ

aeon について

aeonは、時系列機械学習向けのPythonツールキットです。scikit-learn互換APIを備え、分類、回帰、クラスタリング、セグメンテーション、変換に取り組むユーザー向けに、研究由来のアルゴリズムとデータセット・ベンチマーク機能を提供します。

主な機能

  1. 01時系列分類と回帰
  2. 02教師なし時系列クラスタリング
  3. 03セグメンテーションと変化点検出
  4. 04特徴量・系列変換
  5. 05データセット読み込みとベンチマーク

活用シーン

  1. 01ECG、EEG、センサー記録の分類
  2. 02ラベルのない系列を形状で分類
  3. 03連続信号の状態変化の検出
  4. 04ベンチマークデータセットでのアルゴリズム比較

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill aeon

インストール後、Claude Code で/aeonを入力して読み込まれたか確認します。

詳細

aeon

概要

aeon は、時系列 ML タスク(分類、回帰、クラスタリング、セグメンテーション、アノテーション、類似検索、変換)に対応する、scikit-learn 互換の統一 API を提供します。scikit-learn と同じ fit(X, y) / predict(X) パターンに従い、X は形状が (n_instances, n_channels, n_timepoints) の 3D NumPy 配列です。aeon は時系列分野の文献における最先端アルゴリズムを厳選しており、分類には ROCKET とその派生版(MiniROCKET、MultiROCKET)、クラスタリングには DTW を使った k-means、セグメンテーションには CLASP を利用できるほか、データセット全体でアルゴリズムを比較するためのベンチマークツールも提供します。2022 年のガバナンス分割後に開発が継続された、コミュニティ運営の sktime フォークです。

使用する場面

  • 最先端アルゴリズムを使用して、ECG、EEG、加速度計、センサーの時系列を分類する
  • 時系列入力から連続値のターゲットを予測する(例:バイタルサインの波形から患者の重症度を予測する)
  • クラスラベルがない場合に、形状の類似性に基づいて時系列をクラスタリングする
  • 連続記録の変化点を検出する、または均質な区間にセグメント化する
  • 可変長の時系列から、下流の ML 用に固定長の特徴ベクトルを抽出する
  • 再現可能な比較を行いながら、UCR/UEA アーカイブ上で時系列アルゴリズムをベンチマークする
  • より大きなエコシステムが必要な場合や、既存のコードがその API に依存している場合は sktime を使用します。DTW を中心とした処理には tslearn を使用します

前提条件

  • Python パッケージ:aeon、numpy、scikit-learn、matplotlib
  • データ形式:3D NumPy 配列 (n_instances, n_channels, n_timepoints)、または単変量の場合は 2D (n_instances, n_timepoints)
  • オプション:numba(ROCKET、DTW に必要です。pip install aeon[all_extras] でインストールします)
pip install aeon
pip install aeon[all_extras]  # includes numba, statsmodels for full algorithm support

クイックスタート

import numpy as np
from aeon.classification.convolution_based import RocketClassifier
from aeon.datasets import load_unit_test

# Load a small benchmark dataset
X_train, y_train = load_unit_test(split="train")  # shape: (n, 1, timepoints)
X_test, y_test = load_unit_test(split="test")

print(f"Train: {X_train.shape}, classes: {np.unique(y_train)}")

clf = RocketClassifier(num_kernels=500, random_state=42)
clf.fit(X_train, y_train)
accuracy = clf.score(X_test, y_test)
print(f"ROCKET accuracy: {accuracy:.3f}")

コア API

モジュール 1:時系列分類

畳み込み、辞書、距離、特徴、区間、シェイプレットの各ファミリーにまたがる 30 種類以上の分類器を提供します。

import numpy as np
from aeon.datasets import load_unit_test
from aeon.classification.convolution_based import RocketClassifier, MiniRocketClassifier
from aeon.classification.distance_based import KNeighborsTimeSeriesClassifier
from aeon.classification.feature_based import Catch22Classifier
from sklearn.metrics import accuracy_score

X_train, y_train = load_unit_test(split="train")
X_test, y_test   = load_unit_test(split="test")

classifiers = {
    "ROCKET":    RocketClassifier(num_kernels=1000, random_state=42),
    "MiniROCKET": MiniRocketClassifier(random_state=42),
    "KNN-DTW":   KNeighborsTimeSeriesClassifier(n_neighbors=1, distance="dtw"),
    "Catch22":   Catch22Classifier(random_state=42),
}

for name, clf in classifiers.items():
    clf.fit(X_train, y_train)
    acc = accuracy_score(y_test, clf.predict(X_test))
    print(f"{name:15s}: {acc:.3f}")
# Multivariate classification (multiple channels)
from aeon.classification.convolution_based import MultiRocketMultivariateClassifier

# Synthetic multivariate time series: 100 instances, 3 channels, 50 timepoints
np.random.seed(0)
X_mv_train = np.random.randn(100, 3, 50)
y_mv_train = (X_mv_train[:, 0, :].mean(axis=1) > 0).astype(str)
X_mv_test  = np.random.randn(30, 3, 50)
y_mv_test  = (X_mv_test[:, 0, :].mean(axis=1) > 0).astype(str)

clf_mv = MultiRocketMultivariateClassifier(random_state=42)
clf_mv.fit(X_mv_train, y_mv_train)
print(f"Multivariate accuracy: {clf_mv.score(X_mv_test, y_mv_test):.3f}")
モジュール 2:時系列回帰

時系列入力から連続値のターゲットを予測します。

import numpy as np
from aeon.regression.convolution_based import RocketRegressor
from aeon.regression.distance_based import KNeighborsTimeSeriesRegressor
from sklearn.metrics import mean_squared_error

# Synthetic regression: predict the mean of each series
np.random.seed(42)
X_train = np.random.randn(200, 1, 100)
y_train = X_train[:, 0, :].mean(axis=1) + np.random.randn(200) * 0.1
X_test  = np.random.randn(50, 1, 100)
y_test  = X_test[:, 0, :].mean(axis=1) + np.random.randn(50) * 0.1

reg = RocketRegressor(num_kernels=500, random_state=42)
reg.fit(X_train, y_train)
y_pred = reg.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
print(f"ROCKET regressor MSE: {mse:.4f}")
モジュール 3:時系列クラスタリング

クラスラベルを使わず、形状の類似性に基づいて時系列をグループ化します。

import numpy as np
from aeon.clustering.k_means import TimeSeriesKMeans
from aeon.clustering.k_medoids import TimeSeriesKMedoids

# Synthetic clustering dataset: 3 distinct shapes
np.random.seed(0)
n_per_class = 30
class_0 = np.sin(np.linspace(0, 2*np.pi, 50)) + np.random.randn(n_per_class, 1, 50)*0.1
class_1 = np.cos(np.linspace(0, 2*np.pi, 50)) + np.random.randn(n_per_class, 1, 50)*0.1
class_2 = np.linspace(0, 1, 50) + np.random.randn(n_per_class, 1, 50)*0.05
X = np.concatenate([class_0, class_1, class_2], axis=0)

# K-Means with DTW averaging
km = TimeSeriesKMeans(n_clusters=3, metric="dtw", averaging_method="ba",
                       random_state=42, n_init=3, max_iter=50)
labels = km.fit_predict(X)
print(f"Cluster sizes: {np.bincount(labels)}")
print(f"Cluster centers shape: {km.cluster_centers_.shape}")
モジュール 4:セグメンテーションと変化点検出

連続した時系列におけるレジーム間の境界を検出します。

import numpy as np
from aeon.segmentation import ClaSPSegmenter, EAggloSegmenter

# Simulate signal with 3 segments
np.random.seed(0)
seg1 = np.random.randn(100) * 0.5 + 0
seg2 = np.random.randn(100) * 0.5 + 3
seg3 = np.random.randn(100) * 0.5 - 2
signal = np.concatenate([seg1, seg2, seg3])

# CLASP: Classification Score Profile segmentation
clasp = ClaSPSegmenter(period_length=10, n_change_points=2)
labels = clasp.fit_predict(signal)
change_points = clasp.change_points_
print(f"Detected change points: {change_points}")
# Expected near indices 100 and 200
モジュール 5:変換(特徴抽出)

時系列を固定長の特徴ベクトルまたは変換済み時系列に変換します。

import numpy as np
from aeon.transformations.collection.convolution_based import Rocket, MiniRocket
from aeon.transformations.collection.feature_based import Catch22
from sklearn.linear_model import RidgeClassifierCV
from sklearn.pipeline import Pipeline

np.random.seed(42)
X_train = np.random.randn(100, 1, 50)
y_train = (X_train[:, 0, :].mean(axis=1) > 0).astype(str)
X_test  = np.random.randn(30, 1, 50)

# ROCKET transform → Ridge classifier (the classic ROCKET pipeline)
rocket_pipe = Pipeline([
    ("rocket", Rocket(num_kernels=1000, random_state=42)),
    ("clf", RidgeClassifierCV(alphas=[0.1, 1.0, 10.0])),
])
rocket_pipe.fit(X_train, y_train)
print(f"ROCKET pipeline accuracy: {rocket_pipe.score(X_test, (X_test[:, 0, :].mean(axis=1) > 0).astype(str)):.3f}")

# Catch22: 22 canonical time series features per channel
catch22 = Catch22()
X_features = catch22.fit_transform(X_train)
print(f"Catch22 feature matrix: {X_features.shape}")  # (n_instances, 22)
モジュール 6:データセットの読み込みとベンチマーク
from aeon.datasets import load_classification, load_from_tsf_file
from aeon.benchmarking.results_loaders import get_estimator_results_as_array
import numpy as np

# Load UCR/UEA dataset
X_train, y_train = load_classification("BasicMotions", split="train")
X_test, y_test   = load_classification("BasicMotions", split="test")
print(f"BasicMotions: train={X_train.shape}, classes={np.unique(y_train)}")

# Load custom .ts file (UCR format)
# X, y = load_from_tsf_file("my_dataset.ts")

# Compare to published benchmark results
# from aeon.benchmarking import plot_critical_difference_diagram

主要な概念

データ形式の規約

aeon は、形状が (n_instances, n_channels, n_timepoints) の 3D NumPy 配列を使用します。

  • n_instances:時系列の数(sklearn の n_samples に相当)
  • n_channels:各時系列の変数の数(単変量の場合は 1)
  • n_timepoints:各系列の長さ(系列ごとに長さが異なる場合は、インスタンス間で異なることがあります)

scikit-learn が想定するのは 2D (n_samples, n_features) です。変換には aeon のトランスフォーマーを使用します。

ROCKET ファミリー

ROCKET(Random Convolutional Kernel Transform)は、長さ、膨張率、バイアスが異なる 10,000 個の畳み込みカーネルをランダムに生成し、各系列に適用して PPV(正の値の割合)と最大値の特徴量を抽出します。これら 20,000 個の特徴量を線形モデルで分類します。MiniROCKET は数を絞った固定カーネルを使用し、精度は同程度で ROCKET より約 75 倍高速です。MultiROCKET は多変量系列に対応します。

一般的なワークフロー

ワークフロー 1:交差検証による分類器の比較
import numpy as np
from aeon.datasets import load_unit_test
from aeon.classification.convolution_based import RocketClassifier, MiniRocketClassifier
from aeon.classification.feature_based import Catch22Classifier
from sklearn.model_selection import cross_val_score

X, y = load_unit_test()  # Full dataset (train+test merged)

classifiers = {
    "ROCKET":     RocketClassifier(num_kernels=500, random_state=42),
    "MiniROCKET": MiniRocketClassifier(random_state=42),
    "Catch22":    Catch22Classifier(random_state=42),
}

print(f"Dataset: {X.shape}, classes: {np.unique(y)}")
for name, clf in classifiers.items():
    scores = cross_val_score(clf, X, y, cv=5, scoring="accuracy")
    print(f"{name:15s}: {scores.mean():.3f} ± {scores.std():.3f}")
ワークフロー 2:前処理と分類を組み合わせたパイプライン
import numpy as np
from aeon.datasets import load_unit_test
from aeon.transformations.collection.convolution_based import Rocket
from aeon.transformations.collection.normalize import TimeSeriesScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import RidgeClassifierCV
from sklearn.preprocessing import StandardScaler

X_train, y_train = load_unit_test(split="train")
X_test, y_test   = load_unit_test(split="test")

# Normalize series → ROCKET features → Ridge
pipe = Pipeline([
    ("normalize", TimeSeriesScaler()),
    ("rocket",    Rocket(num_kernels=2000, random_state=42)),
    ("scale",     StandardScaler(with_mean=False)),
    ("clf",       RidgeClassifierCV(alphas=[0.01, 0.1, 1.0, 10.0])),
])

pipe.fit(X_train, y_train)
print(f"Pipeline accuracy: {pipe.score(X_test, y_test):.3f}")

主要なパラメーター

パラメーターモジュール/クラスデフォルト範囲/選択肢効果
num_kernelsRocket、RocketClassifier10000500–50000ランダムカーネルの数です。増やすと精度が向上しますが、処理は遅くなります
n_clustersTimeSeriesKMeans82–50K-Means のクラスタ数です
metricTimeSeriesKMeans、KNN"dtw""dtw"、"euclidean"、"msm"、"twe"類似度計算に使用する距離指標です
n_change_pointsClaSPSegmenterauto1–20検出する変化点の想定数です
period_lengthClaSPSegmenterauto5–100最小セグメント長です
n_neighborsKNeighborsTimeSeriesClassifier11–20KNN の k です。時系列では k=1 が最適なことがよくあります
averaging_methodTimeSeriesKMeans"ba""ba"(バリセンター)、"mean"クラスタのプロトタイプの計算方法です
random_state確率的な処理全般Noneint再現性を確保するためのシードです

よく使われるレシピ

レシピ:ROCKET 特徴量を DataFrame にエクスポートして AutoML に渡す
import numpy as np
import pandas as pd
from aeon.transformations.collection.convolution_based import MiniRocket

np.random.seed(0)
X = np.random.randn(200, 1, 100)  # 200 univariate time series, length 100
y = (X[:, 0, :].mean(axis=1) > 0).astype(int)

transformer = MiniRocket(random_state=42)
X_features = transformer.fit_transform(X)  # shape: (200, 9996)

df = pd.DataFrame(X_features, columns=[f"f{i}" for i in range(X_features.shape[1])])
df["label"] = y
df.to_parquet("rocket_features.parquet", index=False)
print(f"Feature matrix: {df.shape}, saved to rocket_features.parquet")
レシピ:カスタムデータセットを読み込んで分類する
import numpy as np
from aeon.classification.convolution_based import RocketClassifier

# Custom dataset: time series stored as 3D array
# Shape: (n_instances, n_channels, n_timepoints)
np.random.seed(42)
X_train = np.random.randn(150, 2, 80)  # 150 bivariate series, length 80
y_train = np.random.choice(["class_A", "class_B", "class_C"], 150)
X_test  = np.random.randn(50, 2, 80)
y_test  = np.random.choice(["class_A", "class_B", "class_C"], 50)

clf = RocketClassifier(num_kernels=2000, random_state=42)
clf.fit(X_train, y_train)
print(f"Test accuracy: {clf.score(X_test, y_test):.3f}")

# Save predictions
y_pred = clf.predict(X_test)
print(f"Predictions: {y_pred[:10]}")

トラブルシューティング

問題原因解決策
ROCKET の使用時に ImportError: numba が発生するnumba がインストールされていないpip install aeon[all_extras] または pip install numba
入力形状エラー:3D 配列が必要3D (n, 1, t) ではなく 2D (n, t) を渡している形状を変更します:X = X[:, np.newaxis, :]
大規模データセットで KNN-DTW が非常に遅いDTW はペアごとに O(n·m) で、全ペアの比較は O(N²) ですN>1000 の場合は代わりに ROCKET を使用するか、系列長を短くします
クラスタリングですべての点が 1 つのクラスタに割り当てられる初期重心が近すぎるか、指標が適していないn_init=10 を設定し、別の metric("msm" または "euclidean")を試します
load_classification がダウンロードエラーで失敗するネットワークのタイムアウト、またはデータセット名の誤り利用可能なデータセットを確認します:aeon.datasets.list_datasets()。手動でダウンロードします
ClaSPSegmenter が誤った数の変化点を検出するn_change_points が大きすぎるか、period_length が適切でないperiod_length を想定される最小セグメント長に設定し、既知の信号で検証します
大規模なパネルデータセットでメモリーエラーが発生するROCKET の変換には n_kernels × n_instances の行列が必要num_kernels を減らし、partial_fit を使用してバッチごとに処理します

関連スキル

  • neurokit2 — aeon の分類器に渡す時系列データ(ECG、EDA)の生成
  • scikit-learn-machine-learning — aeon の特徴量に対応した、sklearn 互換の下流モデル
  • matplotlib-scientific-plotting — 時系列と分類結果の可視化

参考資料

コメント