MNE-Python | 使用 ICLabel 模型进行 ICA 并自动修复样本

        本文涵盖了使用 ICA 和 ICLabel 模型 1 自动修复信号,该模型源自 EEGLab。 有关 ICA 的概念背景,请参阅此 scikit-learn 教程。 有关如何使用 ICA 删除工件的基本了解,请参阅 MNE-Python 中的教程。

        ICLabel 旨在对配备最大信号 ICA 分解算法的独立成分(IC)进行分类,该算法需要 EEG 数据集采用平均值作为重参考并在 [1,100] Hz 之间进行滤波处理。 也可以在不符合这些规范的数据集上运行 ICLabel,但分类性能可能会受到负面影响。 此外,ICLabel 论文没有研究这些预处理步骤的影响。

        同样的我们需要导入必要的 Python 模块并加载一些示例数据。 因为 ICA 的计算量很大,可以将数据裁剪为 60 秒; 为了避免重复预处理(mne.preprocessing),我们将直接从该子模块导入一些函数和类。

import mne
from mne.preprocessing import ICA

from mne_icalabel import label_components

sample_data_folder = mne.datasets.sample.data_path() / "MEG" / "sample"
sample_data_raw_file = sample_data_folder / "sample_audvis_raw.fif"
raw = mne.io.read_raw_fif(sample_data_raw_file)

# 我们裁剪 60 秒的信号段,并删除 MEG 通道
raw.crop(tmax=60.0).pick_types(eeg=True, stim=True, eog=True)
raw.load_data()

输出为:

Opening raw data file C:\Users\Mathieu\mne_data\MNE-sample-data\MEG\sample\sample_audvis_raw.fif...
    Read a total of 3 projection items:
        PCA-v1 (1 x 102)  idle
        PCA-v2 (1 x 102)  idle
        PCA-v3 (1 x 102)  idle
    Range : 25800 ... 192599 =     42.956 ...   320.670 secs
Ready.
Removing projector <Projection | PCA-v1, active : False, n_channels : 102>
Removing projector <Projection | PCA-v2, active : False, n_channels : 102>
Removing projector <Projection | PCA-v3, active : False, n_channels : 102>
Reading 0 ... 36037  =      0.000 ...    60.000 secs...
Measurement dateDecember 03, 2002 19:01:10 GMT
ExperimenterMEG
ParticipantUnknown
Digitized points146 points
Good channels9 Stimulus, 59 EEG, 1 EOG
Bad channelsNone
EOG channelsEOG 061
ECG channelsNot available
Sampling frequency600.61 Hz
Highpass0.10 Hz
Lowpass172.18 Hz
Filenamessample_audvis_raw.fif
Duration00:01:00 (HH:MM:SS)

滤波去除缓慢低频漂移

在运行 ICA 之前,一个重要的步骤是对数据的低频漂移进行过滤,低频漂移会对 ICA 拟合的质量产生负面影响。 缓慢漂移的问题在于它们降低了假定为独立来源相互之间的独立性(例如,在缓慢向上漂移期间,神经、心跳、眨眼和其他肌电信号都会呈现出更高的值),使得算法更难找到准确的解。所以建议使用截止频率为 1 Hz 的高通滤波器。 但是,由于滤波是线性操作,从滤波后的信号中找到的 ICA 解可以应用于未滤波的信号,参考以下文献:

Irene Winkler, Stefan Debener, Klaus-Robert Müller, and Michael Tangermann. On the influence of high-pass filtering on ICA-based artifact reduction in EEG-ERP. In Proceedings of EMBC-2015, 4101–4105. Milan, 2015. IEEE. doi:10.1109/EMBC.2015.7319296.

因此我们将保留未滤波的原始对象的副本,以便我们可以将 ICA 的解作用与原始数据。

filt_raw = raw.copy().filter(l_freq=1.0, h_freq=100.0)

输出为:

Filtering raw data in 1 contiguous segment
Setting up band-pass filter from 1 - 1e+02 Hz

FIR filter parameters
---------------------
Designing a one-pass, zero-phase, non-causal bandpass filter:
- Windowed time-domain design (firwin) method
- Hamming window with 0.0194 passband ripple and 53 dB stopband attenuation
- Lower passband edge: 1.00
- Lower transition bandwidth: 1.00 Hz (-6 dB cutoff frequency: 0.50 Hz)
- Upper passband edge: 100.00 Hz
- Upper transition bandwidth: 25.00 Hz (-6 dB cutoff frequency: 112.50 Hz)
- Filter length: 1983 samples (3.302 sec)

[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done   1 out of   1 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done   2 out of   2 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done   3 out of   3 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done   4 out of   4 | elapsed:    0.0s remaining:    0.0s
[Parallel(n_jobs=1)]: Done  59 out of  59 | elapsed:    0.0s finished

拟合并绘制ICA解

现在即可准备开始建立并拟合ICA。通过观察原始数据可以知道 EOG 和 ECG 的伪影影响很强,所以我们预计这些伪影将在 ICA 之前发生的 PCA 分解的前几个维度中被捕获。因此可能不需要大量的成分来区分数据(尽管有时需要更多的成分来获得更准确的解)。首先可以做尝试,我们将使用n_components=15 运行 ICA(仅使用前 15 个 PCA 成分来计算 ICA 分解)——考虑到我们的数据有 59 个良好的 EEG 通道,成分数量相对较小,但其优势在于它可以快速运行,我们将能够轻松判断它是否有效(因为我们已经知道 EOG / ECG 伪影应该是什么样子)。

ICA 拟合具有不确定性(例如,提取出的成分可能会在不同的计算中出现符号翻转,或者可能并不总是以相同的顺序返回),因此我们还将指定一个随机种子,以便每次本教程都获得相同的结果由我们的网络服务器构建。

在拟合 ICA 之前,我们将应用一个共同的平均重参考,以符合 ICLabel 的要求。

filt_raw = filt_raw.set_eeg_reference("average")

输出为:

EEG channel type selected for re-referencing
Applying average reference.
Applying a custom ('EEG',) reference.

我们将使用 “extended infomax” 方法来拟合 ICA,以符合 ICLabel 要求。 ICLabel 未与其他 ICA 分解算法进行测试,但其性能和准确性不应受算法影响。

ica = ICA(
    n_components=15,
    max_iter="auto",
    method="infomax",
    random_state=97,
    fit_params=dict(extended=True),
)
ica.fit(filt_raw)
ica

输出为

Fitting ICA to data using 59 channels (please be patient, this may take a while)
Selecting by number: 15 components
Computing Extended Infomax ICA
Fitting ICA took 3.3s.
Methodinfomax
Fit500 iterations on raw data (36038 samples)
ICA components15
Explained variance91.0 %
Available PCA components59
Channel typeseeg
ICA components marked for exclusion

我们可以传递给 fit函数 方法的一些可选参数包括 decim(在计算 IC 时仅使用每第 N 个样本,可提升快速性)和reject(拒绝每种通道类型提供最大可接受幅值范围的区间)。

现在我们可以查看 IC 以查看它们捕获的内容。 plot_sources 将显示 IC 的时间序列。 请注意,在我们对 plot_sources 的调用中,我们可以使用原始的、未过滤的 Raw 对象:

raw.load_data()
ica.plot_sources(raw, show_scrollbars=False, show=True)

输出为:

Creating RawArray with float64 data, n_channels=16, n_times=36038
    Range : 25800 ... 61837 =     42.956 ...   102.956 secs
Ready.

我们可以很清楚地看到第一个成分 (ICA000) 捕获了 EOG 信号。 我们可以用plot_components 可视化每个组件的头皮场分布。 这些是基于 ICA 混合矩阵中的值进行插值的:

ica.plot_components()

# blinks
ica.plot_overlay(raw, exclude=[0], picks="eeg")

 输出为:

Applying ICA to Raw instance
    Transforming to ICA space (15 components)
    Zeroing out 1 ICA component
    Projecting back using 59 PCA components

 我们还可以使用 plot_properties 单独绘制 IC 图:

ica.plot_properties(raw, picks=[0])

 输出为:

    Using multitaper spectrum estimation with 7 DPSS windows
Not setting metadata
30 matching events found
No baseline correction applied
0 projection items activated

自动选择 ICA 成分

我们可以应用自动 ICA 标记算法,该算法将输出以下七个成分的概率值:

  • brain

  • muscle artifact

  • eye blink

  • heart beat

  • line noise

  • channel noise

  • other

ICLabel label_components 函数的输出按顺序为这些类中的每一个生成预测概率值。详见文献:

Luca Pion-Tonachini, Ken Kreutz-Delgado, and Scott Makeig. Iclabel: an automated electroencephalographic independent component classifier, dataset, and website. NeuroImage, 198:181–197, 2019. URL: https://www.sciencedirect.com/science/article/pii/S1053811919304185doi:https://doi.org/10.1016/j.neuroimage.2019.05.026.

ic_labels = label_components(filt_raw, ica, method="iclabel")

# 例如:ICA0 可以准确地识别为眨眼,ICA12 被归为肌肉伪影。
print(ic_labels["labels"])
ica.plot_properties(raw, picks=[0, 12], verbose=False)

 print输出结果:

['eye blink', 'brain', 'brain', 'brain', 'brain', 'brain', 'muscle artifact', 'muscle artifact', 'other', 'brain', 'muscle artifact', 'muscle artifact', 'muscle artifact', 'muscle artifact', 'eye blink']

 提取标签并重构原始数据

我们可以提取出所有不属于大脑的成分,保留“大脑”和“其他”。 “其他”是不可分类的成分。 保险起见,并假设我们不能盲目地删除这些成分。

labels = ic_labels["labels"]
exclude_idx = [idx for idx, label in enumerate(labels) if label not in ["brain", "other"]]
print(f"Excluding these ICA components: {exclude_idx}")

输出为:

Excluding these ICA components: [0, 6, 7, 10, 11, 12, 13, 14]

现在我们有了需要被剔除的成分,可以用 mne.apply 去除每个通道上信号的伪影,需要注意的是,我们要将对于过滤后的数据得到的 ICA 解决方案作用于原始未滤波的信号。将原始的数据与重构后的数据一同绘制,心跳和眨眼的伪影已得到修复。

# ica.apply() changes the Raw object in-place, so let's make a copy first:
reconst_raw = raw.copy()
ica.apply(reconst_raw, exclude=exclude_idx)

raw.plot(order=artifact_picks, n_channels=len(artifact_picks), show_scrollbars=False)
reconst_raw.plot(order=artifact_picks, n_channels=len(artifact_picks), show_scrollbars=False)
del reconst_raw

 输出为:

Applying ICA to Raw instance
    Transforming to ICA space (15 components)
    Zeroing out 8 ICA components
    Projecting back using 59 PCA components

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值