用Python玩转DEAP情绪数据集从下载到脑电信号可视化的保姆级教程当你第一次听说DEAP数据集时可能会被它丰富的多模态生理信号和复杂的情绪维度标签所吸引但随即又被.mat/.dat文件格式、32导EEG信号和8064个采样点这些专业术语吓退。别担心这篇教程将手把手带你从零开始用Python一步步揭开这个经典情绪数据集的神秘面纱。1. 环境准备与数据获取在开始之前我们需要搭建一个适合处理生理信号的工作环境。推荐使用Anaconda创建独立的Python环境conda create -n deap_analysis python3.8 conda activate deap_analysis pip install mne numpy scipy matplotlib pandas scikit-learnDEAP数据集可以从官方网址免费下载。数据集包含两个版本原始数据512Hz采样率预处理数据降采样至128Hz已去除眼电等噪声对于大多数应用场景我们建议直接下载预处理好的Python版本(data_preprocessed_python)它包含32个.dat文件每个对应一位被试者的数据。提示下载可能需要填写简单的使用协议文件总大小约2GB确保有足够的存储空间。2. 理解数据结构与情绪维度DEAP数据集的核心结构可以用一个四维张量表示40(试次) × 40(通道) × 8064(采样点)。让我们用代码实际查看一个被试文件import numpy as np from scipy.io import loadmat # 加载单个被试数据 subject_data loadmat(data_preprocessed_python/s01.dat) print(subject_data.keys()) # 查看数据结构你会看到两个关键数组data: 生理信号数据 (40×40×8064)labels: 情绪维度评分 (40×4)情绪维度包括效价(Valence): 愉悦程度 (1负面, 9正面)唤醒度(Arousal): 兴奋程度 (1平静, 9兴奋)优势度(Dominance): 控制感 (1受控, 9主导)喜爱度(Liking): 主观偏好 (1不喜欢, 9很喜欢)3. 使用MNE-Python处理脑电信号MNE-Python是处理脑电数据的利器。我们先创建一个标准的电极位置信息import mne # 定义10-20系统的32导电极位置 montage mne.channels.make_standard_montage(standard_1005) print(montage.ch_names) # 查看电极名称接着我们将原始数据转换为MNE的Raw对象# 提取第一个试次的EEG数据前32通道 eeg_data subject_data[data][0, :32, :] # 32通道×8064采样点 # 创建Info对象 info mne.create_info( ch_namesmontage.ch_names[:32], sfreq128, # 采样率128Hz ch_typeseeg ) # 创建Raw对象 raw mne.io.RawArray(eeg_data, info) raw.set_montage(montage) # 绘制电极位置 raw.plot_sensors(show_namesTrue)4. 脑电信号可视化与分析现在让我们可视化一个试次的脑电信号。选择感兴趣的电极和时间段import matplotlib.pyplot as plt # 设置绘图样式 plt.style.use(seaborn) # 绘制FP1电极在0-10秒的信号 plt.figure(figsize(12, 4)) plt.plot(raw.times, raw.get_data(picks[Fp1])[0], linewidth1) plt.xlim(0, 10) # 前10秒 plt.title(FP1 Electrode Signal (0-10s), fontsize14) plt.xlabel(Time (s)) plt.ylabel(Amplitude (μV)) plt.grid(True) plt.show()对于更专业的分析我们可以计算并绘制功率谱密度(PSD)# 计算功率谱密度 psds, freqs mne.time_frequency.psd_array_multitaper( raw.get_data(), sfreq128, fmin1, fmax50 ) # 绘制平均PSD plt.figure(figsize(10, 5)) plt.plot(freqs, psds.mean(axis0).T, linewidth1) plt.title(Power Spectral Density, fontsize14) plt.xlabel(Frequency (Hz)) plt.ylabel(Power (dB)) plt.xlim(1, 50) plt.grid(True) plt.show()5. 情绪维度与生理信号的关联分析理解情绪标签如何与生理信号关联是研究的核心。我们先看看情绪维度的分布import pandas as pd # 提取所有试次的情绪标签 labels subject_data[labels] df_labels pd.DataFrame(labels, columns[valence, arousal, dominance, liking]) # 绘制情绪维度分布 fig, axes plt.subplots(2, 2, figsize(12, 8)) for i, col in enumerate(df_labels.columns): ax axes[i//2, i%2] df_labels[col].hist(bins9, axax) ax.set_title(f{col.capitalize()} Distribution) ax.set_xlabel(Rating (1-9)) ax.set_ylabel(Count) plt.tight_layout() plt.show()接着我们可以探索高唤醒与低唤醒试次的脑电差异# 分离高/低唤醒试次以中位数5为界 high_arousal subject_data[data][labels[:, 1] 5] low_arousal subject_data[data][labels[:, 1] 5] # 计算各频段平均功率差异 def compute_band_power(data, band): psds np.abs(np.fft.fft(data, axis-1))**2 freqs np.fft.fftfreq(data.shape[-1], 1/128) mask (freqs band[0]) (freqs band[1]) return psds[..., mask].mean(axis-1) bands { Delta: (1, 4), Theta: (4, 8), Alpha: (8, 13), Beta: (13, 30), Gamma: (30, 50) } results {} for name, band in bands.items(): results[f{name}_high] compute_band_power(high_arousal[:, :32, :], band).mean(axis(0,1)) results[f{name}_low] compute_band_power(low_arousal[:, :32, :], band).mean(axis(0,1)) # 绘制频段功率对比 df_bands pd.DataFrame(results) df_bands.plot(kindbar, figsize(12, 6), rot0) plt.title(Band Power Comparison: High vs Low Arousal) plt.ylabel(Power (μV²)) plt.grid(True) plt.show()6. 进阶技巧与实用建议在实际分析中有几个关键点需要注意数据标准化不同被试间的信号幅度可能有差异建议进行z-score标准化伪迹去除虽然数据已经过预处理但仍可能残留眼电或肌电伪迹时频分析情绪变化常体现在特定频段的功率变化上以下是一个实用的时频分析代码示例# 创建Epochs对象 events np.array([[i, 0, 0] for i in range(40)]) # 40个试次 epochs mne.EpochsArray( subject_data[data][:, :32, :], info, eventsevents, tmin-3 # 包含3秒基线 ) # 计算时频表示 freqs np.logspace(*np.log10([4, 30]), num20) n_cycles freqs / 2 # 不同频率使用不同周期数 power mne.time_frequency.tfr_multitaper( epochs, freqsfreqs, n_cyclesn_cycles, return_itcFalse, averageTrue ) # 绘制时频图 power.plot([0], baseline(-3, 0), modelogratio, titleTime-Frequency (Fp1))在处理DEAP数据集时我经常发现以下几个小技巧特别有用使用mne.viz.plot_topomap可以快速查看不同脑区的活动分布对于情绪分类任务建议先进行特征工程如各频段功率、不对称性等考虑使用滑动窗口分析来捕捉情绪的动态变化