[实战指南+数据解析] DEAP数据集:基于EEG、生理与视频信号的多模态情感计算入门
1. DEAP数据集入门:多模态情感计算的钥匙
第一次接触DEAP数据集时,我被它丰富的多模态数据震撼到了。这个数据集就像情感计算领域的"瑞士军刀",包含了EEG脑电波、皮肤电导等生理信号,还有22名参与者的面部视频记录。最特别的是,所有数据都围绕着40段精心挑选的音乐视频展开,每段视频都带有详细的情感评分标签。
数据集的核心价值在于它的"三维情感模型"——用唤醒度(arousal)、愉悦度(valence)和支配度(dominance)这三个维度来量化人类情感。举个例子,当你看恐怖片时,唤醒度会飙升(因为紧张),愉悦度下降(因为害怕),支配度也可能降低(感觉被剧情控制)。这种量化方式比简单地说"开心"或"难过"精确多了。
我建议新手先从预处理后的数据入手(Python或Matlab格式),因为原始BDF文件处理起来相当麻烦。记得第一次处理原始EEG数据时,我花了整整一周时间才搞明白那些电极排列和信号转换。预处理版本已经帮我们完成了降采样、滤波、分段这些繁琐工作,可以直接喂给机器学习模型。
2. 数据获取与权限申请实战
申请DEAP数据集的过程比想象中严格。去年帮实验室申请时,发现必须用机构邮箱(比如.edu或.ac.cn结尾的),还要提供在职证明网页链接。有个博士生用Gmail申请直接被拒了,所以一定要准备好这些材料。
数据集下载页面提供了多种格式选择:
- 元数据:CSV/Excel格式(建议用CSV,兼容性更好)
- 生理信号:原始BDF(5.8GB)/预处理Matlab(2.9GB)/Python(2.7GB)
- 面部视频:AVI格式(15.3GB)
这里有个实用技巧:大文件下载时用wget比浏览器更可靠。我遇到过三次下载到90%断连的情况,后来用这个命令就稳了:
wget --user=你的账号 --password=你的密码 http://deap.dataset.url/data_preprocessed_python.zip下载完成后,目录结构是这样的:
DEAP/ ├── metadata/ │ ├── online_ratings.csv │ ├── video_list.csv │ └── ... ├── data_preprocessed/ │ ├── s01.dat │ └── ... └── face_video/ ├── s01/ │ ├── s01_trial01.avi │ └── ... └── ...3. 数据深度解析与特征工程
预处理后的Python数据用cPickle加载非常简单:
import cPickle with open('s01.dat', 'rb') as f: data, labels = cPickle.load(f)这个data数组的维度(40×40×8064)很有意思:
- 第一个40:40段音乐视频
- 第二个40:40个信号通道(32个EEG+8个生理信号)
- 8064:60秒×128Hz采样率(去掉3秒基线后)
我常用这个特征提取方案:
def extract_features(data): # 时域特征 mean = np.mean(data, axis=2) std = np.std(data, axis=2) # 频域特征 psd = np.abs(np.fft.fft(data, axis=2)[:,:,:40]) # 取前40个频点 delta = psd[:,:,1:4].mean(axis=2) # 1-4Hz theta = psd[:,:,4:8].mean(axis=2) # 4-8Hz return np.concatenate([mean, std, delta, theta], axis=1)对于面部视频,OpenCV的Dlib库是提取表情特征的好帮手:
import dlib detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") def get_landmarks(video_path): cap = cv2.VideoCapture(video_path) landmarks = [] while cap.isOpened(): ret, frame = cap.read() if not ret: break faces = detector(frame) for face in faces: shape = predictor(frame, face) landmarks.append(np.array([[p.x,p.y] for p in shape.parts()])) return np.array(landmarks)4. 多模态融合建模实战
单模态模型效果有限,我试过把EEG、生理信号和面部特征融合后,准确率提升了近20%。这里分享一个简单的融合方案:
from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import StandardScaler # 假设已经提取了三种模态的特征 eeg_features = extract_features(eeg_data) # (40, 120) physio_features = process_physio(physio_data) # (40, 30) face_features = get_face_features(videos) # (40, 136) # 特征融合 scaler = StandardScaler() X = scaler.fit_transform(np.hstack([eeg_features, physio_features, face_features])) y = labels[:, 0] > 5 # 二分类:高愉悦度vs低愉悦度 # 训练模型 model = RandomForestClassifier(n_estimators=100) model.fit(X, y)几个提升性能的小技巧:
- 对EEG信号,试试微分熵特征(Differential Entropy),在情感识别中效果显著
- 生理信号中,GSR(皮肤电导)对唤醒度特别敏感
- 面部特征要注意时序信息,LSTM比单纯用均值效果更好
验证模型时,务必使用留一被试出(Leave-One-Subject-Out)交叉验证,因为不同人的生理信号差异很大。我曾经犯过用全部数据做随机划分的错误,结果模型在实际应用中完全失效。
5. 避坑指南与进阶建议
第一个大坑是数据不平衡。查看label分布时,我发现高唤醒样本比低唤醒多30%。解决方案很简单:
from imblearn.over_sampling import SMOTE X_resampled, y_resampled = SMOTE().fit_resample(X, y)第二个坑是信号质量。有些参与者的EEG数据噪声很大(特别是眨眼多的)。我的处理流程:
- 用ICA去除眼电伪迹
- 剔除信噪比<15dB的片段
- 对缺失值用相邻通道插补
进阶方向可以考虑:
- 注意力机制融合多模态特征
- 用对比学习增强表征能力
- 构建端到端的Transformer架构
最后提醒:DEAP的EEG采样率是128Hz(预处理后),做频域分析时要注意Nyquist极限。有次我试图提取60Hz以上的gamma波特征,结果全是噪声,白白浪费了两天时间。
