当前位置: 首页 > news >正文

用Python玩转WESAD和DREAMER:手把手教你读取ECG情绪识别数据集(附完整代码)

用Python玩转WESAD和DREAMER:手把手教你读取ECG情绪识别数据集(附完整代码)

情绪识别技术正逐渐从实验室走向实际应用,而ECG(心电图)信号因其客观性和连续性成为研究热点。WESAD和DREAMER作为两个重要的多模态情绪识别数据集,为研究者提供了丰富的生理信号数据。本文将带你从零开始,掌握这两个数据集的Python处理技巧。

1. 环境准备与数据获取

在开始处理数据前,我们需要搭建合适的Python环境。推荐使用Anaconda创建独立环境:

conda create -n emotion_recognition python=3.8 conda activate emotion_recognition pip install numpy pandas matplotlib scipy seaborn

WESAD数据集可直接从官网下载,而DREAMER需要提交申请。下载后建议按以下结构组织文件:

情绪识别项目/ ├── data/ │ ├── WESAD/ │ │ ├── S1.pkl │ │ ├── S2.pkl │ │ └── ... │ └── DREAMER.mat ├── scripts/ │ └── data_processing.py └── outputs/ └── figures/

提示:处理生理信号数据时,保持文件路径的规范性非常重要,可以避免许多不必要的错误。

2. WESAD数据集深度解析

WESAD数据集包含15名受试者的多模态生理信号,采样频率为700Hz。其数据结构采用Python字典形式存储,主要包含三个关键部分:

  • subject: 受试者标识符(如S1, S2等)
  • signal: 原始生理信号数据(分为chest和wrist两组)
  • label: 情绪状态标签(0-7)

2.1 数据加载与探索

让我们创建一个专门处理WESAD数据的Python类:

import pickle import numpy as np import matplotlib.pyplot as plt class WESADLoader: def __init__(self, data_path, subject_id): self.data_path = data_path self.subject_id = subject_id self.data = self._load_data() def _load_data(self): with open(f"{self.data_path}/{self.subject_id}.pkl", 'rb') as f: return pickle.load(f, encoding='latin1') def get_chest_signals(self): return self.data['signal']['chest'] def get_labels(self): return self.data['label'] def plot_ecg_segment(self, start=0, end=5000): ecg = self.get_chest_signals()['ECG'][start:end] plt.figure(figsize=(15, 4)) plt.plot(ecg) plt.title(f"ECG Segment (Subject {self.subject_id})") plt.xlabel("Samples") plt.ylabel("Amplitude") plt.grid() plt.show()

使用示例:

loader = WESADLoader("data/WESAD", "S3") chest_data = loader.get_chest_signals() print(f"Available chest signals: {list(chest_data.keys())}") # 输出各信号长度 for signal, values in chest_data.items(): print(f"{signal}: {len(values)} samples") # 可视化ECG片段 loader.plot_ecg_segment(10000, 15000)

2.2 情绪片段提取与分析

WESAD数据集包含多种情绪状态,我们可以按标签提取特定情绪的数据:

def extract_emotion_segments(loader, emotion_code): labels = loader.get_labels() indices = np.where(labels == emotion_code)[0] chest_data = loader.get_chest_signals() segments = {} for signal in chest_data: segments[signal] = chest_data[signal][indices] return segments # 提取基线状态数据(label=1) baseline_data = extract_emotion_segments(loader, 1) # 提取压力状态数据(label=2) stress_data = extract_emotion_segments(loader, 2)

3. DREAMER数据集实战指南

DREAMER数据集记录了23名受试者在观看情绪诱发视频时的ECG和EEG信号,其数据结构更为复杂,采用MATLAB的.mat格式存储。

3.1 数据加载与结构解析

使用scipy.io加载.mat文件:

import scipy.io as sio def load_dreamer(data_path): data = sio.loadmat(data_path, simplify_cells=True) return data['DREAMER'] dreamer_data = load_dreamer('data/DREAMER.mat') print(f"数据集包含 {dreamer_data['noOfSubjects']} 名受试者") print(f"每个受试者有 {dreamer_data['noOfVideoSequences']} 个视频片段")

DREAMER数据结构关键字段:

字段描述数据类型
Data主体数据包含23个受试者数据的列表
ECG_SamplingRateECG采样率256 Hz
ScoreValence效价评分18×1数组
ScoreArousal唤醒评分18×1数组

3.2 ECG信号提取与处理

提取特定受试者的ECG数据:

def get_ecg_data(dreamer_data, subject_idx): subject_data = dreamer_data['Data'][subject_idx] return { 'baseline': subject_data['ECG']['baseline'], 'stimuli': subject_data['ECG']['stimuli'], 'valence': subject_data['ScoreValence'], 'arousal': subject_data['ScoreArousal'] } # 获取第一个受试者的ECG数据 subject_ecg = get_ecg_data(dreamer_data, 0) # 可视化第一个视频片段的ECG plt.figure(figsize=(15, 4)) plt.plot(subject_ecg['stimuli'][0]) plt.title("ECG during Emotion Induction (First Video)") plt.xlabel("Samples") plt.ylabel("Amplitude") plt.grid() plt.show()

4. 高级分析与可视化技巧

掌握了基础数据读取后,我们可以进行更深入的分析。

4.1 心率变异性(HRV)分析

HRV是情绪识别中的重要特征,我们可以从ECG信号中提取:

from scipy.signal import find_peaks def compute_hrv(ecg_signal, fs=700): # 检测R波峰值 peaks, _ = find_peaks(ecg_signal, height=np.mean(ecg_signal)*1.5, distance=fs*0.6) # 计算RR间期(毫秒) rr_intervals = np.diff(peaks) * (1000/fs) # 计算SDNN(HRV常用指标) sdnn = np.std(rr_intervals) return { 'peaks': peaks, 'rr_intervals': rr_intervals, 'sdnn': sdnn } # 计算基线状态的HRV baseline_ecg = loader.get_chest_signals()['ECG'] hrv_results = compute_hrv(baseline_ecg[:20000]) # 使用前20秒数据 plt.figure(figsize=(15, 4)) plt.plot(baseline_ecg[:20000]) plt.plot(hrv_results['peaks'], baseline_ecg[hrv_results['peaks']], 'rx') plt.title("R Peak Detection") plt.show() print(f"HRV (SDNN): {hrv_results['sdnn']:.2f} ms")

4.2 多受试者数据整合

对于需要同时分析多个受试者的情况,我们可以构建统一的数据结构:

def process_multiple_subjects(data_path, subject_ids): all_data = {} for subject in subject_ids: loader = WESADLoader(data_path, subject) signals = loader.get_chest_signals() labels = loader.get_labels() # 提取各情绪状态的平均ECG幅值 emotions = { 1: 'baseline', 2: 'stress', 3: 'amusement' } subject_results = {} for code, name in emotions.items(): segments = extract_emotion_segments(loader, code) subject_results[name] = np.mean(np.abs(segments['ECG'])) all_data[subject] = subject_results return pd.DataFrame(all_data).T # 处理前5名受试者 results_df = process_multiple_subjects("data/WESAD", [f"S{i}" for i in range(1, 6)]) print(results_df)

这将输出一个DataFrame,显示各受试者在不同情绪状态下的ECG平均幅值:

baselinestressamusement
S10.1520.1780.161
S20.1460.1850.158
............

5. 常见问题与调试技巧

在实际操作中,你可能会遇到以下问题:

  1. 数据加载错误

    • 确保文件路径正确
    • 检查Python版本与pickle协议兼容性
    • 对于.mat文件,尝试不同的simplify_cells参数
  2. 信号显示异常

    # 检查数据范围 print(f"ECG range: {np.min(ecg)} to {np.max(ecg)}") # 标准化显示 ecg_normalized = (ecg - np.mean(ecg)) / np.std(ecg)
  3. 内存不足处理

    • 对于大型.mat文件,考虑分块加载
    • 使用memory_map选项:
      data = sio.loadmat('large_file.mat', mat_dtype=True, matlab_compatible=False)
  4. 跨平台兼容性

    • 路径处理使用os.path.join
      import os file_path = os.path.join('data', 'WESAD', 'S1.pkl')

注意:生理信号数据通常包含高频噪声,在实际分析前应考虑适当的滤波处理。一个简单的带通滤波示例:

from scipy.signal import butter, filtfilt def bandpass_filter(data, lowcut=1.0, highcut=35.0, fs=700, order=4): nyq = 0.5 * fs low = lowcut / nyq high = highcut / nyq b, a = butter(order, [low, high], btype='band') return filtfilt(b, a, data) # 应用滤波器 filtered_ecg = bandpass_filter(chest_data['ECG'])
http://www.jsqmd.com/news/875794/

相关文章:

  • CNN-LSTM模型与数据降维在物联网边缘计算中的实践
  • 剖析有名的规划馆展厅策划设计施工专业公司,哪家比较靠谱? - mypinpai
  • 在CentOS7服务器上装Win10?手把手教你用Ventoy搞定双系统(附网卡驱动安装)
  • PCA-ANN-PWA框架:破解大规模非线性系统全局优化难题
  • 基于LLM的AutoM3L框架:实现多模态机器学习自动化流水线
  • 避坑指南:Ubuntu 23.04安装Mininet时遇到的Open vSwitch控制器冲突与解决
  • 大数据机器学习基准测试实战:TPCx-BB扩展与多库性能对比
  • 别再死记硬背公式了!用Python手撸LDA,从随机数据降维到分类实战
  • 告别Win11桌面图标乱跑或锁死:深入‘任务计划程序’与注册表,一劳永逸设置指南
  • 机器学习力场加速热力学积分:双路径计算离子真实电势
  • 因果中介分析:双机器学习与非参数估计框架解析
  • DFT计算揭示稀土掺杂与异质结协同提升光催化材料性能的微观机制
  • 别再只盯着深度学习!用OpenCV+Python实战传统分水岭算法,5分钟搞定细胞图像分割
  • 量子机器学习安全:NISQ时代数据投毒攻击QUID的威胁与防御
  • 基于SpringBoot的工业设备远程运维台账毕业设计
  • 机器学习势与势能面描述符:高通量筛选固态电解质的新范式
  • 基于情感计算与网络分析:在线健身社区性别化情感表达研究
  • OpenLS-DGF:开源逻辑综合数据集生成框架,赋能EDA机器学习研究
  • 【无人机控制】基于强化学习在无人机中调整PID参数附Matlab代码
  • 信息检索模型在社会科学文献结构化提取中的应用与评估
  • 基于KDTree的机器学习壁面函数:提升CFD复杂流动模拟精度与效率
  • 接口测试的本质是验证系统契约而非连通性
  • 机器学习赋能量子软件测试:基于词袋模型与树模型的不稳定测试检测实践
  • 射电天文数据处理:致密源扣除与系统误差量化实战指南
  • 基于Q-learning算法的机器人迷宫路径规划研究附Matlab代码
  • 从ODE到SDE:随机微分方程建模、时间反转与边界值问题求解
  • 从Python课设到CTF利器:JWT_GUI工具开发复盘与使用避坑全指南
  • 基于特征建模的机器学习算法自适应选择方法与实践
  • 基于柯西-施瓦茨不等式的数据融合边界推断:半参数高效方法
  • 机器学习模型虚假相关性识别与应对:四大评估框架与实战指南