EEG频谱分析实战:从傅里叶变换到Welch法的Python实现(附代码)
如果你正在处理脑电数据,无论是为了研究认知过程、诊断神经疾病,还是开发脑机接口,频谱分析都是你工具箱里不可或缺的一把利器。它能把看似杂乱无章的脑电波形,翻译成不同频段(比如我们熟知的α波、β波)的能量“语言”,让我们能定量地窥探大脑在不同状态下的活动模式。然而,从理论公式到能跑出结果的代码,中间往往隔着一道鸿沟。很多教程要么过于理论化,要么代码片段零散,让人难以整合到自己的项目里。这篇文章的目的,就是充当一座桥梁。我们将完全聚焦于实战,手把手带你用Python,特别是强大的MNE库,走完从原始EEG数据到频谱特征提取的完整流程。我会分享一些在真实项目中踩过的坑和总结的技巧,目标是让你读完就能在自己的数据上复现并应用这些方法。
1. 环境搭建与数据准备
在开始任何分析之前,一个稳定、可复现的编程环境是基石。对于EEG分析,我强烈推荐使用Anaconda来管理Python环境,它能很好地解决不同库之间的依赖冲突问题。
首先,我们创建一个专属的分析环境:
conda create -n eeg_analysis python=3.9
conda activate eeg_analysis
接下来,安装核心的分析库。mne是处理脑电数据的瑞士军刀,numpy和scipy是数值计算的基石,matplotlib用于可视化,而scikit-learn可能在后续的特征处理中用到。
pip install mne numpy scipy matplotlib scikit-learn
环境就绪后,我们面临第一个实际问题:数据从哪里来?对于初学者,使用公开数据集是最佳起点。MNE-Python内置了多个经典数据集,方便我们快速上手。这里我们以sample数据集为例,它包含了完整的EEG记录和事件标记。
import mne
import numpy as np
import matplotlib.pyplot as plt
# 加载MNE内置的示例数据
data_path = mne.datasets.sample.data_path()
raw_fname = data_path / 'MEG' / 'sample' / 'sample_audvis_filt-0-40_raw.fif'
raw = mne.io.read_raw_fif(raw_fname, preload=True) # preload=True将数据读入内存
# 快速查看数据的基本信息
print(raw)
print(f"采样率: {raw.info['sfreq']} Hz")
print(f"通道名称: {raw.info['ch_names'][:10]}...") # 只显示前10个通道
原始EEG数据通常包含多种类型的噪声,直接进行频谱分析就像在喧闹的菜市场里听人细语。因此,预处理至关重要。一个典型的预处理流程包括以下几个步骤:
- 选择通道:我们可能只关心特定区域的EEG电极,需要先选取出来。
- 滤波:去除高频噪声(如肌电)和极低频漂移。一个常用的带通滤波范围是0.5 Hz到40 Hz。
- 重参考:将每个通道的信号减去所有通道的平均值(平均参考)或特定参考通道的值,以消除共模噪声。
- 剔除坏段和坏通道:识别并剔除因大幅运动伪迹或电极接触不良导致的异常数据段和通道。
下面的代码演示了如何执行滤波和通道选择:
# 1. 选取EEG通道
raw.pick_types(meg=False, eeg=True, eog=False, stim=False)
# 2. 应用带通滤波 (0.5 - 40 Hz)
raw.filter(0.5, 40., fir_design='firwin')
# 绘制滤波后的数据片段进行视觉检查
raw.plot(duration=5, n_channels=30, scalings='auto')
plt.show()
注意:滤波参数的设置需要谨慎。过低的截止频率可能滤除有意义的慢波信号,而过高的截止频率则可能保留过多的肌电噪声。具体设置需根据你的研究问题和数据质量决定。

301

被折叠的 条评论
为什么被折叠?



