如何用TensorFlow设计一套系统,让亚马逊的语音助理Echo能“看懂”手语的

电子说

1.2w人已加入

描述

编者按:“如果语音是计算的未来,那么对于不能说话或有听力障碍的人该怎么办?”本文作者Abhishek Singh就描述了它是如何用TensorFlow设计一套系统,让亚马逊的语音助理Echo能“看懂”手语的。

几个月前,当我躺在床上时,一个想法突然闪过:“如果语音是计算的未来,那么对于不能说话或有听力障碍的人该怎么办?”不知道为什么会产生这种想法,我本身说话和听力都没有问题,身边也没有这样的残疾人士,而且我也没有语音助手。也许是最近关于语音助手的文章太多了,或者是各大公司之间关于语音助手的竞争太多,亦或者总是在朋友的家里看到语音助手的身影。有了想法之后,我就立刻行动起来。

最终我完成了这个项目,让亚马逊的语音助手Echo能够对美国手语(ASL)做出更准确的反应(手语也分很多种,这里用的是美国手语)。下面的视频能更好地帮助大家看看这个项目的效果,并且我希望这一方法能让大家将关注重点从技术要素上转移到人类要素上,也就是说要更看重技术能否像人一样为我们提供服务。

本文将展示系统背后的原理,另外这里有一个Demo可以自己玩一下:shekit.github.io/alexa-sign-language-translator/

早期研究

在我刚有想法的时候,我就对这一项目所需要的元素有了大致掌握:

一个能读懂手语的神经网络(即将视频中的手势转换成文字)

一个文本转语音系统,可以将转换过后的动作读给语音助手Alexa听(注:Alexa是Echo音箱的语音服务,二者是硬件和系统的关系)

一个语音转文字系统,将Alexa的回复展示给用户

一个可以运行该系统的设备(电脑或平板),以及一个可以互动的Echo音箱

一个交互界面

一开始,我花了大量时间尝试各种神经网络架构,想找出最合适的一个。以下是几个备选项:

由于手语有视觉和时间两方面要考虑,所以我最初想结合一个CNN和RNN,其中最后一个卷积层的输出可以输入到RNN中作为序列。之后我发现长期循环卷积网络可以做到这一点。

利用一个3D卷积网络,其中的卷积可以用到三个维度中,前两个维度用于图像分辨,第三个维度处理时间。然而这些网络需要大量内存,我是想在我用了7年的MacBook Pro上训练的。

与传统的视频流在CNN上一帧一帧地训练不同,我只在光流表示上进行训练,这样会在两个连续帧之间显示出明显的动作变化。我设想的是,可以在其中对动作进行编码,从而创造一款通用的手语模型。

利用双流CNN,其中空间流是单帧(RGB),时间流则用光流表示。

在之后的研究中,我发现了好几篇用到上述方法做视频动作识别的论文。但是我发现不仅是计算力限制了我的操作,而且我自己的能力的确无法从零开始实现这些方法。所以无奈之下只好放弃。

最终我使用的方法完全不同。

进入TensorFlow.js的世界

TensorFlow.js团队既推出了针对机器学习专业的人的程序,也对那些不熟悉机器学习的人提供了开源库,可以自己用JavaScript定义、训练并运行机器学习模型。作为入门可以试试这两个有趣的Demo:

Pacman Webcam Controller:storage.googleapis.com/tfjs-examples/webcam-transfer-learning/dist/index.html

Teachable Machine:teachablemachine.withgoogle.com/

虽然它们都将摄像头捕捉到的图像作为输入,并根据训练数据输出一个预测,但是二者内部是截然不同的。

Pacman Webcam:它所运用的卷积神经网络将输入其中的图片通过一系列卷积传递到最大池化层。这一过程可以提取图像的主要特征,并且根据训练样本预测它的标签。由于训练过程成本较高,它是用的一个名为MobileNet的预训练模型进行的迁移学习。该模型在1000个ImageNet类别中进行的训练,之后进行了优化。

Teachable Machine:它所用到的是kNN(k-Nearest-Neighbours),这种方法非常简单,基本不需要任何学习。捕捉到网络摄像头的图像后,它会对其打上标签进行分类(用训练样本中相似的函数或距离矩阵)。但是在输入到kNN之前,图像会首先通过一个名为SqueezeNet的小型神经网络。将网络倒数第二层的输出输入到kNN中,然后训练自己的类别。这样做的好处是,不直接将原始像素值输入到kNN中,而是用SqueezeNet所学的高层次表示来训练分类器。

现在你可能会想,那手语表示所用的时间怎么办?这些系统都是一帧一帧地输入图像,同时在下一帧之前作出预测。查看RNN的时机是否过早了?有必要真正了解手势吗?在我为了这个项目学习手语时,我发现当你想要用手语表示的时候,不同话语之间,开始和结束的手势以及手的位置都是不同的。跟人交流的时候可能需要看完整个动作才知道说的是什么,但是机器只需要看懂开头和结尾即可。所以我决定只让机器辨认最后的动作。

决定使用TensorFlow.js也有其他几个好处:

不用写代码我就能用这些demo做出原型。刚开始时,我只是在浏览器上简单运行原始案例,让后用手势训练它们,看看系统的表现。

我能直接用TensorFlow.js在浏览器上运行,虽然这个很大,但是不用向服务器发送数据即可直接运行模型。

由于可以在浏览器上运行,我可以用语音转文字和文字转语音API进行交互。

测试、训练、调整的速度都很快。

由于没有手语数据集,所以我要重复地做很多动作用来训练,电脑摄像头能很方便地采集数据。

测试了上述两种方法后(Pacman和Teachable Machine),我发现二者都能胜任。但是我最终决定用Teachable Machine,因为:

在小数据集上,kNN比CNN表现得更好更快。如果训练样本很多的话,kNN可能会变慢,性能也会下降。但是我的数据集很小。

由于kNN并不需要学习,所以它们泛化的能力很弱。所以模型做出的预测并不能很好地进行迁移。不过这对我来说也不是什么障碍,因为模型的训练和测试都是用我自己的手语动作。

TensorFlow.js团队开源了一个简单的模型——boilerplate,对我很有帮助。(github.com/googlecreativelab/teachable-machine-boilerplate)

运行情况

从宏观角度,系统从头到尾的运行原理如下:

将系统安装到浏览器后,第一步是提供训练样本。也就是要用摄像头捕捉你的每个手语动作。

训练完成工,就进入预测模式。将输入图像经过分类器,找到与它最相近的训练模型并打标签。

如果通过了预测,屏幕左侧就会显示标签。

之后用Web Speech API进行语音合成,说出检测出的标签。

说出“Alexa”唤醒Echo。注意,这里我创建了一个随机动作来表示“Alexa”这个单词。

完成整个手语动作后,我用Web Speech API将Echo的回复进行转换。转换后的文字出现在屏幕右侧让用户阅读。

重新唤醒Alexa,清除屏幕进行再次对话。

虽然系统运行的不错,它还需要一些改进,例如:

必须等到Alexa被唤醒后才开始检测手语动作。

加入更多的训练样本。

将阈值提高,防止出现预测错误。

减少预测率,避免在最大帧率时出现预测,控制每秒预测的量有助于减少错误。

保证每个单词都被检测到。

由于手语通常忽略冠词,而是依赖语境。所以我训练了包括特殊单词的模型,其中加入了特殊的冠词或介词,例如天气等等。

另一个挑战就是在用户完成手语后要精确地做出预测,这就需要精确的文字语音转换。如果转换得太快,系统就会开始转换自己的语音,太慢的话就会错过Echo的回复。为了解决这个问题,我用了两种独立的技术,每种都有自己的优缺点:

首先就是在训练时将特定的词语作为结束单词。例如如果用户说:“Alexa, what’s the weather?”我们将”the weather”作为结束词,如果系统检测到它,就会触发正确的转换过程。这个方法不错,但是这也需要用户记住训练时候那个结束词是什么。

第二种方法是让用户特地做出一个结束词的动作,让系统知道他说完了。所以整个对话过程中,用户要先唤醒,再说自己的问题,最后做结束动作。这种方法的缺点是,用户可能会忘了做结束动作。

我认为还有很多种方法可以实现这个项目,如果你想试试不妨参考以下建议:

TensorFlow.js还发布了PoseNet,这也是个有趣的工具。从机器的角度来看,追踪手腕、手肘、肩膀的位置,比预测话语更有效。

利用基于CNN的方法可能会提高准确度,并且模型会更稳定。

CNN+RNN或PoseNet+RNN的结合有可能会让精确度提高一大截哦。

利用新的kNN分类器。

降低网络的复杂性,利用简单架构创造模型,一定会让该项目得到快速应用。我的目标并不仅仅是解决手语到文字的难题,而是用一种全面的设计进行对话,让机器学习落到实处,从而激励人们在这个领域进行更多思考。

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

全部0条评论

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

×
20
完善资料,
赚取积分