4、EEG数据读取与可视化:常用EEG数据格式(.edf, .set, .fif)、MNE-Python库安装与入门、读取原始数据、绘制多通道波形图
说实话,做EEG深度学习的第一步,往往不是搭模型,而是先把数据搞到手、读进来、看清楚。我见过太多同学一上来就调网络,结果数据格式不对、通道名搞混、采样率理解错了——折腾半天全是白费功夫。所以这一章,咱们先把数据读取和可视化这块地基打牢。
4.1 常用EEG数据格式:.edf、.set、.fif
EEG数据格式五花八门,但主流就三种。我这些年接触过的数据集,90%都逃不出这几个格式。
| 格式 | 扩展名 | 典型来源 | 特点 |
|---|---|---|---|
| EDF | .edf / .edf+ | 医院、公开数据集(如PhysioNet) | 最通用,跨平台,但头信息有限 |
| EEGLAB | .set + .fdt | MATLAB用户、EEGLAB工具箱 | 包含电极位置、事件信息,结构清晰 |
| FIF | .fif | MNE-Python原生格式、MEG/EEG联合采集 | 信息最完整,但文件较大 |
.edf格式——说白了就是欧洲数据格式的缩写。我在医院合作项目里经常遇到,优点是几乎所有EEG采集设备都能导出这个格式。但有个坑:它的头文件只支持ASCII字符,中文电极名存进去会乱码。我曾经因为这个排查了半天,后来发现是设备导出的电极名带了个“-Ref”后缀,MNE读进来直接报错。
.set格式——EEGLAB的老用户应该很熟悉。一个.set文件配一个.fdt(二进制数据文件)。我个人习惯用MNE读.set时,记得把两个文件放在同一目录下,不然会提示找不到数据。
.fif格式——这是MNE-Python的亲儿子格式。如果你用MNE做预处理,最后保存成.fif是最稳妥的。它能把电极位置、事件标记、坏道信息全打包进去。嗯,这里要注意:.fif文件通常比较大,一个30分钟的64通道数据,轻松上200MB。
4.2 MNE-Python库安装与入门
MNE-Python是EEG/MEG数据处理的事实标准。我建议你用conda安装,省心。
# 推荐用conda创建独立环境
conda create -n eeg_env python=3.9
conda activate eeg_env
# 安装MNE核心库
conda install -c conda-forge mne
# 如果需要处理.edf,额外装这个
pip install pyedflib
# 可视化增强(我必装)
pip install matplotlib scipy
为什么会推荐conda?因为MNE依赖的numpy、scipy版本比较敏感,用pip装有时候会碰到二进制兼容问题。我在一台新服务器上踩过这个坑,折腾了俩小时才搞定。
装好之后,快速验证一下:
import mne
print(mne.__version__) # 我目前用的是1.6.0
如果没报错,恭喜你,环境搭好了。
4.3 读取原始数据
不同格式的读取方式略有不同,但MNE统一了接口。咱们一个一个来。
4.3.1 读取.edf文件
import mne
# 读取EDF文件
raw = mne.io.read_raw_edf('sample.edf', preload=True)
# 看一眼基本信息
print(raw.info)
print(raw.ch_names)
print(raw.n_times) # 总采样点数
preload=True这个参数我建议新手都加上。它会把数据一次性加载到内存,后续操作快很多。如果文件特别大(比如超过2GB),可以设成False,按需读取。
4.3.2 读取.set文件
# 读取EEGLAB格式
raw = mne.io.read_raw_eeglab('sample.set', preload=True)
# 如果电极位置信息没读进来,可以手动加载
montage = mne.channels.make_standard_montage('standard_1020')
raw.set_montage(montage)
这里有个坑:有些.set文件里的电极名是数字编号(比如“1”、“2”),而不是标准名称(比如“Fz”、“Cz”)。我建议你读完后打印raw.ch_names检查一下,如果全是数字,得手动映射。
4.3.3 读取.fif文件
# 读取FIF格式(最省心)
raw = mne.io.read_raw_fif('sample.fif', preload=True)
# FIF格式通常自带电极位置和事件
print(raw.annotations) # 查看事件标记
FIF格式的好处是信息完整。我一般预处理完数据,最后一步就是保存成.fif:
raw.save('cleaned_raw.fif', overwrite=True)
4.4 绘制多通道波形图
数据读进来了,第一件事就是画图看看。MNE的绘图功能很强大,但参数也多。我挑几个最常用的讲。
4.4.1 基础波形图
# 绘制所有通道的波形
raw.plot(n_channels=10, duration=5.0, scalings='auto')
# 只画特定通道
picks = ['Fz', 'Cz', 'Pz', 'Oz']
raw.plot(picks=picks, duration=10.0)
scaling='auto'会自动调整每个通道的显示幅度。我个人习惯手动设一下,比如脑电通道设成100μV,眼电通道设成500μV,这样看起来更直观。
4.4.2 绘制功率谱密度图
# 绘制功率谱
raw.plot_psd(fmin=0.5, fmax=45.0, picks='eeg')
# 也可以指定频带
raw.plot_psd(fmin=8.0, fmax=12.0, picks='eeg') # 只看alpha频段
为什么要看功率谱?说白了就是检查数据质量。如果50Hz处有个尖峰,说明工频干扰没滤干净。如果低频段(<1Hz)能量特别高,可能有漂移。我在实际项目中,每次拿到新数据都会先画个PSD图,心里就有数了。
4.4.3 绘制电极位置图
# 绘制电极位置(需要先设置montage)
raw.plot_sensors(show_names=True)
# 3D版(需要安装mayavi或pyvista)
raw.plot_sensors(kind='3d')
电极位置图能帮你快速检查电极是否放对了位置。我曾经遇到过一个数据集,标注的是“标准1020系统”,但画出来一看,Cz跑到额头上了——明显是坐标映射错了。
4.5 本章知识体系
下面这张图总结了本章的核心逻辑,我画成了流程图,方便你对照着看:
核心要点:数据读取是EEG深度学习的起点。格式选对、库装好、读进来、画出来——这四步走完,你才算真正拿到了数据。
小技巧:如果你不确定数据格式,可以用mne.what('filename')查看。这个函数会自动识别格式,省得你猜。
注意:读取.set文件时,如果报错“未找到.fdt文件”,检查一下两个文件是否在同一目录。我曾经把.fdt放在子文件夹里,结果MNE找不到,排查了半小时才发现是路径问题。
好了,数据读进来了,图也画出来了。下一步就是预处理——滤波、去伪迹、分段。但那是下一章的事。先把这章的内容跑通,你就算正式入门了。
公众号:蓝海资料掘金营,微信deep3321