python实现对脑电数据情绪分析

AI科技大本营 AI科技大本营     2022-12-17     412

关键词:

作者|李秋键

出品|AI科技大本营(ID:rgznai100)

引言

脑电波是一类由大脑中局部群体神经元同步放电所形成的具有时空特征的脑电活动电波。德国医生汉斯·伯格(Hans Berger)在1924年首次在人的头骨上记录到脑电波图(electroencephalography,EEG)。心理学研究表明,人类的认知和感知可以通过脑电波来表达。当大脑的嗅觉、听觉、视觉、味觉及触觉神经受到刺激时,其刺激反应信号可以通过脑电波表达出来,从而揭示感官和人员之间的心理关联性。其中大量研究展示了使用脑电信号连续确定个人舒适感的可行性,并且可以得到更加客观的数据。近来则有研究表明触觉刺激与脑电波的θ,α,β这三个频段均存在关联性。

传统的情绪识别主要是基于面部特征、肢体动作和语音的研究,这些外在特征容易伪装,并不能反应出真实的情绪,脑电信号可以反映大脑在加工情绪时所伴随的神经电生理活动,能够很好的弥补传统研究方法的缺陷。

故本项目通过使用python语言搭建KNN机器学习算法实现对EEG脑电波数据的情绪分析分类。其最终实现的效果如下图可见:

No.1 “基本介绍”

环境要求

本次环境使用的是python3.6.5+windows平台。主要用的库有:

csv模块。CSV库在这里用来读取CSV数据集文件。其中CSV文件是逗号分隔值文件,是一种常用的文本格式,用以存储表格数据,包括数字或者字符。很多程序在处理数据时都会碰到csv这种格式的文件,它的使用是比较广泛的。

scipy模块。scipy作为高级科学计算库:和numpy联系很密切,scipy一般都是操控numpy数组来进行科学计算、统计分析,所以可以说是基于numpy之上了。scipy有很多子模块可以应对不同的应用,例如插值运算,优化算法等等。scipy则是在numpy的基础上构建的更为强大,应用领域也更为广泛的科学计算包。正是出于这个原因,scipy需要依赖numpy的支持进行安装和运行。以Python为基础的scipy的另一个好处是,它还提供了一种强大的编程语言,可用于开发复杂的程序和专门的应用程序。使用scipy的科学应用程序受益于世界各地的开发人员在软件领域的许多小众领域中开发的附加模块。

pathlib模块。该模块提供了一些使用语义表达来表示文件系统路径的类,这些类适合多种操作系统。

Pickle模块。python的pickle模块实现了基本的数据序列和反序列化。通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储;通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

以及其他常用模块,如OpenCV等不一一介绍了。

KNN算法介绍

其中k近邻算法(k Nearest Neighbor,kNN)是一种理论上比较成熟的智能算法,最初由Cover和Hart于1968年提出。kNN算法思路简单直观:对于给定的测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个“邻居”的信息来进行预测。

kNN方法可以实现分类任务和回归任务。在分类任务中,一般使用“投票法”,即在k个“近邻”样本中出现最多的种类标记作为预测结果。在回归任务中,一般使用“平均法”,即将这k个样本的实值输出标记的平均值作为预测结果。在定义了相似度评价准则后,还可以基于相似度的大小进行加权投票和加权平均。相似度越大的样本权重越大。其中KNN算法分类流程如下图:

No.2 “模型搭建”

数据集准备

首先我们使用官方提供的EEG数据集,放置data文件夹下:

数据特征提取

首先我们使用官方提供的EEG数据集,放置data文件夹下:

通过使用pickle实现对dat数据文件的读取,获取各个数据文件中特征向量,并在每个信道中进行fft。

其中输入:维数为N × M的通道数据,N为通道个数,M为每个通道的脑电图数据个数。

输出:维度为N x M的FFT结果。N表示信道数,M表示每个信道的FFT数据数。

关键代码如下:

for file in os.listdir("../data"):
      fname = Path("../data/"+file)
      x = cPickle.load(open(fname, 'rb'), encoding="bytes")
      for i in range(40):
                num+=1
                eeg_realtime = x[b'data'][i]
                label = x[b'labels'][i]
                if label[0] >6:
                    val_v = 3
                elif label[0] < 4:
                    val_v = 1
                else:
                    val_v = 2
                if label[1] > 6:
                    val_a = 3
                elif label[1] < 4:
                    val_a = 1
                else:
                    val_a = 2
                if i < 39:
                    va_label.write(str(val_v) + ",")
                    ar_label.write(str(val_a) + ",")
                if num==1280:
                    va_label.write(str(val_v) )
                    ar_label.write(str(val_v) )
                eeg_raw = np.reshape(eeg_realtime, (40, 8064))
                eeg_raw = eeg_raw[:32, :]
                eeg_feature_arr = self.get_feature(eeg_raw)
                for f in range(160):
                    if f == 159:
                        fout_data.write(str(eeg_feature_arr[f]))
                    else:
                        fout_data.write(str(eeg_feature_arr[f]) + ",")
                fout_data.write("\\n")
                print(file + " Video watched")

然后从计算fft得到所有通道的频率。输入:维数为N × M的通道数据,N为通道个数,M为每个通道的脑电图数据个数。输出:每个通道的频带:Delta, Theta, Alpha, Beta和Gamma。

# Length data channel
L = len(all_channel_data[0])
# Sampling frequency
Fs = 128
# Get fft data
data_fft = self.do_fft(all_channel_data)
# Compute frequencymotio
frequency = map(lambda x: abs(x // L), data_fft)
frequency = map(lambda x: x[: L // 2 + 1] * 2, frequency)
f1, f2, f3, f4, f5 = itertools.tee(frequency, 5)
# List frequency
delta = np.array(list(map(lambda x: x[L * 1 // Fs - 1: L * 4 // Fs], f1)))
theta = np.array(list(map(lambda x: x[L * 4 // Fs - 1: L * 8 // Fs], f2)))
alpha = np.array(list(map(lambda x: x[L * 5 // Fs - 1: L * 13 // Fs], f3)))
beta = np.array(list(map(lambda x: x[L * 13 // Fs - 1: L * 30 // Fs], f4)))
gamma = np.array(list(map(lambda x: x[L * 30 // Fs - 1:L * 50 // Fs], f5)))

模型预测

从特征得到arousal值和valence值。其中Valence-Arousal分别代表情绪的正负向程度和激动程度,基于这两个维度可以构成一个情感平面空间,任何一个情感状态可以通过具体的Valence-Arousal数值,映射到VA平面空间中具体的一个点。

输入:来自所有频带和信道的特征(标准差和平均值),维度为1 × M(特征数量)。

输出:由每一种arousal和valence产生的1至3级情绪。1表示低,2表示中性,3表示高。

self.train_arousal = self.train_arousal[40*(index-1):40*index]
self.train_valence = self.train_valence[40*(index-1):40*index]
self.class_arousal = np.array([self.class_arousal[0][40*(index-1):40*index]])
self.class_valence = np.array([self.class_valence [0][40*(index-1):40*index]])
distance_ar = list(map(lambda x: ss.distance.canberra(x, feature), self.train_arousal))
# Compute canberra with valence training data
distance_va = list(map(lambda x: ss.distance.canberra(x, feature), self.train_valence))
# Compute 3 nearest index and distance value from arousal
idx_nearest_ar = np.array(np.argsort(distance_ar)[:3])
val_nearest_ar = np.array(np.sort(distance_ar)[:3])
# Compute 3 nearest index and distance value from arousal
idx_nearest_va = np.array(np.argsort(distance_va)[:3])
val_nearest_va = np.array(np.sort(distance_va)[:3])
# Compute comparation from first nearest and second nearest distance.、If comparation less or equal than 0.7, then take class from the first nearest distance. Else take frequently class.
# Arousal
comp_ar = val_nearest_ar[0] / val_nearest_ar[1]

然后从特征中获取情感类。

输入:来自所有频段和信道的特征(标准偏差),尺寸为1 × M(特征数量)。

输出:根据plex模型,情绪在1到5之间的类别。

class_ar, class_va = self.predict_emotion(feature,fname)
print(class_ar, class_va)
if class_ar == 2.0 or class_va == 2.0:
    emotion_class = 5
if class_ar == 3.0 and class_va == 1.0:
    emotion_class = 1
elif class_ar == 3.0 and class_va == 3.0:
    emotion_class = 2
elif class_ar == 1.0 and class_va == 3.0:
    emotion_class = 3
elif class_ar == 1.0 and class_va == 1.0:
    emotion_class = 4

预测结果如下图可见:

完整代码

链接:

https://pan.baidu.com/s/1BX58sJv037eIJx9A8jWt3g

提取码:rwpe

作者简介

李秋键,CSDN博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等。

专访

把钱投给甘坐冷板凳的 AI 研究院

技术

大有乾坤,售前机器人背后 AI 技术

新闻

他的压缩算法改变了世界

转载

女程序员也有35岁危机

分享

点收藏

点点赞

点在看

2021年科大讯飞基于脑电的情绪识别前三名队伍分享

文章目录1.第一名AI_health1.1团队介绍1.2算法方案解析1.2.1数据处理1.2.2模型设计思路1.2.3模型设计1.2.4结果1.3优化思路2.第二名虚拟革命战队2.1团队介绍2.2任务介绍2.3方案2.3.1数据预处理2.3.2深度学习架构2.3.2.1编码器 查看详情

情绪分析的训练数据[关闭]

】情绪分析的训练数据[关闭]【英文标题】:Trainingdataforsentimentanalysis[closed]【发布时间】:2011-11-2423:04:04【问题描述】:我在哪里可以获得已在企业领域中被分类为正面/负面情绪的文档语料库?我想要为公司提供评论的大量文... 查看详情

用于情绪分析的 Mahout

...时间】:2013-02-2214:09:07【问题描述】:使用mahout我可以对数据的情绪进行分类。但我被一个混淆矩阵困住了。我正在使用mahout0.7朴素贝叶斯算法对推文的情绪进行分类。我使用trainnb和testnb朴素贝叶斯分类器来训练分类器并将推... 查看详情

用于电子邮件情绪分析的客户支持数据集

】用于电子邮件情绪分析的客户支持数据集【英文标题】:Customersupportdatasetsfore-mailsentimentanalysis【发布时间】:2012-01-1908:53:03【问题描述】:我正在客户支持领域中寻找一个带注释的数据集以进行情绪分析,以训练我的朴素贝... 查看详情

Vader 情绪分析:如何对单个单词进行评分?

】Vader情绪分析:如何对单个单词进行评分?【英文标题】:VaderSentimentAnalysis:Howaretheindividualwordsrated?【发布时间】:2018-11-2819:11:15【问题描述】:所以我使用VaderSentimentAnalyzer来分析某些客户反馈。在评估输出时,我看到情绪分... 查看详情

人脸情绪识别需求分析心得

...别作出一个解决方案。对用户以各种方式提交的图像视频数据进行分析,并给出相应的情绪分析结果。背景随着计算机的快速发展,人机交互越来越多地出现在日常生活中,如何让计算机更好地理解人类的心理是人机交互必须要解... 查看详情

Huggingface 在情绪分析任务中给出 pytorch 索引错误

...问题描述】:我正在尝试对服务器上包含数百万条推文的数据集进行情绪分析。我正在调用一个API预测函数,该函数获取100条推文的列表并遍历每条推文的测试以返回拥抱脸情绪值,并将该情绪写入solr数据 查看详情

情绪分析的种子数据[关闭]

】情绪分析的种子数据[关闭]【英文标题】:Seeddataforsentimentanalysis[closed]【发布时间】:2010-11-1419:58:06【问题描述】:我正在玩情绪分析,我正在寻找一些种子数据。有免费的字典吗?其实很简单:3组文本/句子,分别代表“正... 查看详情

对关键字的情绪

】对关键字的情绪【英文标题】:Sentimenttowardsakeyword【发布时间】:2017-05-2200:13:57【问题描述】:我一直在寻找情感和文本分析服务,但他们中的大多数似乎分析整个文本并为其提供一个结果。有没有一种方法可以针对两个不同... 查看详情

spark中情绪分析的中立性

...但我对中立的确切含义有一些澄清。据我了解,在给定的数据集中,有预先标记的句子,其中包含必要的类,下面以3个为例。0->Negativesentiment1-> 查看详情

用于情绪分析的好数据集? [关闭]

】用于情绪分析的好数据集?[关闭]【英文标题】:Gooddatasetforsentimentanalysis?[closed]【发布时间】:2014-08-2715:31:28【问题描述】:我正在进行情绪分析,我正在使用此链接中给出的数据集:http://www.cs.jhu.edu/~mdredze/datasets/sentiment/inde... 查看详情

《面向微博的社会情绪词典构建及情绪分析方法研究》学习笔记

  1.目的:      探索一种面向微博的社会情绪词典构建方法;  2.步骤:      1)通过手工方法建立小规模的基准情绪词典;      2)利用深度学习工具Word2vec对社会热点事件的微博语料通过增量式学... 查看详情

图神经网络汇总和总结

...完整项目代码和资料请私聊。数据集1、脑电项目探索和实现(EEG)(上):研究数据集选取和介绍SEED相关论文阅读分析:1、EEG-SEED数据集作者的—基线论文阅读和分析2、图神经网络EEG论文阅读和分析:《EEG-BasedEmotionRecogni... 查看详情

python通过情绪分析处理文本并返回包含情绪指示符“pos”,“neg”,“neutral”和分数f的字典(代码片段)

查看详情

使用 OpenNLP 进行情绪分析

】使用OpenNLP进行情绪分析【英文标题】:SentimentAnalysisusingOpenNLP【发布时间】:2015-09-2307:42:41【问题描述】:我正在使用ApacheOpenNLP对Yammer对话进行情绪分析。这里的想法是将每个对话分为积极、消极或中性情绪。对话可以是单... 查看详情

python实现房产数据分析与可视化数据分析实战

Python库的选择话说,工欲善其事,必先利其器,虽然我们已经选择Python来完成剩余的工作,但是我们需要考虑具体选择使用Pytho的哪些利器来帮助我们更快更好地完成剩余的工作。我们可以看一下,在这个任务中,主要涉及到四... 查看详情

Python NLTK:SyntaxError:文件中的非 ASCII 字符“\xc3”(情绪分析-NLP)

】PythonNLTK:SyntaxError:文件中的非ASCII字符“\\\\xc3”(情绪分析-NLP)【英文标题】:PythonNLTK:SyntaxError:Non-ASCIIcharacter\'\\xc3\'infile(SentimentAnalysis-NLP)PythonNLTK:SyntaxError:文件中的非ASCII字符“\\xc3”(情绪分析-NLP)【发布时间】:20... 查看详情

无监督情绪分析

】无监督情绪分析【英文标题】:UnsupervisedSentimentAnalysis【发布时间】:2011-04-2415:51:19【问题描述】:我已经阅读了很多文章,这些文章解释了在情感分析系统真正起作用之前需要一组初始文本,这些文本被归类为“正面”或“... 查看详情