2023/8/10 -  脑机接口学习内容一览:

        本文主要针对上海交通大学的SJTU(SEED)数据集进行检查和整合,旨在之后通过更加标准流程的实现分类。


数据集介绍

数据集背景

        SJTU 情感脑电数据集(SEED)是由BCMI实验室提供的EEG数据集的集合,该实验室由吕宝粮教授领导 。

数据集详情与情况展示

        图1 文件夹详情

        数据集文件夹情况如上图所示,Preprocessed_EEG中存放我们使用的数据集文件(.mat格式),不用python专门格式当然是因为我没有,而且对mat数据集的处理其实也没什么很大的区别。该子文件夹中的情况如下所示(除了数据集之外包括一个readme.txt以及一个label.mat文件):

 图2 Preprocessed_EEG文件夹情况

        这里读取第一个文件,查看数据集情况,读取代码和结果如下:

import mne
import scipy.io as sio


def read_one_file(path, file_name):
    # 读取单个.mat文件
    data = sio.loadmat(path + file_name)
    print(data.keys())
    print(data['djc_eeg1'].shape)
    print(data['djc_eeg1'])


read_one_file("Preprocessed_EEG/", "dujingcheng_20131027.mat")

        该代码读取到一个包含以下keys的字典:

 dict_keys(['__header__', '__version__', '__globals__', 'djc_eeg1', 'djc_eeg2', 'djc_eeg3', 'djc_eeg4', 'djc_eeg5', 'djc_eeg6', 'djc_eeg7', 'djc_eeg8', 'djc_eeg9', 'djc_eeg10', 'djc_eeg11', 'djc_eeg12', 'djc_eeg13', 'djc_eeg14', 'djc_eeg15'])

        选取前两个'djc_eeg'打印shape得到如下结果:

djc_eeg1.shape is  (62, 47001)
djc_eeg2.shape is  (62, 46601)

        由此得到数据集的基本情况,每个文件应该都包括15个试次 ,每个试次包括62个通道的数据以及一定数量的数据点。根据官方文件通道数据的排列顺序如下所示:

FP1 FPZ FP2 AF3 AF4 F7 F5 F3 F1 FZ F2 F4 F6 F8 FT7 FC5 FC3 FC1 FCZ FC2 FC4 FC6 FT8 T7 C5 C3 C1 CZ C2 C4 C6 T8 TP7 CP5 CP3 CP1 CPZ CP2 CP4 CP6 TP8 P7 P5 P3 P1 PZ P2 P4 P6 P8 PO7 PO5 PO3 POZ PO4 PO6 PO8 CB1 O1 OZ O2 CB2

        Preprocessed_EEG文件夹中还包含一个label.mat文件,上图未截出。因为前文读取的数据明显缺少标签。打印label.mat数据得到标签信息如下:

{'__header__': b'MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Sat Apr 18 22:14:56 2015', '__version__': '1.0', '__globals__': [], 'label': array([[ 1,  0, -1, -1,  0,  1, -1,  0,  1,  1,  0, -1,  0,  1, -1]], dtype=int16)}

         由此可得所有mat文件的数据标签都是统一的,每份文件的15个试次分别对应以下标签[ 1,  0, -1, -1,  0,  1, -1,  0,  1,  1,  0, -1,  0,  1, -1],其中-1表示消极,0表示中立,+ 1表示积极。

预处理

        该数据集已经经过了官方的预处理,理论上可以直接使用。

        官方采用的预处理操作如下:

        1.数据下采样到200hz;

        2.0-75hz的带通滤波;

        以上即为本文对该数据集详情的解释。


附录

        批量读取数据的代码如下,方便之后增加特征提取和分类部分。

        批量读取速度较慢,这里只读取了前三个文件,通过调整函数中的max_files_num参数可改变读取文件个数(上限为45个文件),默认只读取第一个文件。

import mne
import scipy.io as sio
import os

# 超参数
# 通道名顺序
ch_names = ['FP1', 'FPZ', 'FP2', 'AF3', 'AF4', 'F7', 'F5', 'F3', 'F1',
            'FZ', 'F2', 'F4', 'F6', 'F8', 'FT7', 'FC5', 'FC3', 'FC1',
            'FCZ', 'FC2', 'FC4', 'FC6', 'FT8', 'T7', 'C5', 'C3', 'C1',
            'CZ', 'C2', 'C4', 'C6', 'T8', 'TP7', 'CP5', 'CP3', 'CP1',
            'CPZ', 'CP2', 'CP4', 'CP6', 'TP8', 'P7', 'P5', 'P3', 'P1',
            'PZ', 'P2', 'P4', 'P6', 'P8', 'PO7', 'PO5', 'PO3', 'POZ',
            'PO4', 'PO6', 'PO8', 'CB1', 'O1', 'OZ', 'O2', 'CB2']
# 采样频率
sfreq = 200
# 每个.mat文件中的数据label
basic_label = [1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 0, 1, -1]


def read_one_file(file_path):
    """
    input:单个.mat文件路径
    output:raw格式数据
    """
    data = sio.loadmat(file_path)
    # 获取keys并转化为list,获取数据所在key
    keys = list(data.keys())[3:]
    # print(keys)
    # 获取数据
    raw_list = []
    for i in range(len(keys)):
        # 获取数据
        stamp = data[keys[i]]
        # print(stamp.shape)
        # 创建info
        info = mne.create_info(ch_names=ch_names, sfreq=sfreq, ch_types='eeg')
        # 创建raw,取第5秒开始的数据
        raw = mne.io.RawArray(stamp, info).crop(tmin=5)
        # 添加到raw_list
        raw_list.append(raw)
    return raw_list


def read_all_files(path, max_files_num=1):
    # 读取文件夹下所有.mat文件
    print("read_all_files start...")
    # 遍历Preprocessed_EEG文件夹下所有.mat文件
    data_list = []
    # 读取文件数量(每个文件中有15段数据)
    files_num = 0
    for root, dirs, files in os.walk(path):
        for file in files:
            if os.path.splitext(file)[1] == '.mat':
                file_path = os.path.join(root, file)
                raw_list = read_one_file(file_path)
                # 将raw_list中的每一个元素添加到data_list
                data_list.extend(raw_list)
                files_num += 1
                if files_num == max_files_num:
                    break

    # 生成所有数据的label(每个文件中有15段数据,每段数据的label相同)
    label_list = []
    for i in range(int(files_num)):
        label_list.extend(basic_label)
    # 将label_list添加到data_list
    print("共读取了{}个文件".format(files_num))
    print("共有{}段数据".format(len(data_list)))
    print("read ended...")
    return data_list, label_list


# read_all_files("Preprocessed_EEG/", 1)

UPDATE

2023/08/12

在代码中优化了了max_files_num的使用,从超参数改为函数中的参数。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐