步骤 16:ICA 拟合
独立成分分析(ICA)拟合
1. 目标
在干净的高通滤波数据上拟合 独立成分分析(ICA),把混合的脑电信号分解为若干独立成分。每个成分代表"一个独立源",可能是脑源、眼电、肌电、心电、噪声等。
2. 何时使用 / 何时跳过
- 应当使用:任何 ≥ 32 导 EEG 实验
- 可跳过:极小数据集(< 16 导);纯儿童/动物 EEG(噪声太大 ICA 失效)
3. 前置条件
- 已执行步骤 15:SSP 投影已记录到
raw.info['projs'],但尚未施加(apply_proj()留给 epochs) - 数据已带通、已平均参考
⚠️ ICA 拟合数据的两个关键前提: 1. 高通 ≥ 1 Hz(剔除低频漂移,否则 ICA 拆出"漂移成分"); 2. SSP 投影记录但未施加(施加后会损失维度)。
4. 核心代码
Python
import mne
# ====== 准备 ICA 输入数据 ======
# 临时副本,仅用于 ICA(避免污染原数据)
raw_for_ica = raw.copy().filter(
l_freq=1.0, # ICA 专用高通
h_freq=None, # 保留之前所有低通
picks=['eeg', 'eog', 'ecg'], # EOG/ECG 必须参与 ICA
)
# ====== 方式 A:FastICA(默认) ======
from mne.preprocessing import ICA
ica = ICA(
n_components=0.95, # 自动选择保留 95% 方差的成分数
method='fastica',
# fit_params 默认 None:MNE 内部已对数据做 PCA 白化,FastICA 自带 whitening
# 仅在需要微调时显式传 fit_params(如 Picard 的 ortho)
max_iter='auto',
random_state=42, # 固定随机种子以复现
)
ica.fit(raw_for_ica, picks=['eeg']) # ICA 仅对 EEG 拟合
# ====== 方式 B:Infomax('extended' 是它的参数) ======
ica = ICA(
n_components=0.95,
method='infomax',
fit_params=dict(extended=True), # extended 仅 infomax 合法
random_state=42,
)
ica.fit(raw_for_ica)
# ====== 方式 C:Picard(最快,推荐新项目) ======
ica = ICA(
n_components=0.95,
method='picard',
fit_params=dict(ortho=False, whiten='unit-variance'),
random_state=42,
)
ica.fit(raw_for_ica)
# ====== 验证 ======
print(f"拟合的成分数: {ica.n_components_}")
print(f"解释方差: {ica.pca_explained_variance_}")
5. 参数详解
ICA 构造函数
| 参数 | 含义 | 推荐值 |
|---|---|---|
n_components |
保留成分数 | 0.95(保留 95% 方差,自动选数)/30(固定数)/None(=通道数) |
method |
算法 | 'fastica'(默认);'infomax'、'picard' |
fit_params |
算法专属参数 | 默认 None(MNE 内部已白化);Infomax:dict(extended=True);Picard:dict(ortho=False, whiten='unit-variance');FastICA:一般无需传 |
max_iter |
最大迭代 | 'auto'(默认) |
random_state |
随机种子 | 固定为 42 等以确保可复现 |
noise_cov |
噪声协方差 | 默认 None |
fit 方法
| 参数 | 含义 | 推荐值 |
|---|---|---|
picks |
拟合的通道 | ['eeg'](推荐) |
start / stop |
数据时间窗 | 默认全部 |
reject |
自动拒绝阈值 | None 或 dict(eeg=500e-6) |
6. 不同 ICA 方法对比
| 方法 | 速度 | 稳定性 | 适用 |
|---|---|---|---|
| FastICA | 快 | 中 | 一般研究(默认) |
| Infomax | 慢 | 高 | 难数据(多伪迹) |
| Picard | 最快 | 高 | 新项目推荐 |
7. 验证方法
Python
# 验证 1:拟合成功
print(f"成分数: {ica.n_components_}")
assert ica.n_components_ > 0
# 验证 2:可视化所有成分
ica.plot_components()
# 期望:能看到脑电成分、眼电成分(额部明显)、肌电成分等
# 验证 3:可视化成分时间序列
ica.plot_sources(raw_for_ica, start=0, stop=30)
# 期望:能看到眨眼、肢体运动等
# 验证 4:方差解释率
print(f"前 10 成分累积解释方差: {ica.pca_explained_variance_[:10].sum()*100:.1f}%")
# 期望:≥ 80%
# 验证 5:保存 ICA
ica.save('subject-01_ica.fif')
8. 常见错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
n_components=0.95 报错 |
数据长度太短 | 改用固定数(如 30)或保证数据 ≥ 1 分钟 × 通道数 |
| ICA 拆不出眼电成分 | EOG 通道未参与拟合/未标 eog | 步骤 03 重新设通道类型 |
| 拟合过程内存爆炸 | 数据太长 + 通道太多 | 用 start / stop 切片拟合 |
| 每次拟合结果不同 | random_state 未固定 |
显式设置 random_state=42 |
RuntimeError: data is empty |
preload=False |
确保 raw_for_ica.preload=True |
| 拟合后没有脑电成分 | 高通过低(< 1 Hz) | 提高 l_freq 至 1.0 Hz |
TypeError: unexpected keyword argument 'extended' |
FastICA 不接受 extended 参数(仅 infomax 接受) |
FastICA 改用 dict(whiten='unit-variance') |
9. 官方来源
| 资源类型 | 链接 |
|---|---|
ICA 类 |
https://mne.tools/stable/generated/mne.preprocessing.ICA.html |
| 教程 | https://mne.tools/stable/auto_tutorials/preprocessing/plot_40_artifact_correction_ica.html |
| 方法对比 | https://mne.tools/stable/auto_tutorials/preprocessing/40_artifact_correction_ica.html |
10. 学术引用
Bell, A. J., & Sejnowski, T. J. (1995). An information-maximization approach to blind separation and blind deconvolution. Neural Computation, 7(6), 1129-1159.
Ablin, P., et al. (2018). Faster independent component analysis by preconditioning with Hessian approximations. IEEE Transactions on Signal Processing, 66(15), 4040-4049.(Picard)