Python实战:用Scikit-learn处理EEG信号实现睁眼闭眼分类(附完整代码)

张开发
2026/5/6 17:59:34 15 分钟阅读

分享文章

Python实战:用Scikit-learn处理EEG信号实现睁眼闭眼分类(附完整代码)
Python实战用Scikit-learn处理EEG信号实现睁眼闭眼分类脑电信号EEG分析是神经科学和脑机接口领域的重要研究方向。本文将带你从零开始使用Python和Scikit-learn库完成一个完整的EEG信号处理流程实现睁眼和闭眼状态的分类任务。不同于理论讲解我们会聚焦于实际代码实现和工程细节。1. 环境准备与数据加载在开始之前确保你的Python环境已安装以下必要库pip install numpy pandas scikit-learn matplotlib mneMNE-Python是一个专门用于处理神经生理学数据的强大库。我们将使用它来加载和预处理EEG数据。import numpy as np import pandas as pd import mne from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline from sklearn.svm import SVC from sklearn.metrics import classification_report对于本教程我们将使用一个公开的EEG数据集其中包含受试者在睁眼和闭眼状态下的脑电记录。你可以从以下链接下载示例数据提示实际项目中你可能需要根据具体需求调整数据加载方式。临床EEG数据通常采用.edf或.fif格式。2. EEG数据预处理流程EEG信号的预处理是分析成功的关键。原始EEG数据通常包含各种噪声和伪迹需要通过以下步骤进行清理2.1 滤波处理EEG信号的有效成分通常在0.5-30Hz范围内。我们需要使用带通滤波器去除无关频率成分raw_data.filter(0.5, 30., fir_designfirwin)注意滤波参数的设置应根据具体实验设计调整。例如研究gamma波可能需要更高的截止频率。2.2 伪迹去除常见的EEG伪迹包括眼电伪迹眨眼和眼动肌电伪迹肌肉活动心电伪迹线路噪声50/60Hz我们可以使用独立成分分析(ICA)来识别和去除这些伪迹ica mne.preprocessing.ICA(n_components20, random_state97) ica.fit(raw_data) ica.exclude [0, 1] # 假设前两个成分是伪迹 ica.apply(raw_data)2.3 分段与基线校正将连续EEG数据分割为固定长度的epochs并进行基线校正events mne.find_events(raw_data) epochs mne.Epochs(raw_data, events, tmin-0.2, tmax1.0, baseline(-0.2, 0), preloadTrue)3. 特征提取与选择EEG信号的特征提取是将高维时序数据转换为有意义的低维表示的关键步骤。以下是几种常用的特征类型特征类型描述适用场景时域特征均值、方差、峰度等统计量简单快速计算量小频域特征功率谱密度、频带能量适合分析脑波节律时频特征小波变换、短时傅里叶变换捕捉动态变化非线性特征熵、分形维数复杂认知状态分析对于睁眼/闭眼分类频域特征通常效果良好。我们可以计算各频段的平均功率from mne.time_frequency import psd_welch freqs np.arange(1, 30, 1) # 1-30Hz步长1Hz psds, freqs psd_welch(epochs, fmin1, fmax30, n_overlap150, n_fft256) # 提取各频带能量 def bandpower(psd, freqs, band): low, high band idx np.where((freqs low) (freqs high))[0] return np.mean(psd[:, :, idx], axis2) alpha bandpower(psds, freqs, [8, 13]) # alpha波(8-13Hz) beta bandpower(psds, freqs, [13, 30]) # beta波(13-30Hz)4. 构建分类模型有了特征后我们可以构建机器学习模型进行分类。Scikit-learn提供了多种分类器选择4.1 数据准备首先将特征和标签整理为适合Scikit-learn的格式X np.concatenate([alpha, beta], axis1) # 组合特征 y epochs.events[:, -1] # 获取标签 # 划分训练集和测试集 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42)4.2 模型选择与训练支持向量机(SVM)在EEG分类任务中表现良好特别是对于中小规模数据集model make_pipeline( StandardScaler(), SVC(kernelrbf, C1.0, gammascale, random_state42) ) model.fit(X_train, y_train)注意EEG数据通常维度较高而样本量有限容易过拟合。交叉验证和正则化非常重要。4.3 模型评估使用测试集评估模型性能y_pred model.predict(X_test) print(classification_report(y_test, y_pred))典型输出可能如下precision recall f1-score support 0 0.89 0.85 0.87 40 1 0.86 0.90 0.88 40 accuracy 0.87 80 macro avg 0.88 0.87 0.87 80 weighted avg 0.88 0.87 0.87 805. 优化与改进基础模型搭建完成后我们可以从多个角度进行优化5.1 特征工程改进尝试更多类型的特征组合加入theta波(4-8Hz)和delta波(1-4Hz)特征尝试时频联合分析加入左右半球不对称性特征theta bandpower(psds, freqs, [4, 8]) delta bandpower(psds, freqs, [1, 4]) X np.concatenate([delta, theta, alpha, beta], axis1)5.2 模型调优使用网格搜索寻找最优超参数from sklearn.model_selection import GridSearchCV param_grid { svc__C: [0.1, 1, 10, 100], svc__gamma: [scale, auto, 0.01, 0.1, 1] } grid GridSearchCV(model, param_grid, cv5, n_jobs-1) grid.fit(X_train, y_train)5.3 集成学习方法尝试随机森林或梯度提升树等集成方法from sklearn.ensemble import RandomForestClassifier rf_model make_pipeline( StandardScaler(), RandomForestClassifier(n_estimators100, max_depth5, random_state42) )6. 完整代码实现以下是整合了上述所有步骤的完整代码示例# 省略导入语句同上 # 1. 数据加载 raw_data mne.io.read_raw_edf(eeg_data.edf, preloadTrue) # 2. 预处理 raw_data.filter(0.5, 30.) ica mne.preprocessing.ICA(n_components20, random_state97) ica.fit(raw_data) ica.exclude [0, 1] ica.apply(raw_data) # 3. 分段 events mne.find_events(raw_data) epochs mne.Epochs(raw_data, events, tmin-0.2, tmax1.0, baseline(-0.2, 0), preloadTrue) # 4. 特征提取 psds, freqs psd_welch(epochs, fmin1, fmax30, n_overlap150, n_fft256) alpha bandpower(psds, freqs, [8, 13]) beta bandpower(psds, freqs, [13, 30]) X np.concatenate([alpha, beta], axis1) y epochs.events[:, -1] # 5. 模型训练与评估 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2) model make_pipeline(StandardScaler(), SVC(kernelrbf)) model.fit(X_train, y_train) y_pred model.predict(X_test) print(classification_report(y_test, y_pred))在实际项目中我发现alpha波特征对睁眼/闭眼分类特别重要但不同受试者间存在显著差异。因此个性化模型或迁移学习技术可能会进一步提高性能。

更多文章