はじめに
こんにちは、しゅんです。前編では Embedding Atlas を使って Iris や Ariel データを可視化しました。
前編
今回は、PhysioNet が公開する CHB-MIT Scalp EEG Database を題材に、短時間ウィンドウごとのスペクトル特徴量を抽出し、UMAP で埋め込んだ結果を Embedding Atlas で対話的に探索する「発作検知パイプライン」をご紹介します。
CHB-MIT Scalp EEG Database の詳細
CHB-MIT Scalp EEG Database は、米MITと児童病院(Children's Hospital Boston)が共同で収集した小児てんかん患者の頭皮EEGデータセットです。
- 収録対象:24名の小児てんかん患者
- セッション数:986セッション(各セッション30分~2時間程度)
-
ファイル形式:
- 信号データ:EDF(European Data Format)形式
- 発作アノテーション:同名
.edf.seizures
テキストファイル
- チャネル数:23~26チャネル(国際10–20システムに基づく配置)
- サンプリング周波数:256 Hz
-
アノテーション:
- 各発作区間の「開始時刻(秒)」と「終了時刻(秒)」を記述
- 複数発作がある場合は行を追加
- 用途:発作検知アルゴリズムの評価、被験者識別、睡眠ステージ解析など
- ライセンス:非商用研究目的で無料
- ダウンロード方法: (42.6 GB)
- AWS CLI の最新バージョンのインストールまたは更新が前提
aws s3 sync --no-sign-request s3://physionet-open/chbmit/1.0.0/ DESTINATION
1. 特徴量抽出:make_extract_all_chb.py
#!/usr/bin/env python3
# make_extract_all_chb.py
import os, glob
import mne
import pandas as pd
from tqdm import tqdm
from mne.time_frequency import psd_array_welch
BASE_DIR = "/Users/syun/chbmit/DESTINATION" # CHB-MITのルートフォルダ
bands = {'delta':(1,4), 'theta':(4,8), 'alpha':(8,13), 'beta':(13,30)}
all_dfs = []
pattern = os.path.join(BASE_DIR, "chb*", "*.edf")
edf_paths = glob.glob(pattern)
print(f"Found {len(edf_paths)} EDF files")
for path in tqdm(edf_paths, desc="Extracting features"):
raw = mne.io.read_raw_edf(path, preload=True, verbose=False)
raw.filter(1, 40, fir_design='firwin', verbose=False)
data = raw.get_data() # (n_channels, n_times)
sf = raw.info['sfreq'] # 256.0 Hz
# Welch法でPSD計算
psd, freqs = psd_array_welch(data, sfreq=sf,
fmin=1, fmax=30, verbose=False)
feats = {}
for band,(fmin,fmax) in bands.items():
mask = (freqs>=fmin)&(freqs<fmax)
for idx, ch in enumerate(raw.ch_names):
feats[f"{ch}_{band}"] = psd[idx, mask].mean()
# メタデータ:セッション名
session = os.path.basename(path).replace(".edf","")
feats["session"] = session
all_dfs.append(pd.DataFrame([feats]))
# Parquet出力
df_all = pd.concat(all_dfs, ignore_index=True)
df_all.to_parquet("chb_all_features.parquet", index=False)
print(f"✅ chb_all_features.parquet saved (shape={df_all.shape})")
-
ポイント
- 23~26チャネル全てについて、δ/θ/α/β帯の平均パワーを計算
- 各セッションは1行にまとめ、後続分析が容易な形式に
2. UMAP 投影:project_chb_umap.py
#!/usr/bin/env python3
# project_chb_umap.py
import pandas as pd
import umap
df = pd.read_parquet("chb_all_features.parquet")
df = df.fillna(0) # 欠損値を0埋め
# 特徴量列だけ抽出
feat_cols = [c for c in df.columns if c!="session"]
# UMAP設定 & 実行
reducer = umap.UMAP(
n_neighbors=15,
min_dist=0.1,
metric='euclidean',
random_state=42
)
proj = reducer.fit_transform(df[feat_cols].values)
df["proj_x"], df["proj_y"] = proj[:,0], proj[:,1]
df.to_parquet("chb_all_with_proj.parquet", index=False)
print(f"✅ chb_all_with_proj.parquet saved (shape={df.shape})")
-
ポイント
- n_neighbors=15, min_dist=0.1 で試行
- 986セッション→2次元座標に圧縮
3. Embedding Atlas で可視化
embedding-atlas chb_all_with_proj.parquet \
--x proj_x --y proj_y --text session
-
Color by:
session
→ 特定患者/セッションごとの分布比較 - Density:δ/θ/α/β 各帯の密度等高線表示
- Nearest Neighbors:類似セッションの即時強調表示
各セッションは点として配置され、患者間・患者内での発作・非発作パターンの違いを直感的に把握できます。
結果
.venv_embedding-atlas) syun@syunnoMacBook-Pro embedding-atlas % embedding-atlas chb_all_with_proj.parquet \
--x proj_x --y proj_y --text session
Loading data from chb_all_with_proj.parquet
FP1-F7_delta F7-T7_delta T7-P7_delta P7-O1_delta ... VNS_beta proj_x proj_y FILE_NAME
0 8.858657e-10 1.764916e-09 7.376013e-10 1.603063e-09 ... 0.0 8.885270 5.587948 chb_all_with_proj.parquet
1 8.584892e-10 3.807528e-10 3.428298e-10 3.192264e-10 ... 0.0 8.827070 0.517095 chb_all_with_proj.parquet
2 3.015182e-10 1.808278e-10 9.515979e-11 1.316609e-10 ... 0.0 5.863206 -0.101678 chb_all_with_proj.parquet
3 3.337923e-10 1.956481e-10 1.428465e-10 1.890894e-10 ... 0.0 5.621890 0.189674 chb_all_with_proj.parquet
4 1.455937e-10 2.226266e-10 8.724599e-11 2.002493e-10 ... 0.0 4.195142 1.697780 chb_all_with_proj.parquet
.. ... ... ... ... ... ... ... ... ...
681 2.165244e-10 4.052604e-10 8.749266e-10 7.846272e-10 ... 0.0 6.814955 2.804620 chb_all_with_proj.parquet
682 5.686283e-10 1.223299e-09 2.065206e-09 1.556322e-09 ... 0.0 8.300296 3.819256 chb_all_with_proj.parquet
683 4.748919e-10 1.258660e-09 2.268122e-09 1.933899e-09 ... 0.0 8.253319 3.795711 chb_all_with_proj.parquet
684 2.310469e-09 8.774290e-10 8.605009e-10 9.259115e-10 ... 0.0 10.568083 2.417742 chb_all_with_proj.parquet
685 1.467647e-09 7.436803e-10 1.075059e-09 9.689776e-10 ... 0.0 10.415847 2.174259 chb_all_with_proj.parquet
[686 rows x 396 columns]
INFO: Started server process [28098]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://localhost:5055 (Press CTRL+C to quit)
CHB-MIT EEGデータで発作検知可視化#Apple #Embedding Atlas https://t.co/Qh69pDTjmg pic.twitter.com/GA0xXMcS8d
— SYUN@SGD人間 (@syun88AI) July 14, 2025
まとめ
- CHB-MIT EEG の全セッションを「チャネル×帯域パワー特徴量」に変換
- UMAP で 2D に埋め込み、セッション間のスペクトル類似度を可視化
- Embedding Atlas を使えば、ノーコードで密度推定や最近傍探索を駆使した発作パターンの探索が可能
これにより、臨床 EEG データの発作検知モデル開発や、被験者識別、異常検知パイプラインの初期探索を高速かつインタラクティブに行えます。ぜひご自身のデータでもお試しください!