原文来源
:Towards Data Science
作者:
Norman Di Palo
「雷克世界」编译:嗯~是阿童木呀、KABUDA、EVA
导语:如今,随着人工智能技术不断取得突破性进展,越来越多的领域开始使用AI来解决问题。最近,罗马大学(Sapienza University of Rome)一名学习人工智能与机器人的学生Norman Di Palo,使用深度神经网络对大脑的脑电波信号进行分析,对大脑活动进行可视化与解码,以了解大脑的活动意图。而这一研究领域的最终目的是开发出价格合理且有用的假肢设备,通过用大脑控制假肢,以帮助截肢患者重新获得轻松执行基本任务的能力。
神经系统是一个非常复杂的结构。在你的整个身体里,超过十万公里的神经将它的每个部分与你的脊髓和大脑相互通信。这个“网格”传输控制每一个动作的电脉冲(electrical impulse)。这些命令中的每一条都是从你的大脑开始的,这是一种更加神奇的与电子激活信号(electrical activation signal)进行通信的神经元结构。理解和解释大脑的电子模式是神经学家和神经生物学家最大的探索之一,但事实证明这是一项极具挑战性的任务。
脑电图(electroencephalography,EEG)是一种非侵入性的大脑活动记录方式。这是一种能够利用放置在患者头皮上的电极来记录脑电压波动(brain voltage fluctuation)的技术。通常,这些电极中的大约30个被放置在头皮周围,这样即可记录脑电波的全局活动。无论如何,大脑活动和脑电图信号之间的关系是很复杂的,在没有特定实验室测试的情况下,人们对它知之甚少。有一个巨大的挑战,就是学习如何“解码”(在某种意义上)这些脑电图扫描,这可以使用非侵入性脑-计算机接口(non-invasive brain-computer interface,BCI)来控制机器人假肢和其他设备。
用脑电图记录的脑电波的例子
作为强大的数据驱动的学科,深度学习在相关模式识别(related pattern recognition)任务中的最新突破创造了一种使用神经网络分析这些电信号的新方法。在本文中,我们将看到这个主题的介绍:我们将阅读一场Kaggle竞赛所提供的脑电图数据,旨在检测哪些脑电图模式与特定的手臂和手势相对应(例如抓取或举起物体)。然后我们将设计一个神经网络,在以不同的方式对数据进行预处理之后执行这样的分类。我还将展示一些大脑活动的数据可视化(data visualization),以对我们正在使用的数据给出一个大致的理解。这一研究领域的最终目标是开发出价格合理且有用的假肢设备,可以通过用大脑控制假肢,以帮助截肢患者重新获得轻松执行基本任务的能力。类似的技术也可以应用于阅读肌肉电子激活,从而通过分析激活的肌肉来对一个人正在试图执行的动作进行解码。
数据介绍
如果你有Kaggle帐户,你可以免费下载数据。正如你将看到的,数据是由几个.csv文件组成的。这些文件,分别是:
·
将脑电图数据作为模型的输入,用放置在患者头皮上的32个电极进行记录。数据记录以500赫兹进行记录。
·
在6种可能的情况之中,人类测试人员试图实现的运动的框架标签(Frame-wise label)。
这些数据是通过记录不同的人类测试人员执行简单的动作(比如抓取和举起物体)的脑电图而收集的。因此,数据集被划分为不同的场景,也有不同的主题。我们稍后会看到,在精确度预测中,脑电波可能是相当个人化的,因为模型可以非常精确地预测同一个人在不可见场景中的意图,但是如果训练不够充分的话,它们也可能很难在新的测试人员身上做同样的事情。
因此,我们的目标是创建一个神经网络,它将脑电波读数作为输入,并输出测试人员正在试图执行的这6个可能动作的概率分布。由于“无动作”不是一个可能的类,所以我们可以将其作为一个类添加或者将所有可能的输出设置为0到1之间的值,并使用阈值来决定是否检测到该动作。如果每一个动作都在阈值之下,则我们认为它是无动作。
电极位置
为了更好地进行说明,我做了这些电极活动的动画数据可视化图。由于采样频率非常高(500 Hz),我使用一个简单的3步低通滤波器(low pass filter)来平滑数据,并创建了前100帧的动画,即大约1/5秒。
在第一个1/5秒内激活32个电极
我们还可以将时间数据可视化为一个2D热图,其中,纵轴是时间(从顶部开始并不断向下),横轴表示32个电极。
脑电图时域热图(时间从顶部开始并不断向下)
这也是非常有用的,因为我们将会看到,它将使得我们能够使用时空卷积(spatio-temporal convolutions)。
数据预处理
这些原始数据应该进行预处理,以便使学习阶段变得更为成熟。例如,相较于已执行动作的相对较低的变化率,EEG的非常高的采样频率可能会导致许多问题:数据变化非常快,但动作实际上保持不变,因此波动几乎可以被人为是噪声。此外,时间模型会收到很多快速变化的数据,而分类输出永远不会改变。
第一个可能的步骤是用低通滤波器对数据进行过滤。即使是一个简单的运行平均值也能起作用:通过这种方式,我们减轻了数据的高频变化,同时保留了更加有用的低频结构,因为我们即将对其进行分类的动作的变化频率非常低(最多1Hz)。之后,我们可以对数据进行二次采样,也就是说,每10,100次只能保留一个数据点,等等。这也有助于减少时间维度并降低数据的相关性,从而使其从某种意义上说,使得时间更稀疏。
我们可以采用许多其他预处理技术,但是为了简单起见,我们可以在这里停下来,并开始设计我们的神经网络。
神经网络设计与实验
处理时态数据时,我们首先想到的结构就是循环神经网络。这些网络具有动态结构,内部状态允许它们对时态数据进行编码,因此它们也基于过去的输入来计算它们的输出。我基于Keras设计了一个长短期记忆网络(LSTM),并且采用时序结构将训练数据输入至LSTM网络中。结果是好的,但在这个特殊的例子中,我更感兴趣的是展示一个经常用于图像的卷积神经网络,是如何很好地处理时态数据的。
正如前面所描述的,从某种意义上来讲,我们实际是在处理时空数据(spatio-temporal data):上面的纵坐标表示热图的时间演变,而横坐标表示各种电极,相邻的电极几乎总是在人类头皮上的物理空间中相接近。这意味着我们实际上可以通过卷积来提取有用的特征:2D内核将在时间和空间上对模式进行编码。设想一个3×3卷积内核:在热图描述的矩阵上,它可以通过在3个不同的时间步长(3个内核行)上进行加权求和来提取特征值,但也可以在3个不同的电极(3个内核列)上提取特征。因此,具有许多内核的CNN可以发现电极激活是如何在有限的时间周期内改变与目标动作相关的特征的。
我在Keras中实现了一个简单的CNN来检查它在这个数据集中的性能。你可以在
Colaboratory Notebook
中找到本文的所有代码,并且可以在浏览器中直接运行代码。这是
GitHub repo
。
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())