如何使用TensorFlow.js构建这一系统

电子说

1.2w人已加入

描述

如果声音才是计算交互的未来,那么那些聋哑人怎么办?带着这个问题,本文作者构建了一套系统,让亚马逊的Alexa智能小助手学会了识别手语。本文介绍了如何使用TensorFlow.js来构建这一系统,全部代码和演示已上传至Github。

几个月前,有一天晚上我躺在床上,一个念头闪过我的脑海:“如果声音才是计算交互的未来,那么那些聋哑人怎么办?”我不知道究竟为何会产生这个想法,我自己可以正常说话、听觉也正常,我周围认识的人也没有聋哑人,我也不使用语音助手。这个问题总是萦绕在我的脑子里,于是我知道自己需要好好研究一下了。

最终结果就是现在这个项目的诞生,我让一台Amazon Echo智能扬声器对手语做出了响应。确切的说是对美国手语(ASL)做出了响应,因为手语种类有很多。

本文将介绍如何使用TensorFlow.js构建这一系统。读者可以用自己的单词和手语/手势组合来对模型进行训练。此外,我希望这种方法有助于让人们将焦点从项目的技术元素上转移出来,而更多关注人文元素。这个项目更多的不是关于底层技术的讨论,而是该技术能为人类提供的能力。

前期研究与系统需求

构建系统需要:

用于解释符号的神经网络(将视频转换为文本)。

一个文本到语音的转换系统,向Alexa说出需要解释的手势。

语音到文本的转换系统,用于转录Alexa对用户的响应。

运行此系统的设备(笔记本电脑/平板电脑)和与之交互的Echo智能扬声器。

将上述部分联系在一起的交互界面。

我可能花了很多时间来确定采用哪种类型的神经网络架构。为此我提出了几个选项:

1.由于符号有视觉和时间两个方面的属性,我一开始想选择CNN与RNN的组合,其中将最后一个卷积层的输出(在分类之前)作为序列输入RNN。我后来发现这种网络学名叫长期循环卷积网络(LRCN)。

2.使用3D卷积网络,其中卷积将以三维方式应用,前两个维度是图像,第三维度是时间。然而,这些网络需要大量的内存,我的macbook pro吃不消。

3.不再对视频流中的各帧都进行CNN训练,而是仅在光流表示上进行训练,该光流表示将表示两个连续帧之间的视在运动的模式。也就是说,它会对动作进行编码,这将产生更为通用化的手语模型。

4.使用双流CNN,其中空间流将是单帧(RGB)的,时间流将使用光流表示。

我通过阅读论文发现,这些论文至少使用了上述一些视频活动识别方法。然而,我很快就意识到,由于我的计算力有限,而且我需要从头开始研究和实施这些论文中的方法,时间和硬件条件都不够。我最终确定的方法与上面完全不同。

为什么选择TensorFlow.js

TensorFlow.js团队一直在进行有趣的基于浏览器的实验,以使人们熟悉机器学习的概念,并鼓励他们将其用作您自己项目的构建块。对于那些不熟悉的人来说,TensorFlow.js是一个开源库,允许用户使用Javascript直接在浏览器中定义、训练和运行机器学习模型。特别是两个演示似乎是有趣的起点 - Pacman网络摄像头控制器和可教学机器(Teachable Machine)。

虽然它们都从网络摄像头获取输入图像并根据训练数据输出预测结果,但其内部每个操作都不同:

1)“吃豆人”(Pacman)网络摄像头。它使用卷积神经网络(CNN),采用来自网络摄像头的输入图像,通过一系列卷积和最大池化层进行传递。它可以提取图像的主要特征,并根据已经训练过的例子预测其标签。由于训练是一个代价昂贵的过程,使用名为MobileNet的预训练模型进行迁移学习。该模型在1000个ImageNet类上进行了训练,但经过优化,可以在浏览器和移动应用程序中运行。

2)可教学的机器。使用kNN(k-Nearest-Neighbors)模型,它非常简单,从技术上讲,它根本不执行任何“学习”。它采用输入图像(来自网络摄像头)并通过使用相似度函数或距离度量找到最接近该输入图像的训练样本的标签来对其进行分类。

不过,在图像输入kNN之前,首先要通过名为SqueezeNet的小型神经网络,然后将该网络倒数第二层的输出作为输入进入kNN,这样读者就可以训练自己的模型。这样做的好处是,我们可以使用SqueezeNet已经学过的高级抽象内容,而不是直接从网络摄像头向kNN提供原始像素信息,从而训练表现更好的分类器。

选择使用TensorFlow.js也有其他原因:

1.进行原型设计时,无需编写任何代码。一开始通过简单地在浏览器中运行原始示例,进行早期原型设计,对我打算使用的手势进行训练,并查看系统如何执行。即使输出意味着pac-man在屏幕上移动。

2.可以使用TensorFlow.js直接在浏览器中运行模型。从可移植性,开发速度和Web界面交互的能力的角度来看,这都是巨大的优势。此外,模型可以完全在浏览器中运行,无需将数据发送到服务器。

3.由于可以在浏览器中运行,因此可以很好地与现代浏览器支持的语音到文本和文本到语音API进行交互。

4.测试、训练和调整速度更快,而这在机器学习任务中通常是一个挑战。

5.由于我没有手语数据集,并且训练示例基本上是我反复执行手势,因此使用网络摄像头来收集训练数据非常方便。

在彻底测试了这两种方法,并发现两个系统在测试中表现相当之后,我决定使用后者作为我的系统的基础,因为:

在较小的数据集上,kNN实际上可以比CNN更快/更好地执行。 当使用越来越多的示例进行训练时,这种模型会变得很吃内存,造成性能下降。但是因为我使用的数据集很小,所以这不是问题。

由于kNN并未真正从示例中学习,因此在泛化方面表现很差。 因此,完全由一个人进行的实例训练的模型的预测,在另一个人身上的适用度不高。不过,这对我来说仍然不是问题,因为训练和测试模型的只有我一个人。

工作原理

1.在浏览器中启动站点时,第一步是提供训练示例。使用网络摄像头反复捕捉自己的手势。这是个相对较快的过程,因为按住特定的捕获按钮会连续捕获帧数,直到释放按钮,使用适当的手势标记捕获的图像。我训练的系统包含14个单词,这些单词在各种组合中允许我对Alexa发出各种请求。

2.训练完成后,进入预测模式。使用来自网络摄像头的输入图像并通过分类器运行,根据上一步骤中提供的训练示例和标签手势找到其最近的答案。

3.如果结果超过某个预测阈值,就将将手势显示到屏幕的左侧。

4.接下来,使用Web Speech API进行语音合成,说出检测到的手势。

5.如果说出的单词是Alexa,它会唤醒附近的Echo扬声器并开始收听查询请求。另外值得注意的是,我设定了一个任意手势(在空中挥右拳)来表示Alexa这个词,因为美国手语中没有Alexa这个单词,反复拼写A-L-E-X-A会很烦人。

6 一旦整个手势短语完成后,我再次使用WebSpeech API来转录Echo扬声器的响应,这个扬声器响应的请求,并不知道该请求来自另一台机器。转录的响应显示在屏幕的右侧,供用户阅读。

7 再次做出唤醒手势,清除屏幕并重新开始重复查询的过程。

我在Github上传了所有代码(https://github.com/shekit/alexa-sign-language-translator)。读者可以随意使用和修改。

一些尚待完善之处

虽然系统运行情况相对较好,但确实需要一些粗略的改进,来帮助获得理想的结果并提高准确性,如:

确保没有检测到任何符号,除非出现唤醒词Alexa。

添加一个包含完整的全部类别的训练样例,将其归类为“其他”用于表示系统空闲状态(无手势的空白背景,人手臂自然下垂站立)。这可以防止错误地检测到单词。

在接受输出之前设置高阈值,以减少预测错误。

降低预测速度。控制每秒的预测量有助于减少错误的预测。

确保已在该短语中检测到的单词不再被视为新的预测。

另一个挑战是准确预测用户何时完成查询签名。这对于准确转录是必要的。如果转录提前触发(在用户完成签名之前触发),系统就会开始转录它自己的语音。否则,如果转录较晚触发。可能会导致系统错过转录Alexa的部分回答。为了克服这个问题,我实施了两种独立的技术,每种技术都有各自的优缺点:

第一个选项是在添加训练用的特定单词时将它们标记为终端单词(terminal words)。这里所说的terminal words是指用户只会在短语的末尾签名的词。例如,如果查询是“Alexa,what’s the weather?”那么,通过将“weather”标记为一个terminal word,当检测到这个词时,就可以正确地触发转录。虽然这种方法很有效,但这意味着用户必须记住在训练期间将单词标记为terminal words,并且还要假设这个词只出现在查询末尾。这意味着要重新调整你的查询,如果问“Alexa,what’s the weather in New York?”,这种方法就不管用了。我们在视频演示里使用了这种方法。

第二个选项是让用户签署一个停止词(stop-word),以便让系统知道用户已经完成了查询。一旦识别出这个停止词,系统就会触发转录。因此,用户将签署Wakeword >Query> Stopword。这种方法存在用户忘记签署停止词的风险,从而导致转录根本没有被触发。我在一个单独的github branch中实现了这种方法,你可以在其中使用唤醒词“Alexa”作为查询的bookend,比如问“Alexa, what’s the weather in New York (Alexa)?”

当然,如果有一种方法能准确区分来自内部源(笔记本电脑)的语音和来自外部源(附近的Echo)的语音,这整个问题就能解决,但这是另外一个挑战了。

接下来,我认为还有很多其他的方法能处理这个问题,你可以试着用来创建自己的项目:

Tensorflow.js也发布了PoseNet,使用它可能是一种有趣的方法。从机器的角度来看,跟踪手腕、肘部和肩膀在视频帧中的位置应该足以预测大多数单词。在拼写时,手指的位置通常最重要。

使用基于CNN的方法可能能够提高准确性,并使模型更能抵抗平移不变性。CNN还有助于更好地推广到不同的人,还可以包括保存模型或加载预训练的Keras模型的能力。这将不再需要每次重启浏览器都对系统进行训练。

考虑时间特征的一些CNN+RNN或PoseNet+RNN的组合可以提高准确率。

使用tensorflow.js中包含的更新的可重用kNN分类器。

从我第一次发布这个项目以来,就在社交媒体上获得广泛分享和报道,甚至Amazon还在Echo Show上为说话障碍的人实现了一个辅助功能(Tap to Alexa)。这实在太酷了。希望在未来, Amazon Show或其他基于摄像头和屏幕的语音助理都能加入这一功能。对我来说,可能这就是这个原型展示的最终用例了,同时也希望能够为数百万新用户开放这些设备的能力。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分