4. 脑电数据加载与可视化:MNE库入门、读取EDF/GDF格式数据、绘制脑电通道波形、功率谱密度(PSD)图绘制
好,咱们进入实操环节。说实话,很多同学学深度学习做运动想象,第一步就卡在数据加载上。你想想看,算法再牛,数据读不进来全是白搭。这一章我就带你搞定脑电数据的读取和可视化,用的工具是MNE——Python生态里最成熟的脑电分析库。
4.1 MNE库入门:为什么选它?
MNE全称是MNE-Python,最初是为脑磁图(MEG)设计的,后来把EEG也支持得非常好。我个人习惯用MNE做数据预处理,因为它把滤波、降采样、ICA去伪迹这些操作都封装得很优雅。
安装很简单:
pip install mne
如果你用Anaconda,也可以:
conda install -c conda-forge mne
嗯,这里要注意一点:MNE的版本迭代挺快的,我建议你装最新版(至少1.0以上),有些旧接口在新版里已经废弃了。我在项目中遇到过因为版本不匹配导致代码跑不通的情况,排查了半天才发现是API变了。
4.2 读取EDF/GDF格式数据
运动想象脑电数据最常见的格式就是EDF(European Data Format)和GDF(General Data Format)。BCI Competition IV的2a、2b数据集用的就是GDF。MNE读取它们只需要一行代码:
import mne
# 读取EDF文件
raw = mne.io.read_raw_edf('subject01.edf', preload=True)
# 读取GDF文件
raw = mne.io.read_raw_gdf('A01T.gdf', preload=True)
preload=True这个参数我建议你加上。如果不加,MNE会采用懒加载模式,数据不直接读入内存,后续操作会变慢。做深度学习训练时,数据频繁访问,预加载能省不少时间。
读取之后,看看数据的基本信息:
print(raw.info)
print(raw.ch_names)
print(raw.n_times)
你会看到通道名称、采样率、数据时长等信息。BCI Competition IV 2a数据集是22个EEG通道 + 3个EOG通道,采样率250Hz,每个trial持续4秒。
核心知识点:MNE的raw对象是整个数据管线的起点。滤波、降采样、提取事件、切割epochs,全都要基于它。
4.3 绘制脑电通道波形
数据读进来了,第一件事就是看看波形长什么样。MNE的绘图功能非常强大,一行代码就能画出所有通道的时序图:
raw.plot(n_channels=10, duration=5.0, scalings='auto')
这个函数会弹出一个交互式窗口,你可以滚动、缩放、标记坏段。我个人习惯先看30秒的全局波形,快速判断有没有明显的工频干扰或肌电伪迹。
如果你只想看特定通道:
raw.plot(picks=['C3', 'C4', 'Cz'], duration=5.0)
C3、C4、Cz是运动想象最关键的通道。为什么?因为运动皮层的mu节律(8-12Hz)和beta节律(13-30Hz)在这些通道上最明显。我在做左手vs右手分类时,C3和C4的功率差异就是核心特征。
小技巧:如果波形图看起来全是毛刺,先检查一下是不是没做滤波。50Hz(或60Hz)的工频干扰会让波形变得很难看。用raw.filter(1, 40)先带通滤波一下,波形会干净很多。
4.4 功率谱密度(PSD)图绘制
波形图看的是时域信息,PSD图看的是频域信息。运动想象的核心就是不同频段的能量变化,所以PSD几乎是必看的。
MNE计算PSD有两种方式:
- 基于整个raw对象:看全局频谱分布
- 基于epochs:看不同trial条件下的频谱差异
先看全局PSD:
raw.plot_psd(fmin=1, fmax=40, average=True)
这个图会显示每个通道的功率谱密度曲线。你会看到在8-12Hz附近有一个明显的峰,那就是mu节律。如果受试者在做运动想象,这个峰的功率会下降——这就是所谓的「事件相关去同步」(ERD)。
更精细的做法是分条件看PSD。比如左手想象和右手想象:
# 先提取事件和epochs
events, event_dict = mne.events_from_annotations(raw)
epochs = mne.Epochs(raw, events, event_id=event_dict, tmin=-0.5, tmax=4.0)
# 分条件绘制PSD
epochs['left'].plot_psd(fmin=1, fmax=40)
epochs['right'].plot_psd(fmin=1, fmax=40)
对比两张图,你会发现C4通道(对侧运动皮层)在8-12Hz的功率明显低于C3通道。这就是运动想象的神经生理学基础。
避坑指南:我曾经在绘制PSD时发现所有通道的功率都异常高,排查了半天才发现是数据没做基线校正。MNE的epochs默认会做基线校正(基于tmin到0这段时间),但如果你手动改了参数,记得检查一下。另外,PSD的纵轴单位是dB还是μV²/Hz?MNE默认是dB,但有些论文用μV²/Hz,换算时要小心。
4.5 本章知识体系
下面这张图总结了本章的核心流程:
4.6 实战要点总结
| 步骤 | 关键函数 | 常见坑点 | 我的建议 |
|---|---|---|---|
| 数据读取 | read_raw_edf / read_raw_gdf | 忘记加preload=True | 始终预加载,除非内存不够 |
| 波形查看 | raw.plot() | 没滤波导致波形杂乱 | 先做1-40Hz带通滤波 |
| 事件提取 | events_from_annotations | 事件ID映射错误 | 打印event_dict确认 |
| PSD绘制 | epochs.plot_psd() | 基线未校正、单位混淆 | 检查tmin和tmax参数 |
一句话总结:MNE把脑电数据加载和可视化变成了几行代码的事,但真正理解每个步骤背后的生理意义,才能用好这些工具。波形图看伪迹,PSD图看频段能量,两者结合就是运动想象特征提取的基础。