从脑电波到机器人运动——深度学习:介绍

时间:2022-06-20
本文章向大家介绍从脑电波到机器人运动——深度学习:介绍,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本文为 AI 研习社编译的技术博客,原标题 : From brain waves to robot movements with deep learning: an introduction. 作者 | Norman Di Palo 翻译 | 狐不归 校对 | 邓普斯·杰弗 审核 | 酱番梨 整理 | 立鱼王 原文链接: https://towardsdatascience.com/from-brain-waves-to-arm-movements-with-deep-learning-an-introduction-3c2a8b535ece

神经系统是一个极为复杂的结构。你整个身体中的神经总长度超过十万公里,它们的每一部分都与你的脊髓和大脑相连。这个“网络”传输着每一个控制人体运动的电脉冲信号。每一个指令都从你的大脑发出,大脑是一个由神经元构成更加神奇的的结构,神经元间通过电激活信号进行通信。理解和解释脑电模式是神经科学家和神经生物学家的最大任务之一,但它也是一个非常具有挑战性的任务。

一种记录大脑活动的非侵入式的方法是脑电图(EEG),这项技术通过放置在病人头皮上的电极记录大脑的电压波动。通常会有大约30个这样的电极被放置在头皮周围,以记录脑电波的整体波动。总之,大脑活动与EEG信号之间的关系非常复杂,除了一些特定的实验室试验之外,人们对其了解甚少。由此,产生了一个巨大的挑战:如何对这些EEG扫描结果进行“解码”,从而通过非侵入式的脑机接口(BCI)控制机器人假肢或者其他设备。

作为一门强数据驱动的学科,在与深度学习相关的模式识别领域最近有了新的突破,创造出了一种新的使用神经网络分析这些电信号的新方法。在这篇文章中,我们会看到有关这个主题的介绍:我们将会看到一个由Kaggle竞赛提供的EEG数据,该竞赛旨在检测出哪一种EEG模式与特定的胳膊/手的姿势相关,比如抓取或举起物体。接着我们会设计一个神经网络,在用不同的方法对数据进行预处理以后,对不同的动作进行分类。我同样会展示一些大脑活动的数据可视化(图像),使我们对手上的数据有大致的了解。这个领域的研究的最终目的是开发出一种用户负担得起且有用的假肢装置,通过用大脑控制假体,帮助截肢者重获轻松完成基本动作的能力。该技术同样可以被应用于读取肌肉电信号的活动,通过分析激活状态的肌肉,对(使用者)想要进行的那种类型的动作进行解码。

你可以在这个在线olaboratory Notebook上找到本文中的所有代码,你可以在你的浏览器上直接运行代码。Github仓库链接请阅读原文。

数据简介

若你有Kaggle账号,则可以免费下载数据。你即将看到,数据只由几个.csv文件组成,这些文件分别是:

  • 作为模型输入的EGG数据,这项数据由放置在病人头皮上的32个电极采集得到。数据采集频率为500Hz。
  • 在6中可能的运动中,受试者试图完成的动作的结构化标签。

这些数据记录了不同的受试者完成一个简单的动作时的EEG信号,比如抓取或移动物体的动作。因此,数据集被划分为不同的段,也被归入不同的类目中。我们稍后在精确度预测时可以看到,脑电波的个体差异性很强,对于同一个人,模型可以以很高的准确率预测它所没有见过的片段,但如果对一个新的受试者进行这样的预测却可能有较大难度。

因此我们的目标就是创建一个神经网络,将读取到的EEG信号作为输入,输出受试者想要完成的6种可能动作的概率分布。由于“没有动作”本身不是6个类之一,我们可以将它单独作为一类添加,或者将所有可能的输出设定为0到1之间的值,使用一个阈值去决定某类动作是否被检测到。如果所有动作的预测值都在阈值以下,我们就认为没有动作发生。

[电极的位置,来源: https://www.kaggle.com/c/grasp-and-lift-eeg-detection/data]

我对这些电极上的活动做了一个动画版的数据可视化。由于采样频率较高(500Hz),我使用简单的3阶低通滤波器对数据进行平滑,并用前100帧做了个动画,也就是大约0.2秒的时间。

[前1/5秒内电极的活动]

我们还可以以2维热图的形式对数据进行可视化,纵轴是时间(从顶部开始向下),横轴表示32个电极。

[EEG时态热图(时间从顶部开始一直往下)]

这同样非常有用,我们即将看到,它会帮助我们完成时空卷积。

数据预处理

为了提升学习阶段的效果,原始数据要先经过预处理。比如,EEG信号的采样频率很高,而要完成的动作的变化率在则相对较低,这会造成许多问题:数据变化得很快,而动作却一直保持不变,这样一来数据的波动就都会被视为噪声。除此之外,时域的模型会接收到大量快速变化的数据,与此同时分类的输出却保持不变。

第一个可能的步骤是使用低通滤波器对数据进行滤波。即使是一个简单的运行均值也会有效。通过这种方法,我们减少了数据的高频变化,同时保留了更加有用的低频结构,因为我们要分类的动作变化的频率非常低(最高1Hz)。在此之后我们可以对数据进行下采样,即每10100个点仅保留一个数据。这一操作也有助于降低时间维度和数据相关性,从某种意义上来说,使数据更有时间稀疏性。除此之外,许多其他预处理技术也可以被应用,但是为了这篇介绍的简洁性,这里不多赘述,现在开始设计我们的神经网络。

神经网络设计与实验

处理时序数据,我们首先想到的结构之一就是循环神经网络。

这些网络具有动态结构,因此会有一个能够对时态数据进行编码的中间状态,因此可以根据过去的输入计算输出。我在Keras中设计了一个LSTM网络,并输入具有时序结构的训练数据。网络的效果不错,但在这个特别的例子里,我更想展示,通常用于图像处理的卷积神经网络是如何在时态数据上做得很好的。

如前所述,从某种意义上说,我们实际上在处理的是时空数据。上文所展示的热图的纵轴表示的是时域上的变化,而横轴展示的是不同的电极,几乎所有相邻的电极在人的头皮上也是空间相邻的。这意味着我们可以利用卷积来提取出有用的特征。一个2D的核可以同时对时间和空间上的模式进行编码。想象一个3*3的卷积核,它能够在热图所描述的矩阵上,通过对三个不同的时间步长(3个核行)以及3和不同的电极(3个核列)进行加权来提取特征。因此,一个具有多个卷积核的卷积神经网络可以找到在有限的时间周期里,电极的激活随着受试者想要做的运动而变化的特征。

我在Keras中实现了一个简单的CNN网络,检查它在这组数据集上的表现。在这个在线Colaboratory Notebook上,你可以找到所有本文中的代码,并直接在你的浏览器上运行。Github仓库链接请阅读原文。

import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers import Embedding
from keras.layers import LSTM, CuDNNLSTM, BatchNormalization, Conv2D, Flatten, MaxPooling2D, Dropout
from keras.optimizers import Adam

model = Sequential()
#model.add(CuDNNLSTM(128, input_shape = (time_steps//subsample, 32)))
model.add(Conv2D(filters = 64, kernel_size = (7,7), padding = "same", activation = "relu", input_shape = (time_steps//subsample, 32, 1)))
model.add(BatchNormalization())
#model.add(MaxPooling2D(pool_size = (3,3)))
model.add(Conv2D(filters = 64, kernel_size = (5,5), padding = "same", activation = "relu", input_shape = (time_steps//subsample, 32, 1)))
model.add(BatchNormalization())
#model.add(MaxPooling2D(pool_size = (3,3)))
model.add(Conv2D(filters = 64, kernel_size = (3,3), padding = "same", activation = "relu", input_shape = (time_steps//subsample, 32, 1)))
model.add(BatchNormalization())
#model.add(MaxPooling2D(pool_size = (3,3)))
model.add(Flatten())
#model.add(Dropout(0.2))
model.add(Dense(32, activation = "relu"))
model.add(BatchNormalization())
# model.add(Dropout(0.2))
model.add(Dense(6, activation = "sigmoid"))

adam = Adam(lr = 0.001)
model.compile(optimizer = adam, loss = "categorical_crossentropy", metrics = ["accuracy"])

model.summary()

为了检查我们模型的效果,如Kaggle竞赛中所建议的那样,我们对模型的AUC分数进行检查。如果你对AUC不太熟悉,可以查看这个清晰而直观的解释(链接)。你可以在在线笔记本中自己尝试,在一个快速的训练阶段后,我们能够达到约0.85的AUC分数。

通过训练不同的网络结构、采用预处理技术等手段,可以实现许多改进。但这个介绍性的概念验证(POC)展示了神经网络从这类数据中进行学习的卓越能力。

结论

在这篇文章中,我们对脑电信号EEG做了介绍,这是一种非侵入式的、相对简单的从使用者的头皮上采集的有用信号。我们看到了一些直观的数据可视化结果,以及怎样使用神经网络从中提取出诸如运动意图这样的特征。我相信这个领域(机器人假体、脑机交互)会因为深度学习而有显著快速的进步,数据科学技术、平台和竞赛也会更加广阔、逐年发展。

这些技术的影响将是巨大的。拥有能够以自然的方式控制的低成本的假肢,可以极大地改善数百万人的生活。

我建议你们去看一看“共生项目”,这是个最近启动的项目,一群有才华的人聚在一起,试着造出一个能够用肌肉的活动控制的低成本智能假臂,以使得这类设备真正落地、普及。

关注我的Twitter,获取我工作上的更多动态。更多: https://twitter.com/normandipalo

你可以在这个在线Colaboratory Notebook 上找到本文中的所有代码,并且在你的浏览器上直接运行。

想要继续查看该篇文章相关链接和参考文献?