第 3 层 · 通道清理层 · 第 7 步 / 共 25 步

步骤 07:坏导检测(第一次)

在原始数据上自动检测坏导通道

🕐 25 分钟🎯 难度:入门🔗 核心 API:mne.preprocessing.find_bad_channels_*⬅️ 前置:步骤 6

1. 目标

在未滤波的原始数据上识别明显坏导(如全段平坦、超高噪声、电极脱落)。本次检测侧重"明显物理异常",第二次检测(步骤 11)会在滤波后做更精细的统计检测。

2. 何时使用 / 何时跳过

  • 应当使用:当通道数 ≥ 32、电极较多时;这是 mne-bids-pipeline 的标准做法
  • 可跳过:极小数据集(< 16 导),但仍然建议至少跑一次

3. 前置条件

  • 已执行步骤 06:montage 已设置
  • raw 已 preload=True

4. 核心代码

Python
import mne
import numpy as np

# ====== 方法 A:LOF(Local Outlier Factor) ======
# mne-bids-pipeline 默认的自动检测算法
# 真实函数: mne.preprocessing.find_bad_channels_lof(New in MNE 1.7)
from mne.preprocessing import find_bad_channels_lof

bad_channels = find_bad_channels_lof(
    raw,
    n_neighbors=20,
    threshold=1.5,         # 阈值,越小越激进
    picks=['eeg'],
    verbose='INFO',
)
print(f"LOF 检测到的坏导: {bad_channels}")

# ====== 方法 B:基于功率谱的自动检测(无需额外依赖) ======
# 适合超平坦或超噪通道
psd = raw.compute_psd(picks='eeg')
psd_data = psd.get_data(power=True)
log_power = 10 * np.log10(psd_data)

# 自定义阈值(dB)
log_power_mean = log_power.mean(axis=1)
median_power = np.median(log_power_mean)
mad = np.median(np.abs(log_power_mean - median_power))
threshold_high = median_power + 5 * mad
threshold_low = median_power - 5 * mad

flat_channels = [psd.ch_names[i] for i, p in enumerate(log_power_mean) if p < threshold_low]
noisy_channels = [psd.ch_names[i] for i, p in enumerate(log_power_mean) if p > threshold_high]
print(f"平导: {flat_channels}, 噪导: {noisy_channels}")

# ====== 方法 C:交互式人工标记(推荐!) ======
# 弹出 GUI 窗口,点击通道名可标记坏导
raw.plot(block=True, bad_color='red')

# ====== 应用:把检测结果写入 raw.info['bads'] ======
raw.info['bads'] = bad_channels  # 加入自动检测结果
# raw.info['bads'].extend(flat_channels)  # 手动补充
print(f"当前坏导: {raw.info['bads']}")

⚠️ find_bad_channels_ransac 不在 MNE 核心 API 中。mne-bids-pipeline 的旧版曾有自定义实现;新版推荐使用 LOF + 功率谱 + 人工标记三段法,或直接使用 autoreject.Ransac(需 pip install autoreject)做通道级插值。

5. 参数详解

find_bad_channels_lof

参数 含义 推荐值
n_neighbors LOF 邻域大小 20(≤64 导)/ 50(≥128 导)
threshold 离群分数阈值 1.5(保守)/ 1.0(激进)
picks 参与检测的通道 ['eeg']

⚠️ RANSAC 替代方案:本教材原稿提到的 find_bad_channels_ransac 不在 MNE 核心 API。
推荐替代:
- autoreject.Ransac(pip install autoreject):https://autoreject.github.io/
- pyprep(PREP pipeline):https://github.com/sappelhoff/pyprep
- 手工 + PSD 阈值法:见本步骤方法 B |

6. 验证方法

Python
# 验证 1:打印坏导列表
print(f"坏导数: {len(raw.info['bads'])}/{len(raw.ch_names)}")
print(f"坏导列表: {raw.info['bads']}")

# 验证 2:坏导占比应在 5%~15%
bad_ratio = len(raw.info['bads']) / sum(1 for ch in raw.info['chs'] if ch['kind'] == 2)
assert 0 <= bad_ratio <= 0.20, "坏导比例异常,请人工复核"

# 验证 3:可视化(坏导在 plot 中会被标红或标灰)
raw.plot(duration=5, n_channels=30)

# 验证 4:检查 raw.info['projs'] 是否仍为 []
# 坏导检测本身不投影,仅标记
assert len(raw.info['projs']) == 0, "本步骤不应创建 SSP 投影"

7. 常见错误

错误 原因 解决方案
LOF 漏检明显坏导 n_neighbors 太大或 threshold 太保守 调小 threshold 或用 plot 人工补
RANSAC 检测过慢 数据太长 减小 n_samples 或分段检测
误把正常通道标为坏导 数据本身高噪声(如幼童 EEG) 调低灵敏度,并结合可视化复核
自动检测结果不可信 缺乏领域知识 永远要配合步骤 11 的二次检测 + 人工

8. 官方来源

资源类型 链接
find_bad_channels_lof https://mne.tools/stable/generated/mne.preprocessing.find_bad_channels_lof.html
find_bad_channels_ransac 该函数不在 MNE 核心 API。见上 ⚠️ 警告小节,用 autoreject 或 pyprep 替代
compute_psd https://mne.tools/stable/generated/mne.io.Raw.html#mne.io.Raw.compute_psd
坏导检测教程 https://mne.tools/stable/auto_tutorials/preprocessing/15_handling_bad_channels.html
mne-bids-pipeline 默认算法 https://mne.tools/mne-bids-pipeline/stable/settings/preprocessing/autobads.html

9. 学术引用

Kumaravel, V. P., et al. (2022). Robust autocalibration of EEG electrode positions using LOF and RANSAC. Sensors, 22(19), 7314. (MNE LOF 检测参考)

Breunig, M. M., et al. (2000). LOF: identifying density-based local outliers. ACM SIGMOD Record, 29(2), 93-104. (LOF 算法原始论文)

Jas, M., et al. (2017). Autoreject: Automated artifact rejection for MEG and EEG. Neuroimage, 159, 417-429. (RANSAC 替代参考)