数据分析实战<一>脑电(EEG)分析

这两天需要对预实验的脑电进行一个分类,在这里记录一下流程

脑电分析系列文章
mne官网
mne教程
随机森林分类
Python 多因素方差分析

文章目录

  • 1. 脑电数据的处理
    • 1.1 基本概念
    • 1.2 实际处理
    • 1.3 全部代码
  • 2. 随机森林分类
    • 1. label的制作
    • 2. 使用随机森林进行分类
    • 3. 全部代码
  • 3. 显著性检验
  • 4. 多文件测试
    • 1. 文件选择
    • 2. 精确度分析
    • 3. anova分析
  • 4. 可扩展性
    • 1. 抽取代码
    • 2. 有待扩展

1. 脑电数据的处理

1.1 基本概念

由于是刚刚学习的一些概念,这里就不做过多的解释贻笑大方了。就简单说一下自己的理解。

  • raw :读取脑电的原始数据,里面重要的数据结构如下:
    • info:记录一些备注信息,比如哪些是坏通道
    • ch_name:采集数据用到的channel名字
  • epoch:把原始的数据划分成段,方便后续的分析
  • annotation/event: 每一段epoch的标签,两者区别具体看官方文档。不过用起来基本是一样的,并且有mne.events_from_annotationsevents_from_annotations可以相互转换。

了解完以上的概念之后,就可以进行实际的操作了。

1.2 实际处理

实际需求

  1. 由于采集数据的时候,没有进行annotation和event的标记,所以直接使用时间作为划分epoch的依据,这里采用30s作为一个epoch。
  2. 采集的是全64个通道,但是真正采集的就9个通道,需要对通道进行过滤
  3. 每20Min受试者报告一次或者两次本阶段的困倦程度,所以10 or 20min内的所有epoch都是一样的annotation
  4. 由于采集的时候电解液的风干,以及电极帽的接触不良,所以有的通道的数据可能不能用,应该进行过滤。

处理过程

1. 数据读取

import numpy as np
import mne
from mne.time_frequency import psd_welch
import os################# 文件路径 ######################
filename = "D:/data/eeg/physionet-sleep-data/SC4001E0-PSG.edf"
filename2 = "D:/data/eeg/qyp.edf"
savepath = "result"
## 使用hxx作为训练数据, qyp作为测试数据
resultName = "features_test.npy"# ############# 1. 读取文件 #################
raw = mne.io.read_raw(filename2, preload=True)

2. 数据预处理

数据预处理分成两步:

  1. 过滤不必要的频域
  2. 过滤不需要的通道

############# 2. 预处理 #####################
# 过滤高低频域,过滤防止0的干扰,同时减少数据量
raw.filter(l_freq=0.1, h_freq=40)
# 选择通道
alllist = ['Fpz', 'Fp1', 'Fp2', 'AF3', 'AF4', 'AF7', 'AF8', 'Fz', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'FCz', 'FC1', 'FC2', 'FC3', 'FC4', 'FC5', 'FC6', 'FT7', 'FT8', 'Cz', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'T7', 'T8', 'CP1', 'CP2', 'CP3', 'CP4', 'CP5', 'CP6', 'TP7', 'TP8', 'Pz', 'P3', 'P4', 'P5', 'P6', 'P7', 'P8', 'POz', 'PO3', 'PO4', 'PO5', 'PO6', 'PO7', 'PO8', 'Oz', 'O1', 'O2', 'ECG', 'HEOR', 'HEOL', 'VEOU', 'VEOL']
goodlist = ['FCz', 'Pz', 'Fpz', 'Cz', 'C1', 'C2','O1', 'O2', 'Oz',]
goodlist = set(goodlist)
badlist = []
for x in alllist:if x not in goodlist:badlist.append(x)
picks = mne.pick_channels(alllist, goodlist, badlist)
raw.plot(order=picks, n_channels=len(picks))
for x in badlist:raw.info['bads'].append(x)

3. 按时间划分epoch

# 30s一个epoch
epochs = mne.make_fixed_length_epochs(raw, duration=30, preload=False)

4. 特征提取

def eeg_power_band(epochs):"""脑电相对功率带特征提取该函数接受一个""mne.Epochs"对象,并基于与scikit-learn兼容的特定频带中的相对功率创建EEG特征。Parameters----------epochs : EpochsThe data.Returns-------X : numpy array of shape [n_samples, 5]Transformed data."""# 特定频带FREQ_BANDS = {"delta": [0.5, 4.5],"theta": [4.5, 8.5],"alpha": [8.5, 11.5],"sigma": [11.5, 15.5],"beta": [15.5, 30]}psds, freqs = psd_welch(epochs, picks='eeg', fmin=0.5, fmax=30.)# 归一化 PSDs,这个数组中含有0元素,所以会出现问题,正确的解决方式,从epoch中去除或者从数组中去除# psds = np.where(psds < 0.1, 0.1, psds)# sm = np.sum(psds, axis=-1, keepdims=True)# psds = numpy.divide(psds, sm)psds /= np.sum(psds, axis=-1, keepdims=True)X = []for fmin, fmax in FREQ_BANDS.values():psds_band = psds[:, :, (freqs >= fmin) & (freqs < fmax)].mean(axis=-1)X.append(psds_band.reshape(len(psds), -1))return np.concatenate(X, axis=1)

5. 保存文件

由于实验2个小时,所以会划分成240个epoch,但是有的可能会长,有的可能会短一个,长的应该直接舍去,因为这个是实验之后关闭设备采到的。

ans = eeg_power_band(epochs)
# 截取前240个数据
if ans.shape[0] > 240 :ans = ans[:240]
print(ans.shape) ## hxx(240, 45), qyp (239, 45)if not os.path.exists(savepath):os.mkdir(savepath)
np.save(savepath + "/" + resultName, ans)

1.3 全部代码

"""
@author:fuzekun
@file:myFile.py
@time:2022/10/10
@description:
"""
import numpy as np
import mne
from mne.time_frequency import psd_welch
import os################# 文件路径 ######################
filename = "D:/data/eeg/physionet-sleep-data/SC4001E0-PSG.edf"
filename2 = "D:/data/eeg/qyp.edf"
savepath = "result"
## 使用hxx作为训练数据, qyp作为测试数据
resultName = "features_test.npy"# ############# 1. 读取文件 #################
raw = mne.io.read_raw(filename2, preload=True)# ############ 2. 预处理 #####################
# # 过滤防止0的干扰
raw.filter(l_freq=0.1, h_freq=40)
# # 选择通道
alllist = ['Fpz', 'Fp1', 'Fp2', 'AF3', 'AF4', 'AF7', 'AF8', 'Fz', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'FCz', 'FC1', 'FC2', 'FC3', 'FC4', 'FC5', 'FC6', 'FT7', 'FT8', 'Cz', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'T7', 'T8', 'CP1', 'CP2', 'CP3', 'CP4', 'CP5', 'CP6', 'TP7', 'TP8', 'Pz', 'P3', 'P4', 'P5', 'P6', 'P7', 'P8', 'POz', 'PO3', 'PO4', 'PO5', 'PO6', 'PO7', 'PO8', 'Oz', 'O1', 'O2', 'ECG', 'HEOR', 'HEOL', 'VEOU', 'VEOL']
goodlist = ['FCz', 'Pz', 'Fpz', 'Cz', 'C1', 'C2','O1', 'O2', 'Oz',]
goodlist = set(goodlist)
badlist = []
for x in alllist:if x not in goodlist:badlist.append(x)
picks = mne.pick_channels(alllist, goodlist, badlist)
raw.plot(order=picks, n_channels=len(picks))
for x in badlist:raw.info['bads'].append(x)# ############## 2. 切分成epochs ################
epochs = mne.make_fixed_length_epochs(raw, duration=30, preload=False)# ############# 3 特征提取 ##################
def eeg_power_band(epochs):"""脑电相对功率带特征提取该函数接受一个""mne.Epochs"对象,并基于与scikit-learn兼容的特定频带中的相对功率创建EEG特征。Parameters----------epochs : EpochsThe data.Returns-------X : numpy array of shape [n_samples, 5]Transformed data."""# 特定频带FREQ_BANDS = {"delta": [0.5, 4.5],"theta": [4.5, 8.5],"alpha": [8.5, 11.5],"sigma": [11.5, 15.5],"beta": [15.5, 30]}psds, freqs = psd_welch(epochs, picks='eeg', fmin=0.5, fmax=30.)# 归一化 PSDs,这个数组中含有0元素,所以会出现问题,正确的解决方式,从epoch中去除或者从数组中去除# psds = np.where(psds < 0.1, 0.1, psds)# sm = np.sum(psds, axis=-1, keepdims=True)# psds = numpy.divide(psds, sm)psds /= np.sum(psds, axis=-1, keepdims=True)X = []for fmin, fmax in FREQ_BANDS.values():psds_band = psds[:, :, (freqs >= fmin) & (freqs < fmax)].mean(axis=-1)X.append(psds_band.reshape(len(psds), -1))return np.concatenate(X, axis=1)ans = eeg_power_band(epochs)
# 截取前240个数据
if ans.shape[0] > 240 :ans = ans[:240]
print(ans.shape) ## hxx(240, 45), qyp (239, 45)if not os.path.exists(savepath):os.mkdir(savepath)
np.save(savepath + "/" + resultName, ans)

2. 随机森林分类

1. label的制作

label制作分成两部分:

  1. 将原始的label从excel或者txt文件中提取出来
  2. 对原始label进行扩展,形成维度和特征相同的label列表

步骤1:

# 没有操作excel,直接复制粘贴的,应该采用excel的操作更加通用一些
"""
@author:fuzekun
@file:generateLabelFile.py
@time:2022/10/12
@description: 由原始标签生成每一个用户的id:label对应的set
"""
from collections import defaultdict
from json import dump, loadrawlabelFile = "result/rawLabel.json"# 文件夹下面的名字
fileName = ["hxx.edf", "qyp.edf"]
# 对应的label
raws = []
raw1 = [(4, 5), 6, 7, 7, 6, 6] # hxx
raw2 = [4, 6, 7, (7, 6), (7, 5),5] #qup
raws.append(raw1)
raws.append(raw2)ans = dict(zip(fileName, raws))print(ans)with open(rawlabelFile, 'w') as fp:dump(ans, fp)with open(rawlabelFile, 'r') as fp:ans = load(fp)print(ans)

将用户的文件名和label做一个映射:类似下面这种

在这里插入图片描述
步骤2:


def extractLabel(raw, n, spliteY, splitT, totalT):"""raw:原始标记n: 特征的数量spliteY: 划分的阈值splitT: 划分epoch的时间 stotalT: 总时常 h"""# 总共有多少段,然后每一个标签应该对应多少段splitTime = totalT * 3600 // splitT // len(raw)label = []for i, x in enumerate(raw):med = min(n, (i + 1) * splitTime)mbg = i * splitTimeif (str.isdigit(str(x))):x = 0 if x <= spliteY else 1  # [1,4]打成0,否则打成1for _ in range(mbg, med):label.append(x)else:  ## 一次回答两个数值的情况x, y = xx = 0 if x <= spliteY else 1y = 0 if y <= spliteY else 1for _ in range(mbg, mbg + splitTime // 2):label.append(x)for _ in range(mbg + splitTime // 2, med):label.append(y)return label

2. 使用随机森林进行分类

"""
@author:fuzekun
@file:myFile.py
@time:2022/10/10
@description:
"""
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report
from sklearn.model_selection import train_test_splitX_file = "result/X.npy"
y_file = "result/y.npy"X = np.load(X_file)
y = np.load(y_file)Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3)
clf = RandomForestClassifier(max_depth=2,random_state=0)
clf.fit(Xtrain, Ytrain)
# print(clf.feature_importances_)y_predict = clf.predict(Xtest)
acc = accuracy_score(Ytest, y_predict)print("Accuracy score: {}".format(acc))
print(classification_report(Ytest, y_predict))

在这里插入图片描述
可以看到效果还是比较显著的。

3. 全部代码

  1. 整合数据
"""
@author:fuzekun
@file:extractFetures.py
@time:2022/10/12
@description: 特征提取
"""
import os
from json import loadimport numpy as np
import mne
from mne.time_frequency import psd_welchdataFilePath = "D:/data/eeg"
rawLabelFile = "result/rawLabel.json"
save_X = "D:/data/X.npy"
save_y = "D:/data/y.npy"def extractFeture(dataFile:str, ch_name:list, spliteT:int, totalT:int):"""根据文件和chnnel提取特征dataFile: 文件名ch_name: 通道名称spliteT:划分的时间stotalT: 总时长hreturn: 返回特征numpys数组"""# ############# 1. 读取文件 #################raw = mne.io.read_raw(dataFile, preload=True)# ############ 2. 预处理 ###################### # 过滤防止0的干扰raw.filter(l_freq=0.1, h_freq=40)# # 选择通道alllist = ['Fpz', 'Fp1', 'Fp2', 'AF3', 'AF4', 'AF7', 'AF8', 'Fz', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8','FCz', 'FC1', 'FC2', 'FC3', 'FC4', 'FC5', 'FC6', 'FT7', 'FT8', 'Cz', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6','T7', 'T8', 'CP1', 'CP2', 'CP3', 'CP4', 'CP5', 'CP6', 'TP7', 'TP8', 'Pz', 'P3', 'P4', 'P5', 'P6', 'P7','P8', 'POz', 'PO3', 'PO4', 'PO5', 'PO6', 'PO7', 'PO8', 'Oz', 'O1', 'O2', 'ECG', 'HEOR', 'HEOL', 'VEOU','VEOL']goodlist = ch_namegoodlist = set(goodlist)badlist = []for x in alllist:if x not in goodlist:badlist.append(x)# picks = mne.pick_channels(alllist, goodlist, badlist)# raw.plot(order=picks, n_channels=len(picks))for x in badlist:raw.info['bads'].append(x)# ############## 2. 切分成epochs ################epochs = mne.make_fixed_length_epochs(raw, duration=spliteT, preload=False)# ############# 3 特征提取 ##################def eeg_power_band(epochs):"""脑电相对功率带特征提取该函数接受一个""mne.Epochs"对象,并基于与scikit-learn兼容的特定频带中的相对功率创建EEG特征。Parameters----------epochs : EpochsThe data.Returns-------X : numpy array of shape [n_samples, 5]Transformed data."""# 特定频带FREQ_BANDS = {"delta": [0.5, 4.5],"theta": [4.5, 8.5],"alpha": [8.5, 11.5],"sigma": [11.5, 15.5],"beta": [15.5, 30]}psds, freqs = psd_welch(epochs, picks='eeg', fmin=0.5, fmax=30.)# 归一化 PSDs,这个数组中含有0元素,所以会出现问题,正确的解决方式,从epoch中去除或者从数组中去除# psds = np.where(psds < 0.1, 0.1, psds)# sm = np.sum(psds, axis=-1, keepdims=True)# psds = numpy.divide(psds, sm)psds /= np.sum(psds, axis=-1, keepdims=True)X = []for fmin, fmax in FREQ_BANDS.values():psds_band = psds[:, :, (freqs >= fmin) & (freqs < fmax)].mean(axis=-1)X.append(psds_band.reshape(len(psds), -1))return np.concatenate(X, axis=1)ans = eeg_power_band(epochs)n = totalT * 3600 // spliteT# 截取前n个数据if ans.shape[0] > n:ans = ans[:n]print(ans.shape)  ## hxx(240, 45), qyp (239, 45)return ansdef extractLabel(raw, n, spliteY, splitT, totalT):"""raw:原始标记n: 特征的数量spliteY: 划分的阈值splitT: 划分epoch的时间 stotalT: 总时常 h"""# 总共有多少段,然后每一个标签应该对应多少段splitTime = totalT * 3600 // splitT // len(raw)label = []for i, x in enumerate(raw):med = min(n, (i + 1) * splitTime)mbg = i * splitTimeif (str.isdigit(str(x))):x = 0 if x <= spliteY else 1  # [1,4]打成0,否则打成1for _ in range(mbg, med):label.append(x)else:  ## 一次回答两个数值的情况x, y = xx = 0 if x <= spliteY else 1y = 0 if y <= spliteY else 1for _ in range(mbg, mbg + splitTime // 2):label.append(x)for _ in range(mbg + splitTime // 2, med):label.append(y)return labeldef extract(filePath, splitT, totalT, spliteY) : # 提取文件夹下的全部efg作为训练集,同时进行标签的填充X = []y = []with open(rawLabelFile, 'r') as fp:AllRawLabels = load(fp)for fileName in os.listdir(filePath):file = os.path.join(filePath, fileName)if not os.path.isfile(file): continuech_name = ['FCz', 'Pz', 'Fpz', 'Cz', 'C1', 'C2','O1', 'O2', 'Oz',]features = extractFeture(file, ch_name, splitT, totalT)rawLabel = AllRawLabels[fileName]labels = extractLabel(rawLabel, len(features), spliteY, splitT, totalT)X.extend(list(features))y.extend(labels)return X, yX, y = extract(dataFilePath, 30, 2)
X, y = np.array(X), np.array(y)
print(X.shape, y.shape)
np.save(save_X, X)
np.save(save_y, y)
  1. 随机森林
"""
@author:fuzekun
@file:myFile.py
@time:2022/10/10
@description:
"""
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report
from sklearn.model_selection import train_test_splitX_file = "result/X.npy"
y_file = "result/y.npy"X = np.load(X_file)
y = np.load(y_file)Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3)
clf = RandomForestClassifier(max_depth=2,random_state=0)
clf.fit(Xtrain, Ytrain)
# print(clf.feature_importances_)y_predict = clf.predict(Xtest)
acc = accuracy_score(Ytest, y_predict)print("Accuracy score: {}".format(acc))
print(classification_report(Ytest, y_predict))

3. 显著性检验

显著性检验分成四步

  1. 读取numpy数组
  2. 将numpy数组转化成pandas数组
  3. 使用函数进行anova分析,首先进行主观效应,其次进行多重比较检验
  4. 根据结果判断是否影响是否显著
"""
@author:fuzekun
@file:anova.py
@time:2022/10/12
@description: 方差分析
"""import pandas as pd
import numpy as np
from statsmodels.formula.api import ols
from scipy import stats
import statsmodels.api as sm
import matplotlib.pyplot as pltfeature_name_list = []
for i in range(45) :feature_name_list.append('f' + str(i))
# print(feature_name_list)data_array = np.load("result/X.npy")
label_array = np.load("result/y.npy")data_df = pd.DataFrame(data_array, columns=feature_name_list)
data_df['target'] = label_array# print(data_df)
# print(label_df)
formula = 'target ~ '
for i, x in enumerate(feature_name_list):if i != len(feature_name_list) - 1 :formula += x + '+'else :formula += x# print(data_df['f0'])
tired_anova = sm.stats.anova_lm(ols(formula,data = data_df).fit(),typ = 3)
print(tired_anova)

在这里插入图片描述

可以看到,上面的f0, f2, f4的远远小于了0.05, 也就是说拒绝了原假设,选择备择假设,可以说这些都是和target的相关性较强的点。

4. 多文件测试

1. 文件选择

使用了7个文件,选择了每一个文件的公共通道进行训练。部分脑电的图片如下所示:

在这里插入图片描述
在这里插入图片描述

2. 精确度分析

使用7个文件分类效果如下所示:精确度78%

在这里插入图片描述

3. anova分析

可以看到显著性较为明显

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-freWk28Q-1665668130424)(D:\blgs\source\imgs\image-20221013213403549.png)]

4. 可扩展性

1. 抽取代码

Json文件中存放了原始的标签。可以通过下面的代码生成,也可以直接进行编写。

"""
@author:fuzekun
@file:generateLabelFile.py
@time:2022/10/12
@description: 由原始标签生成每一个用户的id:label对应的set
"""
from collections import defaultdict
from json import dump, loadrawlabelFile = "result/rawLabel.json"# 文件夹下面的名字
fileName = ["hxx.edf", "qyp.edf", "1_1.edf", "4_1.edf", "7_1.edf", "11_1.edf", "csk.edf"]
# 对应的label
raws = []
raw1 = [(4, 5), 6, 7, 7, 6, 6] # hxx
raw2 = [4, 6, 7, (7, 6), (7, 5),5] #qup
raw3 = [7,	(9, 8),	(5, 7),	(5, 4),	4,	3] # 1_1
raw4 = [2,	5,	4,	5,	7,	8] # 4_1
raw5 = [7,	7,	8,	7,	6,	5] # 7_1
raw6 = [3,	5,	8,	6,	9,	5] # 11_1
raw7 = [3,	4,	5,	5,	6,	5] # cskraws.append(raw1)
raws.append(raw2)
raws.append(raw3)
raws.append(raw4)
raws.append(raw5)
raws.append(raw6)
raws.append(raw7)ans = dict(zip(fileName, raws))print(ans)with open(rawlabelFile, 'w') as fp:dump(ans, fp)with open(rawlabelFile, 'r') as fp:ans = load(fp)print(ans)

将label和特征的生成抽取成文件。

  • 划分epoch的时间进行抽取
  • 实验的时长,以及每一次询问的间隔。需要满足整数次
  • 选择的通道进行抽取
"""
@author:fuzekun
@file:extractFetures.py
@time:2022/10/12
@description: 特征提取
"""
import os
from json import loadimport numpy as np
import mne
from mne.time_frequency import psd_welch### 原始的标签放在了rawLable.json文件中,可以进行编写,也可以直接修改generateLableFile生成。dataFilePath = "D:/data/eeg"
rawLabelFile = "result/rawLabel.json"
save_X = "result/X.npy"
save_y = "result/y.npy"
ch_name = ['FCz', 'Pz', 'Fpz', 'Cz', 'C1', 'C2', ]def extractFeture(dataFile:str, ch_name:list, spliteT:int, totalT:int):"""根据文件和chnnel提取特征dataFile: 文件名ch_name: 通道名称spliteT:划分的时间stotalT: 总时长hreturn: 返回特征numpys数组totalT * 3600 / spliteT一定要能整除。"""# ############# 1. 读取文件 #################raw = mne.io.read_raw(dataFile, preload=True)# ############ 2. 预处理 ###################### # 过滤防止0的干扰raw.filter(l_freq=0.1, h_freq=40)# # 选择通道alllist = ['Fpz', 'Fp1', 'Fp2', 'AF3', 'AF4', 'AF7', 'AF8', 'Fz', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8','FCz', 'FC1', 'FC2', 'FC3', 'FC4', 'FC5', 'FC6', 'FT7', 'FT8', 'Cz', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6','T7', 'T8', 'CP1', 'CP2', 'CP3', 'CP4', 'CP5', 'CP6', 'TP7', 'TP8', 'Pz', 'P3', 'P4', 'P5', 'P6', 'P7','P8', 'POz', 'PO3', 'PO4', 'PO5', 'PO6', 'PO7', 'PO8', 'Oz', 'O1', 'O2', 'ECG', 'HEOR', 'HEOL', 'VEOU','VEOL']goodlist = ch_namegoodlist = set(goodlist)badlist = []for x in alllist:if x not in goodlist:badlist.append(x)# picks = mne.pick_channels(alllist, goodlist, badlist)# raw.plot(order=picks, n_channels=len(picks))for x in badlist:raw.info['bads'].append(x)# ############## 2. 切分成epochs ################epochs = mne.make_fixed_length_epochs(raw, duration=spliteT, preload=False)# ############# 3 特征提取 ##################def eeg_power_band(epochs):"""脑电相对功率带特征提取该函数接受一个""mne.Epochs"对象,并基于与scikit-learn兼容的特定频带中的相对功率创建EEG特征。Parameters----------epochs : EpochsThe data.Returns-------X : numpy array of shape [n_samples, 5]Transformed data."""# 特定频带FREQ_BANDS = {"delta": [0.5, 4.5],"theta": [4.5, 8.5],"alpha": [8.5, 11.5],"sigma": [11.5, 15.5],"beta": [15.5, 30]}psds, freqs = psd_welch(epochs, picks='eeg', fmin=0.5, fmax=30.)# 归一化 PSDs,这个数组中含有0元素,所以会出现问题,正确的解决方式,从epoch中去除或者从数组中去除# psds = np.where(psds < 0.1, 0.1, psds)# sm = np.sum(psds, axis=-1, keepdims=True)# psds = numpy.divide(psds, sm)psds /= np.sum(psds, axis=-1, keepdims=True)X = []for fmin, fmax in FREQ_BANDS.values():psds_band = psds[:, :, (freqs >= fmin) & (freqs < fmax)].mean(axis=-1)X.append(psds_band.reshape(len(psds), -1))return np.concatenate(X, axis=1)ans = eeg_power_band(epochs)n = totalT * 3600 // spliteT# 截取前n个数据if ans.shape[0] > n:ans = ans[:n]print(ans.shape)return ansdef extractLabel(raw, n, spliteY, splitT, totalT):"""raw:原始标记n: 特征的数量spliteY: 划分的阈值splitT: 划分epoch的时间 stotalT: 总时常 h"""# 总共有多少段,然后每一个标签应该对应多少段# 注意这个一定要能整除,否则出现标签数量过少的情况splitTime = totalT * 3600 // splitT // len(raw)label = []for i, x in enumerate(raw):med = min(n, (i + 1) * splitTime)mbg = i * splitTimeif (str.isdigit(str(x))):x = 0 if x <= spliteY else 1  # [1,4]打成0,否则打成1for _ in range(mbg, med):label.append(x)else:  ## 一次回答两个数值的情况x, y = xx = 0 if x <= spliteY else 1y = 0 if y <= spliteY else 1for _ in range(mbg, mbg + splitTime // 2):label.append(x)for _ in range(mbg + splitTime // 2, med):label.append(y)return labeldef extract(filePath, splitT, totalT, spliteY, ch_name) : # 提取文件夹下的全部efg作为训练集,同时进行标签的填充X = []y = []with open(rawLabelFile, 'r') as fp:AllRawLabels = load(fp)for fileName in os.listdir(filePath):print('##################' + fileName + '###################')file = os.path.join(filePath, fileName)if not os.path.isfile(file): continuefeatures = extractFeture(file, ch_name, splitT, totalT)rawLabel = AllRawLabels[fileName]labels = extractLabel(rawLabel, len(features), spliteY, splitT, totalT)print(len(features), len(labels))X.extend(list(features))y.extend(labels)return X, yX, y = extract(dataFilePath, 30, 2, 4, ch_name)
X, y = np.array(X), np.array(y)
print(X.shape, y.shape)
np.save(save_X, X)
np.save(save_y, y)

2. 有待扩展

  • 应该从excel文件中直接读取,但是没有这样做,还需要手动写。
  • 实验如果有中断,每一个文件的时常会变化,单是extract()函数默认每一个文件的时长和划分的间隔都是一样的。可以修改extract函数,将每一个文件的时长形成列表。然后分别extractLable和extractFeatur

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/62270.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TensorRT量化第一课:量化的定义及意义

目录 模型量化原理前言1. What、Why and How1.1 What1.2 Why1.3 How 2. 拓展-export参数详解3.总结参考 模型量化原理 前言 手写AI推出的全新TensorRT模型量化课程&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考。 本次课程为第一课&#xff0c;主要讲解量化的…

TensorRT量化第三课:动态范围的常用计算方法

目录 模型量化原理注意事项一、2023/4/11更新二、2023/4/13更新三、2023/4/16更新四、2023/4/24更新前言1.前情回顾2.动态范围的常用计算方法3.Histogram3.1 定义3.2 histogram实现3.3 思考3.4 拓展 4.Entropy4.1 定义4.2 示例代码4.3 流程实现4.4 思考4.5 实际应用4.6 TRT Ent…

当下流行的ChatGPT与百度的文心一言谁才是AI的霸主

ChatGPT和百度的文心一言是两种不同的自然语言处理&#xff08;NLP&#xff09;AI技术&#xff0c;它们具有相似的功能和特点&#xff0c;但有着很大的差异和各自的优势。ChatGPT是OpenAI团队开发的基于Transformer框架的大规模语言模型&#xff0c;是从大量自然语言数据中训练…

游戏本地化项目简介

节选自《翻译与本地化项目管理》&#xff0c;:凯瑞J.邓恩、埃琳娜S.邓恩 一个典型而完整的多平台游戏本地化项目涉及了文本的翻译、翻译与本地化项目管理音频的修改或再创作、完成本地化之后游戏内容的整合、质量保证、交付厂家和项目行政管理。 翻译是游戏本地化的中心任务。游…

游戏开发与本地化

游戏由内容和技术组成&#xff0c;技术将内容呈现给玩家&#xff0c;并控制游戏的顺序。内容由图形设计师、音频设计师、动画师以及游戏等级设计师创造&#xff0c;可能以游戏等级、角色、动画和影片等形式体现。技术就是游戏运行时计算机(或主机和其他设备)所读取的可执行代码…

国内头部游戏本地化服务商 安睿杰本地化翻译

安睿杰翻译深耕多年&#xff0c;具有丰富的游戏出海项目经验&#xff0c;凭借50语种、1000资深游戏母语译者的资源优势&#xff0c;已为500家游戏厂商提供千余款成功作品。 自2020年至今&#xff0c;ARJ为国内某头部手游厂商的一款热销手游提供了游戏本地化服务。 这是一款以…

Revit教程免费下载——Revit建筑施工图高级视频课程

Revit建筑施工图高级教程&#xff0c;包含施工图教程、多专业协同、案例文件三个分类。 【下载地址】 链接&#xff1a;https://pan.baidu.com/s/18KSIgfABHG8rNNd9sDHtDg 提取码&#xff1a;jwu8 【资源大小】14.14GB 【资源截图】 【目录】 一、施工图教程 0前言.mp4 …

建筑施工图纸

一、如何看懂施工图纸 在一个建筑工程项目中&#xff0c;看懂施工图纸是决定建筑工程项目施工成败的关键因素。 我们经常会看到老师傅手中拿着图纸&#xff0c;认真的观察。他们在查看施工图纸&#xff0c;很多新手不会看图纸&#xff0c;下面就来教你如何看懂。 二、学会使…

Revit软件中参照线在制作墙体上的使用及快速CAD图纸墙转化

Revit软件中参照线在制作墙体上的使用及快速CAD图纸墙转化 Revit中参考线(参照线)在墙上的妙用&#xff0c;如果你想做这样的墙&#xff0c;你会怎么想? 墙的顶部是倾斜的。对于这形状的墙&#xff0c;不可能通过传统墙的编辑轮廓来完成&#xff0c;因为我们知道编辑轮廓是墙的…

学习如何在AutoCad土木工程中绘制建筑设计图

学习如何在AutoCad中绘制建筑设计图从平面图到AutoCad土木工程中的整栋建筑 你会学到: 如何绘制房屋地图 如何绘制建筑设计 如何从AutoCad打印或出图 AutoCaD使用 AutoCaD命令使用 如何在2D Autocad中构建家庭或房屋地图(完整教程视频包括家庭地图、窗户、门、室内家具或物品、…

建筑设计中,如何快速获得场地的等高线图?

等高线指的是地形图上高程相等的相邻各点所连成的闭合曲线。把地面上海拔高度相同的点连成的闭合曲线&#xff0c;并垂直投影到一个水平面上&#xff0c;并按比例缩绘在图纸上&#xff0c;就得到等高线。&#xff08;来自百度百科的定义&#xff09; 图新地球软件&#xff0c;…

YOLOv7改进Transformer主干系列:最新结合BoTNet Transformer结构,一种简单却功能强大的backbone,自注意力提高模型性能

&#x1f4a1;统一使用 YOLOv7 代码框架&#xff0c;结合不同模块来构建不同的YOLO目标检测模型。&#x1f31f;本项目包含大量的改进方式,降低改进难度,改进点包含【Backbone特征主干】、【Neck特征融合】、【Head检测头】、【注意力机制】、【IoU损失函数】、【NMS】、【Loss…

yolov8模型训练结果分析以及如何评估yolov8模型训练的效果

运行结果目录 一、 confusion_matrix_normalized.png和confusion_matrix.png 混淆矩阵是对分类问题预测结果的总结。使用计数值汇总正确和不正确预测的数量&#xff0c;并按每个类进行细分&#xff0c;显示了分类模型进行预测时会对哪一部分产生混淆。通过这个矩阵可以方便地看…

安卓面试题 Android interview questions

安卓面试题 Android interview questions 作者&#xff1a;韩梦飞沙 ‎2017‎年‎7‎月‎3‎日&#xff0c;‏‎14:52:44 1. 要做一个尽可能流畅的ListView&#xff0c;你平时在工作中如何进行优化的&#xff1f; ①Item布局&#xff0c;层级越少越好&#xff0c;使用hie…

求职与面试(一):Android必备

2019年的冬天有点冷,一份基础面试题送给还在奋斗在Android领域的同学. Android基础问题 Activity&View系列 简述Android的布局分类? 早期Android官方提供以下五种布局: LinearLayoutRelativeLayoutFrameLayoutGridLayoutTableLayout 以上传统的布局,以LinearLayout和…

在Android面试前背八股和学面试技巧真的有用吗?

前言&#xff1a; 今年秋招以来&#xff0c;我集中面试了一些公司&#xff0c;想着至少能过一家吧&#xff0c;但后面发现面试安排十分紧凑&#xff0c;有种顾此失彼的感觉。 我刚开始的时候对Android面试的具体情况全然不知&#xff0c;也没有人告诉我应该注意些什么&#…

如何在Android面试中脱颖而出,高频Android面试题解析,帮你快速拿到Offer

Android面试就“小技巧” 了解自己的技能水平&#xff1a;在面试前&#xff0c;确保你对所面试的职位的技能要求有足够的了解&#xff0c;并检查自己的技能水平是否符合这些要求。熟悉面试流程&#xff1a;了解面试过程中可能会遇到的问题&#xff0c;并为每个问题准备好回答。…

Android面试攻略

文章背景 好记性不如烂笔头 Android层面 一、Android基础 1、四大组件的意义及使用&#xff0c;生命周期回调及意义 2、AsyncTask、Handler的使用 3、Android系统层次框架结构 4、AsyncTask的实现方式 5、AsyncTask使用的时候应该注意什么 6、Android常见的存储方式 7、Loop…

面试汇总:这是一份全面详细的Android面试指南

核心面试内容 对于Android技术专业面试&#xff0c;主要考察的内容包括&#xff1a;&#xff08;已按优先级排序&#xff09; 通用编程基础计算机基础特定编程语言智力题 需要特别注意的是&#xff1a; 编程基础、计算机基础是 所有技术开发都必备的基础知识&#xff0c;务必…

澜舟科技成立两周年|“孟子GPT”大模型开启邀测

2023年6月10日&#xff0c;澜舟科技迎来了成立两周年的纪念日。回首过去的两年&#xff0c;无惧诸多挑战和困难&#xff0c;我们始终坚持信念和目标&#xff0c;并取得了一系列瞩目的成绩。在此&#xff0c;我们要特别感谢一直支持和信赖我们的投资方们&#xff1a;创新工场、联…