第 4 层 · 伪迹剔除层 · 第 19 步 / 共 25 步

步骤 19:应用 ICA

从数据中去除伪迹 ICA 成分

🕐 18 分钟🎯 难度:进阶🔗 核心 API:ica.apply⬅️ 前置:步骤 18

1. 目标

把 ica.exclude 中的成分真正从数据中移除,重建 EEG 时间序列。剔除后眼电/心电等伪迹源被消除,但不影响其他成分。

2. 何时使用 / 何时跳过

  • 必须使用:ICA 识别出伪迹成分后,最终施加剔除
  • 绝不可跳过:否则 ica.exclude 仅是标注,未实际生效

3. 前置条件

  • 已执行步骤 18:ica.exclude 列表已稳定(包含 EOG + ECG 成分)
  • 注意:不要在原始数据上 apply,应在 epochs 上 apply(详见下文)

4. 核心代码

Python
import mne

# ====== 推荐做法:在 Epochs 上施加 ======
# ICA 施加前先创建 epochs(步骤 21)
# epochs = mne.Epochs(raw, events, ...)
# epochs.load_data()
# ica.apply(epochs)

# ====== 临时在 Raw 上施加(仅调试用) ======
# 警告:会修改 raw,建议保留 raw_for_ica 副本
raw_clean = ica.apply(raw.copy())  # 不修改原 raw
# 或就地修改:
# ica.apply(raw)

# ====== 验证剔除效果 ======
# 对比 raw vs raw_clean 的 EOG 通道附近(如 Fp1)
fp1_before = raw.copy().pick(['Fp1']).get_data()[0]
fp1_after = raw_clean.copy().pick(['Fp1']).get_data()[0]
variance_reduction = (fp1_before.var() - fp1_after.var()) / fp1_before.var() * 100
print(f"Fp1 方差降低: {variance_reduction:.1f}%")
# 期望:10-50%(显著降低但不会变 0)

# ====== 检查 exclude 列表 ======
print(f"ICA 排除成分: {ica.exclude}")
assert len(ica.exclude) > 0, "exclude 列表为空,未生效"

5. 参数详解(真实签名)

ica.apply(inst, include=None, exclude=None, n_pca_components=None, start=None, stop=None, *, on_baseline='warn', verbose=None)

参数 含义 推荐值
inst 要施加的对象 Epochs(推荐)/ Raw(仅调试)
exclude 要剔除的成分 默认用 ica.exclude
include 仅保留的成分(白名单) 默认全部
n_pca_components PCA 降维后再剔除 默认 None
start / stop 时间窗 默认全部

⚠️ 真实签名中无 picks 参数——ica.apply() 不接受通道选择;它只对所有通道施加已计算好的 ICA 解混矩阵。
⚠️ 建议施加时机:在 Epochs 上 ica.apply(),不要在 Raw 上。原因: 1. Raw 上剔除可能影响后续可视化判断; 2. Epochs 是最终分析对象,避免 Raw 与 Epochs 不一致。

6. 验证方法

Python
# 验证 1:exclude 列表已生效
print(f"剔除成分数: {len(ica.exclude)}")
assert len(ica.exclude) >= 1

# 验证 2:眼电时刻的振幅明显降低
# 手动找到一次眨眼时刻
blink_idx = raw.copy().pick(['VEOG']).get_data()[0].argmax()
blink_window = slice(blink_idx - 100, blink_idx + 100)
before = raw.get_data(picks=['Fp1'])[0, blink_window].var()
after = raw_clean.get_data(picks=['Fp1'])[0, blink_window].var()
print(f"眨眼时刻 Fp1 方差: 剔除前={before:.2e}, 剔除后={after:.2e}")
# 期望:after 显著小于 before

# 验证 3:脑电成分(视觉诱发)不应受影响
# 用 ERP 信号验证(具体研究依赖)

# 验证 4:可视化对比
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 1, sharex=True)
axes[0].plot(raw.times[:5000], raw.get_data(picks=['Fp1'])[0, :5000]*1e6)
axes[0].set_title('Before ICA')
axes[1].plot(raw_clean.times[:5000], raw_clean.get_data(picks=['Fp1'])[0, :5000]*1e6)
axes[1].set_title('After ICA')

7. 常见错误

错误 原因 解决方案
apply 后 ERP 没改善 误识别了一些正常成分 人工逐个核对 ica.exclude
误删过多成分导致数据"过干净" threshold 太低,自动识别过多 减少 ica.exclude
apply 报错 unexpected keyword 'picks' picks 不是 apply 的参数 删除 picks= 参数;apply() 自动施加到 inst 的全部通道
ICA 施加后通道变少 配置错误 apply() 不会减通道;如减了请检查 n_pca_components
apply 在 Raw 上做了,epochs 又 apply 一次 双重剔除 仅在 Epochs 上 apply 一次

8. 官方来源

资源类型 链接
ica.apply https://mne.tools/stable/generated/mne.preprocessing.ICA.html#mne.preprocessing.ICA.apply
ICA 教程 https://mne.tools/stable/auto_tutorials/preprocessing/plot_40_artifact_correction_ica.html

9. 学术引用

Iriarte, J., et al. (2003). Independent component analysis as a tool for the analysis of EEG data. Clinical Neurophysiology, 114(11), 1995-2001.