tshibei/miaf

GitHub: tshibei/miaf

MIAF 是一个用于颅内脑电图伪迹检测与过滤的机器学习流水线,旨在提升高频振荡识别的精度与临床可靠性。

Stars: 1 | Forks: 0

# 🧠 MIAF: Michigan Intracranial Artifact Filter 一个经过医学训练的机器学习流水线,用于**去除颅内脑电图(EEG)中的伪迹高频振荡(HFOs)**。完整流水线使用 **MATLAB** 实现,分类步骤提供等效的 **Python** 实现。 ## 📄 关联出版物 **关键结果:** - 精确度从 **86% → 98%** - **PR-AUC: 0.99**,**ROC-AUC: 0.92** - 在约 8,000 个临床标注的 HFO 事件(35 名患者)上进行训练 - 在完全保留的测试集上评估 ## 📊 结果(保留测试集) MIAF 在 **完全保留的测试队列** 上进行评估,所有训练与特征选择均在独立队列上完成。 ### 📊 分类性能(保留测试集) | 指标 | MIAF 之前 | MIAF 之后 | |---|---|---| | 精确度(PPV) | 86% | **98%**(p < 0.001) | | 特异性 | 0% | **92%** [89–95%] | | 灵敏度(naHFOs) | 100% | 73% [71–75%] | | 灵敏度(真实 HFOs) | 100% | **86%** [84–88%] | | AUROC | — | **0.92** [0.90–0.93] | | AUPRC | — | **0.99** [0.98–0.99] | *置信区间使用 Clopper-Pearson(特异性/灵敏度)和 bootstrap(AUROC/AUPRC)计算。* ### 🧹 伪迹去除 - 去除 **92.4%** 的伪迹,同时保留 **73.1%** 的非伪迹 HFO - 将伪迹污染从 **13.7% → 1.6%** - 过滤后,**98.4%** 的剩余 HFO 为非伪迹 ### 🧠 临床验证 应用于 49+ 百万个 HFO 检测结果(35 名患者): - 在 **76.5%** 的患者(34/34)中改善了 HFO 与发作起始区(SOZ)的相关性(26/34) - 在 **88.9%** 的患者(16/18)中改善了 HFO 与切除体积的相关性 - 支持在 **所有警觉状态** 下进行 HFO 分析(不局限于 NREM 睡眠) ### ⚙️ 模型选择 评估了多种模型(逻辑回归、SVM、SVR、神经网络)。 选择了 **逻辑回归模型**,因其性能优异、可解释性强,且不依赖头皮 EEG 特征。 ### 🏁 基准测试 MIAF 在 ROC 曲线和精确率-召回曲线下均优于两种替代伪迹检测器(单独使用 qHFO 检测器;qHFO + 肌电伪迹 + 背景活动滤波器)。 ## 💡 为何选择 MIAF - 去除导致临床应用的主要障碍——假阳性 HFO - 基于临床标注的伪迹进行训练(而非启发式规则) - 仅使用事件时间点的颅内 EEG - 改善下游 SOZ 定位与临床可解释性 - 易于与现有 HFO 检测器集成 ## 🧠 流水线概述 MIAF 包含三个模块化阶段: 1. **EEG 预处理** - 去除不良通道,应用公共平均参考(CAR),带通滤波 2. **HFO 检测(用户定义)** - 使用任意检测器生成候选 HFO 事件 3. **HFO 分类** - 逻辑回归分类器将事件分为: - 伪迹 - 非伪迹 HFO(naHFO) - 无效 ``` graph TD A[Raw EEG] --> B[Step 1: Preprocessing] B --> C[Preprocessed EEG] C --> D[Step 2: User HFO Detection] D --> E[Detected HFO Events] E --> F[Step 3: HFO Classification] F --> G[Classification .csv Output] ``` ## 🚀 快速开始 ``` git clone https://github.com/tshibei/MIAF.git cd MIAF ``` **运行完整流水线(MATLAB)** ``` demo_full_pipeline ``` **仅运行分类步骤(Python)** ``` python python/demo_classify_events.py ``` # 📚 文档 **A. 流水线概述** **B. 仓库结构** **C. 安装与设置** **D. 运行流水线**  D1. 完整 MATLAB 流水线  D2. 仅 HFO 分类步骤(Python) **E. 分步使用(1–3)**  1. 预处理  2. 用户定义 HFO 检测  3. HFO 分类 **F. 输出文件** **G. 可视化示例数据集** **H. 在 EEGLAB 中可视化 EEG + HFO 事件** **I. 引用** # A. 流水线概述 MIAF 流水线包含 **三个模块化阶段**: 1. **EEG 预处理** 去除不良通道,应用公共平均参考(CAR),并对信号进行带通滤波。 2. **HFO 检测(用户定义)** 提供任意算法以输出候选 HFO 事件。 3. **HFO 分类** 逻辑回归分类器将每个事件分配为: - 伪迹 - 非伪迹 HFO(naHFO) - 无效 ``` graph TD A[Raw EEG] --> B[Step 1: Preprocessing] B --> C[Preprocessed EEG] C --> D[Step 2: User HFO Detection] D --> E[Detected HFO Events] E --> F[Step 3: HFO Classification] F --> G[Classification .csv Output] ``` # B. 仓库结构 ``` MIAF/ ├── input_data/ ├── data_for_visualization/ ├── matlab/ │ ├── demo_full_pipeline.m │ ├── preprocess_eeg_for_hfo_detection.m │ ├── classify_events.m │ ├── preprocessing/ │ ├── features/ │ ├── classification/ │ ├── utils/ │ └── requirements/ ├── python/ │ ├── demo_classify_events.py │ ├── classify_events.py │ ├── classification/ │ ├── utils/ │ └── requirements.txt ├── model/ │ └── model.json └── outputs/ ``` 注意:`outputs/` 文件夹在运行时创建,不会被纳入版本控制。 # C. 安装与设置 ## C1. 获取仓库 **选项 1 — 下载 ZIP** 1. 点击 **Code → Download ZIP** 2. 解压并在 MATLAB 中打开文件夹 **选项 2 — Git 克隆** ``` git clone https://github.com/tshibei/MIAF.git cd MIAF ``` ## C2. MATLAB 设置 在 MATLAB 中,从 `matlab/requirements/` 运行: ``` check_requirements ``` ## C3. Python 设置(可选;仅分类) ``` python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install -r python/requirements.txt ``` # D. 运行流水线 ## D1. 在 MATLAB 中运行完整流水线 在 MATLAB 中运行所有步骤(预处理、特征提取与分类): ``` demo_full_pipeline ``` 该脚本将: - 加载示例输入 - 运行预处理 - 提取事件特征 - 执行 HFO 分类 - 将输出写入 `outputs/` 文件夹 生成的文件包括: - `preprocessed_eeg.mat` - `preprocessed_channel_info.mat` - `classified_hfo_events.csv` - `hfo_event_features.mat` ## D2. 仅使用 Python 运行 HFO 分类步骤 如果预处理与检测已完成,可仅使用 Python 运行第三步。 从 `python/` 运行: ``` python demo_classify_events.py ``` 该脚本将: - 加载检测到的 HFO 事件 - 读取预处理后的 EEG(通过 `h5py` 的 MATLAB v7.3) - 提取特征 - 使用 `model.json` 中的逻辑回归模型进行预测 - 生成与 MATLAB 版本相同的输出 MATLAB 与 Python 的分类结果 **完全一致**。 # E. 分步使用 以下是流水线的三个详细步骤。 # E1. 步骤 1 — EEG 预处理 将以下文件放入 `input_data/`: ## 必需输入 **1. 原始 EEG** (`raw_eeg.mat`) - 格式:MATLAB v7.3 - 示例:`example_raw_eeg.mat` - 必须包含变量: | 变量 | 描述 | |----------|-------------| | `data` | **时间 × 通道** 的 EEG 记录矩阵
• 建议最短持续时间:约 10 分钟
• 行表示时间点,列表示通道 | **2. 通道信息** (`channel_info.mat`) - 示例:`example_channel_info.mat` - 必须包含变量: | | 描述 | |----------|-------------| | `ecog_chan_idx` | ECoG 通道的 1 基索引(列向量),若无则为 `[]` | | `depth_chan_idx` | 深度(SEEG)通道的 1 基索引(列向量),若无则为 `[]` | **3. 采样率** (`sampling_rate.mat`) - 示例:`example_sampling_rate.mat` - 必须包含变量: | 变量 | 描述 | |----------|-------------| | `fs` | 采样率(Hz,浮点数) | ## 运行预处理 ``` preprocess_eeg_for_hfo_detection( ... 'input_data_dir', 'input_data', ... 'raw_eeg_file', 'raw_eeg.mat', ... 'channel_info_file', 'channel_info.mat', ... 'sampling_rate_file', 'sampling_rate.mat', ... 'output_dir', 'outputs', ... 'preprocessed_eeg_file', 'preprocessed_eeg.mat', ... 'preprocessed_channel_info_file', 'preprocessed_channel_info.mat'); ``` ## 生成的输出 在 `outputs/` 文件夹中生成以下文件。 ### 预处理后的 EEG `preprocessed_eeg.mat` | 变量 | 描述 | |------|-------------| | `ecog_hfo_raw` | CAR 参考的 ECoG 原始信号(未滤波) | | `ecog_car_raw` | ECoG 的公共平均参考(CAR)信号 | | `ecog_hfo_filt` | 带通滤波后的 ECoG 信号(80–500 Hz) | | `ecog_car_filt` | 带通滤波后的 ECoG CAR 信号 | | `depth_hfo_raw` | CAR 参考的深度信号(未滤波) | | `depth_car_raw` | 深度通道的公共平均参考信号 | | `depth_hfo_filt` | 带通滤波后的深度信号(80–500 Hz) | | `depth_car_filt` | 带通滤波后的深度 CAR 信号 | 所有矩阵保持原始的 **时间 × 通道** 结构。 ### 预处理后的通道信息 `preprocessed_channel_info.mat` | 字段 | 描述 | |------|-------------| | `ecog_chan_idx` | ECoG 通道的 1 基索引 | | `depth_chan_idx` | 深度(SEEG)通道的 1 基索引 | | `good_chan_mask` | 逻辑向量,指示有效通道(`true` = 有效,`false` = 排除),通过 `invalid_epoch_detector` 自动噪声检测确定 | # E2. 步骤 2 — 用户定义的 HFO 检测 可使用任意 HFO 检测方法。检测必须基于 `preprocessed_eeg.mat` 中的以下变量(在 `outputs/` 中生成): | 变量 | 描述 | |----------|-------------| | `ecog_hfo_filt` | [时间 × 通道] 矩阵,公共平均参考并带通滤波的 ECoG 通道 | | `depth_hfo_filt` | [时间 × 通道] 矩阵,公共平均参考并带通滤波的深度通道 | 检测应分别在 ECoG 和深度通道上执行,并将输出合并(如下所示)。 ### 必需输出 将以下变量保存为 `detected_hfo_events.mat`,放入 `input_data/` 文件夹(参见 `example_detected_hfo_events.mat`)。 | 变量 | 描述 | | ----------- | ---------------------------- | | `start_idx` | 起始样本索引(1 基),列向量 | | `end_idx` | 结束样本索引(1 基),列向量 | | `chan_idx` | 通道索引(1 基),列向量 | 所有变量必须为等长的列向量。 # E3. 步骤 3 — HFO 分类 在 **MATLAB 与 Python 中均可用**。 ### 模型格式(`model.json`) 模型文件存储在 `model/` 文件夹中的 `model.json`,包含一个预训练的逻辑回归模型,格式如下: | 字段 | 类型 | 描述 | |----------------|---------------|-------------| | `coefficients` | `List[float]` | 每个特征的回归权重(β),顺序与 `features` 一致 | | `intercept` | `float` | 截距项(β₀) | | `threshold` | `float` | 二分类概率阈值(例如概率 ≥ 阈值 → 类别 1) | | `features` | `List[str]` | 模型使用的特征名称列表 | | `mean` | `List[float]` | z-score 归一化的特征均值 | | `std` | `List[float]` | z-score 归一化的特征标准差 | 在 MATLAB 中,从 `matlab/` 运行: ``` classify_events( ... 'input_data_dir', 'input_data', ... 'detected_hfo_events_file', 'detected_hfo_events.mat', ... 'sampling_rate_file', 'sampling_rate.mat', ... 'model_dir', 'model', ... 'model_file', 'model.json', ... 'output_dir', 'outputs', ... 'preprocessed_eeg_file', 'preprocessed_eeg.mat', ... 'preprocessed_channel_info_file', 'preprocessed_channel_info.mat', ... 'classified_hfo_events_file', 'classified_hfo_events.csv', ... 'hfo_event_features_file', 'hfo_event_features.mat'); ``` 或者, 在 Python 中,从 `python/` 运行: ``` python classify_events.py \ --input-data-dir input_data \ --detected-hfo-events-file detected_hfo_events.mat \ --sampling-rate-file sampling_rate.mat \ --model-dir model \ --model-file model.json \ --output-dir outputs \ --preprocessed-eeg-file preprocessed_eeg.mat \ --preprocessed-channel-info-file preprocessed_channel_info.mat \ --classified-hfo-events-file classified_hfo_events.csv \ --hfo-event-features-file hfo_event_features.mat ``` # F. 输出文件 ## F1. 特征矩阵 `outputs/hfo_event_features.mat` | 变量 | 描述 | |----------|-------------| | `X` | [事件 × 特征] 矩阵,每个检测到的 HFO 事件提取的特征
• 行表示单个 HFO 事件
• 列表示用于分类的特征值 | ## F2. 分类 CSV `outputs/classified_hfo_events.csv` | 列 | 描述 | | ---- | ---- | | `start_idx` | 事件起始索引 | | `end_idx` | 事件结束索引 | | `chan_idx` | 通道 | | `prob_HFO` | 预测概率 | | `is_HFO_thresh_0_95` | 二值标签 | | `is_bad_chan` | 1 = 坏通道,0 = 好通道 | | `is_nan_event` | 1 = 无效事件(无效分数或检测在坏通道上),0 = 有效事件 | # G. 可视化示例数据集 位于: ``` data_for_visualization/ ``` 每个示例包含: 1. `example_raw_eeg_{n}.set`:EEG 信号 2. `example_detected_hfo_events_{n}.set`:检测到的 HFO 事件(含真实标签:脑 / 伪迹) 3. `example_classified_hfo_events_{n}.set`:MIAF 分类后的 HFO 事件(含分类标签:伪迹 / 非伪迹 HFO(naHFO)/ 无效) 这些为仅用于可视化的 EEGLAB `.set` 数据集。 # H. 在 EEGLAB 中可视化 EEG + HFO 事件 ## H1. 安装 EEGLAB 下载地址: https://sccn.ucsd.edu/eeglab/download.php ## H2. 加载示例数据集 1. 在 EEGLAB 中:**File → Load existing dataset(s)** 2. 打开 `data_for_visualization/` 中的 `.set` 文件 ## H3. 查看 EEG 与事件标记 打开滚动查看器: **Plot → Channel data (scroll)** 使用箭头键浏览 EEG。 ## H4. 示例 EEG 时期与分类器行为 展示了三种代表性 EEG 时期,说明分类器在不同信号条件下的行为: ### 示例 1 — 明显伪迹 该时期包含一个肉眼可见的标注伪迹。 分类器成功识别出标注伪迹以及该段中额外的未标注伪迹,展示了模型泛化到标注之外伪迹形态的能力。 ### 示例 2 — 脑源性 HFO 该时期包含一个标注的脑源性 HFO。 分类器正确识别了标注的 HFO;但在短暂窗口内将几个额外的脑源性 HFO 误判为伪迹。这些 HFO 较为微弱且未叠加在明显尖波上,难以区分,尤其在检测器保守优先去除伪迹的设置下。 ### 示例 3 — 混合肌电伪迹与脑源性 HFO 该时期包含肌电伪迹与脑源性 HFO 的混合。 也显示了头皮 EEG 轨迹供参考。明显的 HFO 出现在尖波上,但肌电活动显著,使得单通道难以区分。分类器成功将肌电伪迹与脑源性 HFO 分离。 # I. 📚 引用 若在研究中使用 MIAF,请引用: ``` @article{tan2026miaf, author = {Tan, Shi Bei and Gliske, Stephen V. and John, Neha Sara and Kerr, Wesley T. and Mihaylova, Temenuzhka and Smith, Garnett and McNamara, Nancy and Beimer, Nicholas and Romanowski, Erin Fedak and Stacey, William C.}, title = {A comprehensive, physician-trained algorithm to remove artifactual false positive {High Frequency Oscillations} in long-term intracranial {EEG}}, journal = {Journal of Neural Engineering}, year = {2026}, doi = {10.1088/1741-2552/ae512b} } ``` # 📄 许可证 详见 **LICENSE.md** 获取完整许可信息。
标签:Apex, artifact去除, Caido项目解析, EEG, HFO, iEEG, MATLAB, PR-AUC, Python, ROC-AUC, 临床验证, 信号处理, 分类模型, 医学成像, 医生训练, 无后门, 时间序列分类, 期刊论文, 机器学习, 特征选择, 生物医学信号, 留出测试集, 神经工程, 系统独立性, 脑电图, 逆向工具, 逻辑回归, 高精度, 高频率振荡