首页 / 资讯中心 / 文章详情

基于DEAP与SEED-IV的EEG情绪检测:从预处理到通道级SVM分类全流程

基于DEAP与SEED-IV的EEG情绪检测:从预处理到通道级SVM分类全流程 ★ FEATURED ARTICLE
简介该资源是一篇面向情感计算与脑机接口方向学习者的研究论文聚焦基于EEG信号的情绪检测适合做毕业设计、课程研究或入门脑电信号处理的学生参考。论文以DEAP和SEED-IV两个公开数据库为数据来源采用离散小波变换将预处理信号分解为5个频段提取功率、能量、微分熵和时域等特征并构建通道级SVM分类器与通道组合器完成二维情绪模型下的状态识别四类分类准确率在DEAP上为74%、86%、72%、84%在SEED-IV上为79%、76%、77%、74%。资源包共1个PDF文件约701KB内容为完整的英文论文正文涵盖摘要、引言、相关工作、方法设计与实验结果可帮助读者理解EEG情绪检测的完整技术路线与特征工程思路。目前已有346人学习适合需要复现实验流程或撰写相关论文的研究者参考。1. 从一份公开数据集出发EEG 情绪检测方案要解决什么做毕设最怕的不是算法难而是数据拿不到、流程跑不通、结果说不清。这套方案要解决的就是这件事用 DEAP 和 SEED-IV 两个公开脑电数据库把「原始 EEG 信号 → 预处理 → 特征提取 → 通道级 SVM 分类 → 通道融合 → 四类情绪判定」这条链路完整走通最终给出可复现的分类准确率。它适合正在做脑机接口、情感计算方向毕业设计或课程设计的学生也适合需要快速搭一套生理信号分类基线的从业者。整套方案不依赖自采设备全部基于公开数据硬件门槛为零难点集中在信号处理和特征工程上。2. 数据与预处理设计两个数据库的差异怎么抹平DEAP 和 SEED-IV 的采集协议完全不同直接混用会翻车。DEAP 是 32 通道、500Hz 采样、32 名被试、每人 40 段 1 分钟视频刺激SEED-IV 是 64 通道、1000Hz 采样、15 名被试、每人 3 个 session、每个 session 24 段 2 分钟视频。通道数、采样率、事件时长全对不上所以方案里必须先把「统一口径」这件事做扎实否则后面特征维度对不齐SVM 直接报错。2.1 事件切分与通道对齐DEAP 原始数据是连续记录需要按采集协议把每段视频对应的时间窗切出来转成 mat 文件SEED-IV 官方给的就是已经切好的 mat事件是预分离的。这一步的关键是只保留两个库共有的通道方案里统一取 32 通道作为特征计算的基础SEED-IV 多出来的通道在预处理阶段就裁掉。采样率方面SEED-IV 的 1000Hz 数据在读取后做降采样到与 DEAP 一致的量级保证后续 DWT 分解的频带边界含义一致。import scipy.io as sio import numpy as np from scipy.signal import resample def load_deap(path): # DEAP 的 mat 里 data 字段形状为 [ trials, channels, samples ] raw sio.loadmat(path) data raw[data] # 40 x 40 x 8064前 32 通道是 EEG eeg data[:, :32, :] # 只取 32 个 EEG 通道 return eeg def load_seed4(path, target_fs500): raw sio.loadmat(path) eeg raw[data] # 已切分的事件数据 orig_fs 1000 if orig_fs ! target_fs: n_samples int(eeg.shape[-1] * target_fs / orig_fs) eeg resample(eeg, n_samples, axis-1) return eeg上面两个函数把「通道对齐」和「采样率对齐」一次做完。data[:, :32, :]这行是血泪经验DEAP 的 mat 里第 33 到 40 通道是外周生理信号眼电、肌电等不裁掉会污染特征。resample的axis-1表示沿时间轴重采样别写成axis0否则会把通道数改掉。2.2 三级滤波链的设计逻辑预处理不是随便套个带通就完事。方案里用三级滤波串联先 50Hz 陷波去工频干扰国内电网 50Hz用 60Hz 会漏再做平均参考重参考最后 0.1–60Hz 带通把信号限制在 EEG 有效频段内。中间还插了一级 10 阶一维中值滤波去脉冲噪声。顺序不能乱——陷波必须在带通之前否则 50Hz 成分会被带通部分保留中值滤波放在重参考之后避免参考电极引入的直流量被中值滤波误判成脉冲。from scipy.signal import iirnotch, filtfilt, medfilt, butter def preprocess(eeg, fs500): # 1) 50Hz 陷波 b, a iirnotch(50, 30, fs) eeg filtfilt(b, a, eeg, axis-1) # 2) 平均参考 eeg eeg - eeg.mean(axis1, keepdimsTrue) # 3) 10 阶中值滤波去脉冲 eeg medfilt(eeg, kernel_size(1, 1, 11)) # 4) 0.1-60Hz 带通20 阶 b, a butter(10, [0.1, 60], btypeband, fsfs) eeg filtfilt(b, a, eeg, axis-1) return eegiirnotch(50, 30, fs)里第二个参数是品质因数30 对应较窄的陷波带宽既能压住工频又不会把邻近频段削掉。medfilt的kernel_size(1,1,11)表示只在时间维做 11 点中值通道维不动。带通的butter(10, ...)是 10 阶对应原文的 20 阶滤波器butter的阶数是实际阶数的一半语义这里按等效陡度取 10。filtfilt做零相位滤波避免相位延迟导致事件时间窗错位——这一点在情绪检测里很关键因为情绪响应本身就有几百毫秒的潜伏期。注意中值滤波的核长必须是奇数写成 10 会直接抛异常另外medfilt对多维数组的kernel_size要写全维度只写一个整数会作用到所有轴。3. 特征工程与通道级分类器34 维特征向量怎么来特征提取是整个方案里最影响准确率的一环。原文用 8 层 db8 小波分解出 delta、theta、alpha、beta、gamma 五个频带再在每个频带上算能量、功率谱密度、微分熵、平均带功率加上时域统计量和 Hjorth 参数凑成 34 维特征。这个维度不是拍脑袋定的是「时域 12 维 频域 20 维 其他 2 维」的组合刚好能喂给每个通道一个独立 SVM。3.1 五频带 DWT 分解与频域特征db8 小波做 8 层分解采样率 500Hz 时第 8 层近似系数对应 0–1Hz细节系数逐层对应 1–2、2–4、4–8、8–16、16–32、32–64Hz。要拿到 delta(1–3)、theta(4–7)、alpha(8–13)、beta(14–30)、gamma(31–60) 这五段需要把相邻层的细节系数按频带重组而不是简单取某一层。import pywt import numpy as np def band_features(segment, fs500): # 8 层 db8 分解 coeffs pywt.wavedec(segment, db8, level8) feats [] # 按频带重组delta/theta/alpha/beta/gamma bands { delta: (1, 3), theta: (4, 7), alpha: (8, 13), beta: (14, 30), gamma: (31, 60) } for name, (lo, hi) in bands.items(): # 用带通滤波后的信号算该频带能量与微分熵 from scipy.signal import butter, filtfilt b, a butter(4, [lo, hi], btypeband, fsfs) band_sig filtfilt(b, a, segment) energy np.sum(band_sig ** 2) # 微分熵高斯假设下 DE 0.5*log(2*pi*e*var) de 0.5 * np.log(2 * np.pi * np.e * np.var(band_sig) 1e-8) feats.extend([energy, de]) return np.array(feats) # 5 频带 x 2 特征 10 维这里用带通滤波重组频带而不是直接取小波系数是因为 db8 的频带边界和标准 EEG 频段不完全重合直接取系数会让 alpha 和 beta 的边界模糊。1e-8是防止方差为零时 log 发散这个后悔药必须加否则遇到平坦段直接出 inf。微分熵按高斯分布公式算是 EEG 情绪检测里的常用近似比直接算香农熵稳定。3.2 时域统计量与 Hjorth 参数时域部分取均值、RMS、标准差、一阶差分、归一化一阶差分、二阶差分、归一化二阶差分、峰度、偏度、方差再加 Hjorth 的 mobility 和 complexity。Hjorth 三个参数里 activity 就是方差所以实际新增的是 mobility 和 complexity 两个。from scipy.stats import kurtosis, skew def time_features(x): d1 np.diff(x) d2 np.diff(x, n2) feats [ np.mean(x), np.sqrt(np.mean(x**2)), np.std(x), np.mean(np.abs(d1)), np.mean(np.abs(d1)) / (np.std(x) 1e-8), np.mean(np.abs(d2)), np.mean(np.abs(d2)) / (np.std(x) 1e-8), kurtosis(x), skew(x), np.var(x) ] # Hjorth mobility / complexity mob np.std(d1) / (np.std(x) 1e-8) comp (np.std(d2) / (np.std(d1) 1e-8)) / (mob 1e-8) feats.extend([mob, comp]) return np.array(feats) # 12 维归一化一阶差分除以标准差是为了消除不同被试信号幅度差异带来的量纲漂移——这是跨被试分类能不能稳住的关键。分母的1e-8同样是防零除。峰度和偏度用scipy.stats直接算注意kurtosis默认是 Fisher 定义正态分布为 0如果和别的库对比结果对不上先查这个。3.3 通道级 SVM 与通道融合策略原文的核心设计是「每个通道一个 SVM」DEAP 32 通道就是 32 个分类器每个分类器输入该通道的 34 维特征输出四类情绪之一。然后做通道融合把 32 个通道的预测结果合成最终情绪状态。融合方式原文没细说通常的做法是多数投票或者按通道历史准确率加权投票。from sklearn.svm import SVC from sklearn.preprocessing import StandardScaler from collections import Counter def train_channel_svms(X_train, y_train): # X_train: [n_samples, n_channels, n_features] models [] for ch in range(X_train.shape[1]): scaler StandardScaler() Xc scaler.fit_transform(X_train[:, ch, :]) clf SVC(kernelrbf, C1.0, gammascale) clf.fit(Xc, y_train) models.append((scaler, clf)) return models def predict_fusion(models, X_test): votes [] for ch, (scaler, clf) in enumerate(models): pred clf.predict(scaler.transform(X_test[:, ch, :])) votes.append(pred) votes np.array(votes) # [n_channels, n_samples] # 多数投票 final [Counter(votes[:, i]).most_common(1)[0][0] for i in range(votes.shape[1])] return np.array(final)SVC(kernelrbf, C1.0, gammascale)是基线配置gammascale会按特征数自动缩放比手写固定值稳。每个通道单独StandardScaler很重要——不同通道的绝对幅度差异大不归一化的话 RBF 核的距离度量会被大幅值通道主导。多数投票用Counter实现平票时most_common返回先出现的类别如果要更严谨可以改成按通道验证集准确率加权。注意训练集和测试集必须按被试划分不能按样本随机划分。DEAP 用 22 人训练、10 人测试SEED-IV 用 32 人训练、13 人测试。按样本随机划分会让同一被试的数据同时出现在训练和测试里准确率虚高十几个点答辩时一问就露馅。4. 实验配置与结果复现四类情绪怎么定义和评估四类情绪按二维 valence-arousal 模型划分HAHV高唤醒高效价、HALV高唤醒低效价、LALV低唤醒低效价、LAHV低唤醒高效价。DEAP 的标签来自被试自评SEED-IV 的标签来自视频刺激的预设情绪类别两个库的标签体系不同所以方案里是分别训练两个独立模型不混训。4.1 训练/测试划分与特征矩阵形状DEAP 训练集特征矩阵是 880×3422 名被试 × 40 个事件 880 个样本每个样本 34 维。SEED-IV 训练集是 742×3432 名被试 × 24 个事件 ≈ 768去掉部分无效事件后约 742。测试集分别是 10 人 × 40 400 和 13 人 × 24 ≈ 312。这个形状对不上是正常的因为两个库事件数不同关键是每个通道的分类器输入维度一致。配置项DEAPSEED-IV通道数3232从 64 裁剪采样率500Hz降采样至 500Hz训练被试2232测试被试1013每被试事件数4024特征维度3434分类器数量32324.2 分类结果与解读原文报告的四类准确率DEAP 为 74%、86%、72%、84%SEED-IV 为 79%、76%、77%、74%。DEAP 的 HALV 类到 86%明显高于其他类通常是因为该类样本在特征空间里更可分SEED-IV 四类比较均衡在 74–79% 之间说明跨 session 的分布漂移被平均掉了。整体落在 72–86% 区间和文献综述里 74–90% 的范围一致属于合理水平。from sklearn.metrics import classification_report, confusion_matrix def evaluate(models, X_test, y_test): y_pred predict_fusion(models, X_test) print(classification_report(y_test, y_pred, target_names[HAHV, HALV, LALV, LAHV])) print(confusion_matrix(y_test, y_pred)) return y_pred跑完classification_report先看每类的 precision 和 recall 是否均衡。如果某一类 recall 特别低多半是训练集里该类样本太少或者通道融合的投票被多数类带偏。confusion_matrix用来定位混淆对——比如 HALV 和 LAHV 互相混淆多说明 valence 维度的特征区分度不够需要回头加强频域特征。提示复现时如果准确率比原文低 5 个点以上先查三件事——陷波频率是不是 50Hz、训练测试有没有按被试划分、每个通道有没有单独标准化。这三处是最常见的翻车点。5. 避坑与排查这套流程里最容易出错的五个地方5.1 准确率虚高一换被试就崩现象是训练集和测试集随机划分时准确率能到 90% 以上按被试划分后掉到 70% 左右。原因是同一被试的 EEG 片段在统计上高度相关随机划分造成信息泄漏。解决办法是严格按被试 ID 划分训练集和测试集的被试集合不相交这一点在代码里用subject_id做 group split 就能保证。5.2 DWT 分解后频带对不上现象是提取出来的 alpha 频带能量异常大或异常小。原因通常是采样率没统一——SEED-IV 原始 1000Hz 直接做 8 层分解频带边界会整体偏移一倍。解决方法是先降采样到 500Hz 再做 DWT或者在分解前用pywt.scale2frequency核对每层对应的实际频率范围。5.3 通道融合后结果反而变差现象是单通道最高准确率有 80%融合后掉到 70%。原因是某些通道信噪比极低多数投票被噪声通道拖累。解决办法是给每个通道按验证集准确率设权重低于随机水平的通道直接剔除或者改用加权投票而不是等权投票。5.4 中值滤波把有效信号削掉现象是预处理后波形变得过于平滑高频成分丢失。原因是中值滤波核长设得太大或者作用到了通道维。解决方法是核长控制在 5–11 点之间kernel_size明确写成(1, 1, k)只沿时间轴滤波。5.5 标签映射错位现象是混淆矩阵里类别完全对不上准确率接近随机。原因是 DEAP 的自评标签和 SEED-IV 的预设标签阈值不同valence/arousal 的高低分界点没统一。解决办法是在各自库内独立做二值化DEAP 用被试自评的中位数做阈值SEED-IV 用官方标签两个库的类别编号在代码里显式映射不共用一套 label encoder。6. 验收与答辩怎么证明这套方案真的跑通了验收这套方案核心不是看准确率数字好不好看而是看流程是否可复现、划分是否干净、结果是否可解释。答辩时评委最常问的三个问题是数据怎么切的、特征为什么这么选、准确率有没有水分。提前把这三件事的证据准备好比背十页 PPT 管用。具体做法是准备一张「复现检查表」每项都要有对应的代码位置和输出截图。第一项数据划分打印训练集和测试集的被试 ID 列表证明两者无交集。第二项预处理对同一段原始信号画出滤波前后的波形对比图标出 50Hz 陷波前后的频谱差异。第三项特征给出一个通道的 34 维特征向量样例说明每一维的来源。第四项分类给出四类的混淆矩阵和每类 precision/recall而不只是总体准确率。第五项融合对比单通道最优、等权投票、加权投票三种策略的准确率说明为什么选当前方案。验收项证据形式合格标准被试划分训练/测试被试 ID 列表无交集预处理滤波前后波形频谱图50Hz 峰明显下降特征提取单通道 34 维向量样例维度与表 1 一致分类结果混淆矩阵分类报告四类均有 recall通道融合三种策略对比表融合不低于单通道最优答辩陈述的顺序建议反过来讲先给最终混淆矩阵再倒推「为了得到这个结果我做了哪几步关键处理」最后讲遇到的坑和怎么解决的。评委对「踩坑—排查—修正」的过程比对一个漂亮数字更买账因为这证明你真的动手跑过而不是抄了个流程。我自己的习惯是每次交方案前强制走一遍「换一台机器从零跑」的流程——清空环境、重新装依赖、从头执行脚本任何一步报错都记下来补进文档。这个习惯救过我好几次因为本地能跑不代表交付能跑路径写死、随机种子没固定、依赖版本漂移都是答辩现场翻车的经典原因。从那以后我每次交付前都强制走一遍干净环境复现希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站