用Python玩转DEAP情绪数据集:从脑电信号到情感标签的完整实战指南

张开发
2026/4/16 9:19:36 15 分钟阅读

分享文章

用Python玩转DEAP情绪数据集:从脑电信号到情感标签的完整实战指南
用Python玩转DEAP情绪数据集从脑电信号到情感标签的完整实战指南当你第一次打开DEAP数据集时那些.mat文件里密密麻麻的数字矩阵可能会让你感到无从下手——32个脑电通道、8064个采样点、三维情感标签这些专业术语就像一堵高墙。但别担心这篇指南会像手术刀一样精准地解剖这个复杂的数据集带你从原始信号一直走到可运行的情感预测模型。1. 理解DEAP数据集的核心结构在开始写代码之前我们需要像侦探一样仔细审视这个数据集的犯罪现场。DEAP数据集实际上是一个精心设计的心理学实验产物每个数据点背后都对应着被试者观看音乐视频时的生理反应。1.1 数据文件的解剖学下载解压后的文件夹里你会看到两种预处理版本data_preprocessed_matlab/MATLAB格式的.mat文件data_preprocessed_python/Python专用的.dat文件每个文件对应一个被试者包含两个关键数组data: 形状为(40, 40, 8064)的numpy数组 labels: 形状为(40, 4)的numpy数组这个三维数组可以这样理解第一维4040段不同的音乐视频刺激第二维4040个生理信号通道32个EEG8个其他第三维8064128Hz采样率下63秒的数据点含3秒基线1.2 情感维度的密码本labels数组的4列分别对应效价(Valence)1-9分从负面到正面情绪唤醒度(Arousal)1-9分从平静到兴奋状态优势度(Dominance)1-9分从被动接受到主动控制喜爱度(Liking)1-9分个人主观喜好评分注意实际研究中通常只使用前三个维度因为它们是情感计算的标准模型2. 数据加载与初步探索现在让我们打开Python工具箱开始真正的数据处理之旅。这里推荐使用MNE库——它是处理脑电信号的瑞士军刀。2.1 搭建你的Python工作环境首先确保安装这些关键库pip install mne scikit-learn pandas matplotlib seaborn2.2 读取.mat文件的正确姿势虽然可以直接用scipy.io.loadmat但DEAP的.mat文件有特殊结构import scipy.io import numpy as np def load_deap_data(file_path): mat scipy.io.loadmat(file_path) data mat[data] # (40, 40, 8064) labels mat[labels] # (40, 4) return data, labels # 示例加载第一个被试的数据 data, labels load_deap_data(data_preprocessed_matlab/s01.mat)2.3 可视化脑电信号的时间序列让我们看看原始EEG信号长什么样。选择第一个视频片段的FP1通道前额叶区域import matplotlib.pyplot as plt # 提取第一个视频、第一个通道的所有采样点 eeg_sample data[0, 0, :] plt.figure(figsize(12, 4)) plt.plot(np.arange(0, 63, 1/128), eeg_sample) # 时间轴 plt.xlabel(Time (s)) plt.ylabel(Amplitude (μV)) plt.title(FP1 Channel EEG Signal During Video 1) plt.grid(True) plt.show()你会看到一个充满振荡的波形图——这些就是大脑神经元集体放电产生的电活动。3. 专业级的EEG信号处理技术原始EEG信号就像未经加工的矿石我们需要一系列专业处理才能提取有价值的信息。3.1 频带分解大脑的无线电频道EEG信号可以分解为不同频率的振荡波频带名称频率范围 (Hz)心理状态关联Delta0.5-4深度睡眠Theta4-8冥想、创造力Alpha8-13放松清醒Beta13-30主动思考Gamma30-100信息整合使用MNE进行频带功率计算import mne # 创建虚拟的Raw对象FP1通道示例 info mne.create_info([FP1], sfreq128, ch_typeseeg) raw mne.io.RawArray(data[0, 0:1, :], info) # 计算各频带功率 freq_bands {Delta: (0.5, 4), Theta: (4, 8), Alpha: (8, 13), Beta: (13, 30), Gamma: (30, 45)} band_powers mne.time_frequency.psd_array_multitaper( data[0, 0:1, :], 128, fmin0.5, fmax45, bandwidth1, verboseFalse)3.2 眼电伪迹的识别与处理眨眼和眼球运动会产生大幅度的EOG伪迹。虽然DEAP数据已经过预处理但了解原理很重要# 提取水平眼电信号(HEOG) heog data[0, 32, :] plt.figure(figsize(12, 3)) plt.plot(heog) plt.title(Horizontal EOG Signal with Blink Artifacts) plt.xlabel(Samples) plt.ylabel(Amplitude (μV)) plt.axhline(y100, colorr, linestyle--) # 眨眼阈值 plt.show()4. 构建情感预测模型现在来到最激动人心的部分——让机器学习理解人类情感。我们将构建一个端到端的分类器。4.1 特征工程从信号到特征向量好的特征比复杂的模型更重要。以下是我们提取的典型特征时域特征均值、方差、偏度、峰度Hjorth参数活动性、移动性、复杂性频域特征各频带相对功率频带间不对称性from scipy.stats import skew, kurtosis def extract_features(eeg_segment): features [] # 时域特征 features.append(np.mean(eeg_segment)) features.append(np.std(eeg_segment)) features.append(skew(eeg_segment)) features.append(kurtosis(eeg_segment)) # 频域特征简化版 psd np.abs(np.fft.fft(eeg_segment))**2 freqs np.fft.fftfreq(len(eeg_segment), 1/128) for band, (low, high) in freq_bands.items(): mask (freqs low) (freqs high) features.append(np.mean(psd[mask])) return np.array(features)4.2 构建情感分类器我们将效价和唤醒度分别建模为二分类问题高/低以5分为界from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 准备数据集示例使用第一个被试 X [] y_valence [] y_arousal [] for vid in range(40): # 提取所有通道特征简化处理 vid_features [] for ch in range(32): # 只用EEG通道 vid_features.extend(extract_features(data[vid, ch, :])) X.append(vid_features) # 创建标签1高0低 y_valence.append(1 if labels[vid, 0] 5 else 0) y_arousal.append(1 if labels[vid, 1] 5 else 0) X np.array(X) y_valence np.array(y_valence) y_arousal np.array(y_arousal) # 训练效价分类器 X_train, X_test, y_train, y_test train_test_split( X, y_valence, test_size0.2, random_state42) clf RandomForestClassifier(n_estimators100) clf.fit(X_train, y_train) preds clf.predict(X_test) print(fValence Accuracy: {accuracy_score(y_test, preds):.2f})在我的测试中这个简单模型能达到约65-70%的准确率——对于生理信号来说已经不错了5. 高级技巧与优化方向当你掌握了基础流程后这些进阶技术可以进一步提升性能5.1 跨被试建模的挑战DEAP包含32个被试的数据但个体差异很大。处理策略标准化对每个被试单独进行z-score标准化迁移学习使用预训练模型进行微调群体建模添加被试ID作为额外特征5.2 深度学习架构探索对于更复杂的模型可以尝试from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv1D, LSTM, Dense model Sequential([ Conv1D(64, 3, activationrelu, input_shape(8064, 1)), Conv1D(128, 3, activationrelu), LSTM(64), Dense(1, activationsigmoid) ]) model.compile(optimizeradam, lossbinary_crossentropy)5.3 实时情感识别系统将整个流程产品化的关键步骤信号采集使用OpenBCI等廉价EEG设备在线处理实现滑动窗口特征提取模型部署使用Flask构建API服务反馈界面实时可视化情感状态我在一个音乐推荐项目中实际应用过这个流程最大的挑战是处理个体差异——同一个音乐片段不同人的脑电反应可能截然不同。解决方法是为每个用户收集少量校准数据进行个性化微调。

更多文章