DEAPDataset的EEG脑电图数据(Emotion_Prediction)使用介绍【第一期】
DEAPDataset一个用于分析人类情感状态的多模态数据集。在 32 名参与者观看 40 段一分钟长的音乐视频片段时,记录了他们的脑电图(EEG)和外周生理信号。参与者对每个视频的唤醒度、效价、喜好 / 厌恶、支配度和熟悉度水平进行了评分。在 32 名参与者中,有 22 人的 frontal face 视频也被记录了下来。我们使用了一种新的刺激材料选择方法,该方法利用了从 last.fm 网站通过情感标签检索、视频高光检测和一个在线评估工具。
下载地址:https://www.eecs.qmul.ac.uk/mmv/datasets/deap/index.html
该数据集已公开提供,我们鼓励其他研究人员使用它来测试他们自己的情感状态估计方法。该数据集首次在以下论文中介绍:点击这里
数据集说明:原始数据与预处理版本介绍
1. 原始数据文件(Data_original.zip)
这些是原始记录数据,包含 32 个.bdf 文件(由 Actiview 软件生成的 BioSemi 数据格式),每个文件有 48 个记录通道,采样率为 512Hz。具体通道分布如下:
- 32 个 EEG 通道、12 个外周生理通道、3 个未使用通道和 1 个状态通道。
- .bdf 文件可通过多种软件工具读取,如 Matlab 的 EEGLAB 和 BIOSIG 工具包。
数据采集地点差异
数据在两个地点采集,导致格式存在细微差异:
- EEG 通道顺序不同:特温特(参与者 1-22)和日内瓦(参与者 23-32)的通道命名和排序不同,具体转换关系见下表:
通道编号 | 特温特通道名 | 日内瓦通道名 | 日内瓦→特温特索引 | 特温特→日内瓦索引 |
---|---|---|---|---|
1 | Fp1 | Fp1 | 1 | 1 |
2 | AF3 | AF3 | 2 | 2 |
3 | F7 | F3 | 4 | 4 |
4 | F3 | F7 | 3 | 3 |
... | ... | ... | ... | ... |
32 | Cz | O2 | 24 | 17 |
- GSR 测量单位不同:
- 特温特的 GSR 为皮肤电阻(单位:纳西门子,nS),日内瓦的 GSR 为皮肤电导(单位:欧姆,Ω)。
- 转换公式:
GSRGeneva = 10⁹ / GSRTwente
其他通道说明
通道编号 | 通道名 | 内容描述 |
---|---|---|
33-36 | EXG1-EXG4 | 眼电(hEOG:水平眼电;vEOG:垂直眼电) |
37-38 | EXG5-EXG6 | 颧肌肌电(zEMG) |
39-40 | EXG7-EXG8 | 斜方肌肌电(tEMG) |
41 | GSR1 | 皮肤电反应(左手中指和无名指) |
42-44 | Erg1-Erg2 | 未使用 |
45 | Resp | 呼吸带信号 |
46 | Plet | 体积描记图(左拇指) |
47 | Temp | 温度(左小指) |
48 | Status | 状态通道(包含刺激开始 / 结束标记) |
状态通道标记说明
状态码 | 事件持续时间 | 事件描述 |
---|---|---|
1(首次) | N/A | 实验开始(参与者按键启动) |
1(第二次) | 120000 ms | 基线记录开始 |
1(后续) | N/A | 评分界面开始 |
2 | 1000 ms | 视频同步界面(首次试验前、休息前后、最后一次试验后) |
3 | 5000 ms | 试验开始前的注视界面 |
4 | 60000 ms | 音乐视频播放开始 |
5 | 3000 ms | 视频播放后的注视界面 |
7 | N/A | 实验结束 |
2. 预处理数据文件(Data_preprocessed_matlab.zip 和 Data_preprocessed_python.zip)
这些文件包含降采样(至 128Hz)、预处理和分段后的数据,格式为 Matlab(.mat)或 Python(pickled numpy),适合快速测试分类 / 回归算法。每个压缩包包含 32 个文件(每位参与者一个)。
标签含义解析
一、EEG 电极位置标签(前 14 个)
这些标签代表头皮电极的位置,遵循国际 10-20 电极定位系统,用于标注 EEG 信号的采集位置:
标签 | 电极位置说明 | 脑区关联 |
---|---|---|
AF3/AF4 | 前额叶前部(靠近前额) | 涉及情绪调节、决策 |
F3/F4 | 前额叶(左右半球) | 与认知、情绪表达相关 |
F7/F8 | 前颞叶(左右侧) | 参与听觉处理、记忆 |
FC5/FC6 | 中央前回(额叶与中央区交界) | 运动皮层与认知整合 |
O1/O2 | 枕叶(脑后部) | 视觉处理中枢 |
P7/P8 | 顶叶(左右侧) | 感觉整合、空间认知 |
T7/T8 | 颞叶(左右侧) | 听觉处理、语言理解 |
二、情感维度标签(后 2 个)
valence
和arousal
是情感心理学中的核心维度,用于量化情感状态:
标签 | 含义 | 评分范围 | 示例场景 |
---|---|---|---|
valence | 效价(情感极性) | 1-9 分(1 = 极度负面,9 = 极度正面) | 愉悦度、满意度 |
arousal | 唤醒度 | 1-9 分(1 = 极度平静,9 = 极度兴奋) | 兴奋程度、紧张感 |
三、应用场景
这些标签常见于DEAP 数据集或类似的 EEG 情感识别研究中,例如:
- 数据格式:每行数据对应一段 EEG 信号(如 1 秒),前 14 列是各电极的电压值,后 2 列是情感评分
- 研究目标:通过分析不同脑区的 EEG 信号,预测用户的情感效价和唤醒度
- 典型关联:
- 前额叶(F3/F4)的 α 波功率可能与效价相关
- 颞叶(T7/T8)的 β 波活动可能与唤醒度相关
# 包含CSV文件的目录directory = './Data/'# 初始化列表,用于存储EEG通道和标签all_eeg_channels = []all_labels = []# 遍历目录中的每个文件for filename in os.listdir(directory): if filename.endswith(".csv"): file_path = os.path.join(directory, filename) print(file_path) # 读取CSV文件 data = pd.read_csv(file_path) # 选择EEG通道列 eeg_channels = data[['AF3', 'AF4', 'F3', 'F4', 'F7', 'F8', 'FC5', 'FC6', 'O1', 'O2', 'P7', 'P8', 'T7', 'T8']][:-2] # 选择情绪效价和唤醒度列 labels = data[['valence', 'arousal']].iloc[0] # 将EEG通道和标签转换为数组并存储 all_eeg_channels.append(eeg_channels.values) all_labels.append(labels.values)# 将列表转换为数组all_eeg_channels_array = np.array(all_eeg_channels)all_labels_array = np.array(all_labels)# 打印数组的形状(数据维度的大小)print("All EEG Channels Array Shape:", all_eeg_channels_array.shape)print("All Labels Array Shape:", all_labels_array.shape)
def map_labels(valence, arousal): # 将情绪效价和唤醒度映射为四个类别 if valence <= 2.5and arousal <= 2.5: return0# 低情绪效价,低唤醒度 elif valence <= 2.5and arousal > 2.5: return1# 低情绪效价,高唤醒度 elif valence > 2.5and arousal <= 2.5: return2# 高情绪效价,低唤醒度 else: return3# 高情绪效价,高唤醒度# 示例用法:# 对所有标签进行映射,将情绪效价和唤醒度转换为类别标签labels_mapped = np.array([map_labels(valence, arousal) for valence, arousal in all_labels_array])# 打印映射后的标签数组labels_mapped
array([0, 2, 1, 3, 0, 3, 1, 3, 0, 3, 1, 3, 0, 3, 1, 3, 0, 3, 1, 3, 0, 3, 1, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 2, 1, 2, 3, 1, 1, 3, 2, 2, 0, 3, 2, 3, 3, 3, 2, 0, 0, 2, 0, 3, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 2, 3, 1, 3, 2, 0, 1, 2, 0, 2, 1, 3, 0, 3, 1, 3, 0, 2, 1, 3, 0, 0, 0, 3, 0, 3, 1, 3, 0, 2, 1, 3])
检查形状和数据类型:检查阵列的形状和数据类型。
汇总统计:计算脑电通道的均值、中位数、最小值、最大值、标准差等基本汇总统计。
可视化:绘制每个EEG通道的直方图或箱形图,以了解其分布。
相关性分析:计算EEG通道之间的相关系数,并使用热图将其可视化。
标签分析:绘制价和觉醒标签的直方图或箱形图,以了解其分布。
标签相关性:计算价和觉醒标签之间的相关性。
特征工程:探索潜在的特征工程技术,如傅里叶变换、小波变换或其他信号处理方法。
异常检测:检测和处理异常值,如果存在于数据中。
channel_names = ['AF3', 'AF4', 'F3', 'F4', 'F7', 'F8', 'FC5', 'FC6', 'O1', 'O2', 'P7', 'P8', 'T7', 'T8']# 3. 可视化# 设置图形的大小plt.figure(figsize=(12, 8))# 遍历所有EEG通道for i in range(all_eeg_channels_array.shape[2]): # 创建子图,4行4列,第i+1个位置 plt.subplot(4, 4, i+1) # 绘制第i个通道的直方图 # 使用flatten()将二维数组展平为一维数组,bins=50表示直方图的柱数 plt.hist(all_eeg_channels_array[:,:,i].flatten(), bins=50, color='skyblue', alpha=0.7) # 设置子图的标题,显示通道名称 plt.title(f"{channel_names[i]} Channel Histogram") # 设置x轴标签 plt.xlabel("Value") # 设置y轴标签.分别设置x轴和y轴的标签,表示值和频率。 plt.ylabel("Frequency")# 调整子图之间的布局,使其紧凑plt.tight_layout()# 显示图形plt.show()
# 降低样本大小以进行相关性分析,对单个样本的EEG通道数据进行相关性分析,并将相关性矩阵以热力图的形式可视化sample_size = 1# 现在样本大小为1sample_data = all_eeg_channels_array[0] # 取第一个样本# 计算样本数据的相关性矩阵corr_matrix = np.corrcoef(sample_data.T)# 绘制相关性矩阵plt.figure(figsize=(10, 8))sns.heatmap(corr_matrix, cmap='coolwarm', annot=True, fmt=".2f", xticklabels=['AF3', 'AF4', 'F3', 'F4', 'F7', 'F8', 'FC5', 'FC6', 'O1', 'O2', 'P7', 'P8', 'T7', 'T8'], yticklabels=['AF3', 'AF4', 'F3', 'F4', 'F7', 'F8', 'FC5', 'FC6', 'O1', 'O2', 'P7', 'P8', 'T7', 'T8'])plt.title("Correlation Matrix of EEG Channels (Single Sample)")plt.xlabel("EEG Channels")plt.ylabel("EEG Channels")plt.show()
# 计算所有样本的相关性矩阵,计算所有样本的EEG通道之间的相关性矩阵,然后求这些相关性矩阵的平均值,并将平均相关性矩阵以热力图的形式可视化。cor_matrices = np.array([np.corrcoef(sample.T) for sample in all_eeg_channels_array])# 沿着一个新的维度堆叠相关性矩阵stacked_cor_matrices = np.stack(cor_matrices, axis=2)# 沿着新的维度取平均值,得到平均相关性矩阵average_cor_matrix = np.mean(stacked_cor_matrices, axis=2)# 绘制平均相关性矩阵plt.figure(figsize=(10, 8))sns.heatmap(average_cor_matrix, cmap='coolwarm', annot=True, fmt=".2f", xticklabels=['AF3', 'AF4', 'F3', 'F4', 'F7', 'F8', 'FC5', 'FC6', 'O1', 'O2', 'P7', 'P8', 'T7', 'T8'], yticklabels=['AF3', 'AF4', 'F3', 'F4', 'F7', 'F8', 'FC5', 'FC6', 'O1', 'O2', 'P7', 'P8', 'T7', 'T8'])plt.title("Average Correlation Matrix of EEG Channels")plt.xlabel("EEG Channels")plt.ylabel("EEG Channels")plt.show()
# 5. 标签分析:对情绪效价(valence)和唤醒度(arousal)标签进行可视化分析,具体来说是绘制它们的直方图。# 设置图形的大小plt.figure(figsize=(10, 4))# 绘制情绪效价的直方图plt.subplot(1, 2, 1) # 创建子图,1行2列,第1个位置plt.hist(all_labels_array[:,0], bins=20, color='skyblue', alpha=0.7) # 绘制直方图plt.title("Valence Histogram") # 设置子图的标题plt.xlabel("Valence") # 设置x轴标签plt.ylabel("Frequency") # 设置y轴标签# 绘制唤醒度的直方图plt.subplot(1, 2, 2) # 创建子图,1行2列,第2个位置plt.hist(all_labels_array[:,1], bins=20, color='salmon', alpha=0.7) # 绘制直方图plt.title("Arousal Histogram") # 设置子图的标题plt.xlabel("Arousal") # 设置x轴标签plt.ylabel("Frequency") # 设置y轴标签# 调整子图之间的布局,使其紧凑plt.tight_layout()# 显示图形plt.show()
# 6. 标签相关性# 计算情绪效价和唤醒度标签之间的相关性矩阵label_corr_matrix = np.corrcoef(all_labels_array[:,0], all_labels_array[:,1])# 绘制热力图plt.figure(figsize=(8, 6))sns.heatmap(label_corr_matrix, cmap='coolwarm', annot=True, fmt=".2f")plt.title("Correlation between Valence and Arousal Labels")plt.xlabel("Valence")plt.ylabel("Arousal")plt.show()
# 3. 可视化:数据分布;对每个EEG通道的数据分布进行可视化,具体来说是绘制每个通道的直方图。# 设置图形的大小plt.figure(figsize=(12, 8))# 遍历所有EEG通道for i in range(all_eeg_channels_array.shape[2]): # 创建子图,4行4列,第i+1个位置 plt.subplot(4, 4, i+1) # 绘制第i个通道的直方图 # 使用flatten()将二维数组展平为一维数组,bins=50表示直方图的柱数 plt.hist(all_eeg_channels_array[:, :, i].flatten(), bins=50, color='skyblue', alpha=0.7) # 设置子图的标题,显示通道名称 plt.title(f"{channel_names[i]} Channel Distribution") # 设置x轴标签 plt.xlabel("Value") # 设置y轴标签 plt.ylabel("Frequency")# 调整子图之间的布局,使其紧凑plt.tight_layout()# 显示图形plt.show()
# 绘制小提琴图plt.figure(figsize=(12, 8)) # 设置图形的大小为12×8英寸# 使用Seaborn的violinplot函数绘制小提琴图sns.violinplot(data=all_eeg_channels_array.reshape(-1, all_eeg_channels_array.shape[-1]), palette='muted', inner='point')plt.title('Distribution of EEG Data Across Channels') # 设置图形的标题plt.xlabel('Channels') # 设置x轴标签plt.ylabel('EEG Data') # 设置y轴标签# 设置x轴刻度的位置和标签,显示通道名称plt.xticks(ticks=np.arange(all_eeg_channels_array.shape[-1]), labels=channel_names)plt.show() # 显示图形
from scipy.signal import butter, filtfiltchannel_names = ['AF3', 'AF4', 'F3', 'F4', 'F7', 'F8', 'FC5', 'FC6', 'O1', 'O2', 'P7', 'P8', 'T7', 'T8']# 定义滤波器参数lowcut = 0.5# 带通滤波器的下截止频率(单位:赫兹)highcut = 45# 带通滤波器的上截止频率(单位:赫兹)fs = 128 # 采样频率(单位:赫兹)order = 4 # 滤波器的阶数# 定义一个函数,用于创建Butterworth带通滤波器的系数def butter_bandpass(lowcut, highcut, fs, order=4): nyquist = 0.5 * fs # 计算奈奎斯特频率 low = lowcut / nyquist # 将下截止频率归一化 high = highcut / nyquist # 将上截止频率归一化 b, a = butter(order, [low, high], btype='band') # 创建滤波器系数 return b, a# 定义一个函数,用于应用Butterworth带通滤波器def butter_bandpass_filter(data, lowcut, highcut, fs, order=4): b, a = butter_bandpass(lowcut, highcut, fs, order=order) # 获取滤波器系数 filtered_data = filtfilt(b, a, data) # 对数据进行滤波 return filtered_data# 对每个EEG通道应用滤波器filtered_data = np.zeros_like(all_eeg_channels_array) # 创建一个与原始数据形状相同的数组,用于存储滤波后的数据for i in range(all_eeg_channels_array.shape[2]): # 遍历每个通道 filtered_data[:,:,i] = butter_bandpass_filter(all_eeg_channels_array[:,:,i], lowcut, highcut, fs, order) # 对每个通道的数据进行滤波# 可视化滤波后的数据plt.figure(figsize=(12, 8)) # 设置图形的大小for i in range(filtered_data.shape[2]): # 遍历每个通道 plt.subplot(4, 4, i+1) # 创建子图 plt.plot(filtered_data[:,:,i].flatten(), color='skyblue') # 绘制滤波后的数据 plt.title(f"{channel_names[i]} Channel (Filtered)") # 设置子图的标题 plt.xlabel("Time") # 设置x轴标签 plt.ylabel("Amplitude") # 设置y轴标签plt.tight_layout() # 调整子图之间的布局plt.show() # 显示图形
from scipy.signal import butter, filtfiltimport numpy as npimport matplotlib.pyplot as plt# 定义滤波器参数lowcut = 0.5# 下截止频率(单位:赫兹)highcut = 45# 上截止频率(单位:赫兹)fs = 128 # 采样频率(单位:赫兹)order = 4 # 滤波器阶数# 定义一个函数,用于创建Butterworth带通滤波器的系数def butter_bandpass(lowcut, highcut, fs, order=4): nyquist = 0.5 * fs # 计算奈奎斯特频率 low = lowcut / nyquist # 将下截止频率归一化 high = highcut / nyquist # 将上截止频率归一化 b, a = butter(order, [low, high], btype='band') # 创建滤波器系数 return b, a# 定义一个函数,用于对3D数组应用Butterworth带通滤波器def butter_bandpass_filter_3d(data, lowcut, highcut, fs, order=4): filtered_data = np.zeros_like(data) # 创建一个与输入数据形状相同的数组,用于存储滤波后的数据 for i in range(data.shape[0]): # 遍历第一个维度(样本) for j in range(data.shape[1]): # 遍历第二个维度(通道) b, a = butter_bandpass(lowcut, highcut, fs, order=order) # 获取滤波器系数 filtered_data[i, j, :, :] = filtfilt(b, a, data[i, j, :, :]) # 对每个通道的数据进行滤波 return filtered_data# 对EEG通道数据应用滤波器filtered_data = butter_bandpass_filter_3d(reshaped_channels_array, lowcut, highcut, fs, order)# 可视化每个通道的滤波后数据plt.figure(figsize=(16, 20)) # 设置更大的图形尺寸for i in range(filtered_data.shape[1]): # 遍历通道 for j in range(filtered_data.shape[2]): # 遍历子段 plt.subplot(14, 5, i*5 + j + 1) # 创建子图 plt.plot(filtered_data[0, i, j, :].flatten(), color='skyblue') # 绘制滤波后的数据 plt.title(f"{channel_names[i]} Channel (Filtered)", fontsize=8) # 设置子图的标题 plt.xlabel("Time", fontsize=8) # 设置x轴标签 plt.ylabel("Amplitude", fontsize=8) # 设置y轴标签plt.tight_layout() # 调整子图之间的布局plt.show() # 显示图形
代码主要实现了对脑电(EEG)数据的处理、分析和特征提取,用于情绪识别相关的研究或应用。以下是对代码功能的详细介绍:
一、数据读取与初步处理
-
导入必要的库
使用os
处理文件路径,pandas
和numpy
处理数据,matplotlib
和seaborn
进行数据可视化。 -
读取 CSV 格式的 EEG 数据
- 遍历指定目录下的所有 CSV 文件(如
S01G1AllChannels.csv
等),这些文件可能包含不同受试者(S01
到S25
)和不同组(G1
到G4
)的 EEG 数据。 - 从每个文件中提取 14 个 EEG 通道的数据(如
AF3
、F3
、O1
等)和情绪标签(效价valence
和唤醒度arousal
)。 - 最终将数据存储为 NumPy 数组,形状为
(100, 38250, 14)
,其中:100
表示 100 个样本(文件),38250
表示每个样本的时间点数量,14
表示 14 个 EEG 通道。
- 遍历指定目录下的所有 CSV 文件(如
二、数据探索与可视化
-
数据基本信息检查
查看数据形状、数据类型(如float64
),确保数据读取正确。 -
描述性统计分析
计算每个 EEG 通道的均值、中位数、最小值、最大值和标准差,了解数据的基本分布特征。 -
数据可视化
- 直方图:展示每个 EEG 通道的数据分布,观察数据的集中趋势和离散程度。
- 箱线图:检测数据中的异常值,了解数据的四分位数分布。
- 小提琴图:同时展示数据的分布密度、中位数和四分位数,比箱线图更直观。
- 相关性热图:计算单个样本或所有样本的 EEG 通道间相关性,通过热图可视化通道间的关联性(颜色越暖表示正相关性越强,越冷表示负相关性越强)。
-
情绪标签分析
- 绘制效价(
valence
)和唤醒度(arousal
)的直方图,了解情绪标签的分布。 - 计算两者的相关性,分析情绪维度之间的关系。
- 绘制效价(
三、数据重塑与预处理
-
数据分段(Segmentation)
将长序列的 EEG 数据分割为多个段(segments
)和子段(subsegments
),以便提取更细粒度的特征。例如,将 38250 个时间点分割为 6 个段,每个段再分为 5 个子段,最终形状为(100, 6, 14, 5, 1275)
。 -
带通滤波
使用 Butterworth 滤波器对 EEG 数据进行滤波,去除低频(<0.5Hz)和高频(>45Hz)噪声,保留脑电信号的有效频段(0.5-45Hz)。滤波后的数据更适合后续特征提取。
四、特征提取(微分熵,Differential Entropy)
-
微分熵计算
微分熵是衡量信号不确定性的指标,常用于 EEG 信号的频域特征提取。代码通过以下步骤计算:- 对每个 EEG 通道的子段数据进行直方图统计,估计概率密度函数。
- 基于概率密度计算微分熵(以 2 为底),反映信号的频域复杂度。
- 最终得到的特征形状为
(600, 14, 1275, 5)
,其中:600
表示 600 个样本(分段后),14
表示 14 个通道,1275
表示每个子段的时间点,5
表示 5 个子段。
-
数据洗牌(Shuffle)
使用sklearn.utils.shuffle
对特征和标签进行随机洗牌,避免模型训练时的顺序偏差,确保数据随机性。
五、情绪标签映射
- 情绪分类
将连续的效价和唤醒度标签映射为 4 类离散情绪:0
:低效价 + 低唤醒度(平静)1
:低效价 + 高唤醒度(焦虑)2
:高效价 + 低唤醒度(愉悦)3
:高效价 + 高唤醒度(兴奋)
映射后的标签用于后续的分类任务。
六、整体流程总结
- 数据获取:读取多通道 EEG 数据和情绪标签。
- 探索性分析:通过统计和可视化了解数据分布与相关性。
- 预处理:分段和滤波,提升数据质量。
- 特征提取:计算微分熵,将时域信号转换为频域特征。
- 数据准备:洗牌和标签映射,为机器学习模型训练做准备。
该流程常用于脑电情绪识别研究,通过特征提取和分类可实现基于 EEG 信号的情绪状态预测。