通往低于 10% 字词错误率的旅程

在 Mozilla,我们相信语音界面将成为未来人们与设备交互的重要方式。今天,我们很高兴地宣布我们开源语音识别模型的初始版本,以便任何人都可以开发引人入胜的语音体验。

Mozilla 研究院的机器学习团队一直在开发一个开源自动语音识别引擎,该引擎模仿了百度发布的 Deep Speech 论文 (12)。从一开始,主要目标之一就是使转录的字词错误率低于 10%。我们已经取得了巨大进展:我们在 LibriSpeech 的 test-clean 集上的字词错误率为 6.5%,这不仅实现了我们的初始目标,而且让我们接近人类水平的表现。

这篇文章概述了团队的工作,并以对拼图的最后一块——CTC 解码器的更详细解释结束。

架构

Deep Speech 是一种端到端的可训练、字符级、深度循环神经网络 (RNN)。用更通俗的话来说,它是一个具有循环层的深度神经网络,它接收音频特征作为输入并直接输出字符——音频的转录。它可以使用从头开始的监督学习进行训练,无需任何外部“智能来源”,例如音素到音位转换器或对输入进行强制对齐。

This animation shows how the data flows through the network. Data flows from the audio input to the feature computation, through three initial feed forward layers, then through a bidirectional RNN layer, and finally through the final softmax layer, where a character is predicted.

此动画展示了数据如何在网络中流动。实际上,我们不是单独处理音频输入的切片,而是同时处理所有切片。

 

该网络有五层:输入被馈送到三个全连接层,然后是双向 RNN 层,最后是全连接层。隐藏的全连接层使用 ReLU 激活。RNN 层使用具有 tanh 激活的 LSTM 单元。

网络的输出是随时间推移的字符概率矩阵。换句话说,对于每个时间步,网络都会为字母表中的每个字符输出一个概率,它代表该字符对应于音频中此时所说内容的可能性。 CTC 损失函数 (PDF 链接) 同时考虑了音频与转录的所有对齐方式,使我们能够最大程度地提高预测正确转录的概率,而无需担心对齐。最后,我们使用 Adam 优化器 进行训练。

数据

监督学习需要数据,大量数据。训练像 Deep Speech 这样的模型需要数千小时的标记音频,获取和准备这些数据的工作量可能与实现网络和训练逻辑一样多,甚至更多。

我们首先下载了免费提供的语音语料库,例如 TED-LIUMLibriSpeech,,以及获取了付费语料库,例如 FisherSwitchboard。我们用 Python 为不同的数据集编写了导入器,这些导入器将音频文件转换为 WAV,分割音频并清理掉不必要的字符,例如标点符号和重音符号。最后,我们将预处理后的数据存储在 CSV 文件中,这些文件可用于将数据馈送到网络。

使用现有的语音语料库使我们能够快速开始研究模型。但为了获得出色的结果,我们需要更多的数据。我们必须有创造力。我们认为,这种类型的语音数据可能已经存在于人们的档案中,所以我们联系了公共电视台和广播电台、大学的语言学习部门,以及任何可能拥有标记语音数据可供分享的人。通过这种努力,我们能够将训练数据量增加一倍以上,这现在足以训练一个高质量的英语模型。

拥有一个高质量的语音语料库公开可用不仅有助于推进我们自己的语音识别引擎。它最终将促进广泛的创新,因为开发人员、初创公司和世界各地的研究人员可以使用它来训练和试验针对不同语言的不同架构和模型。它可以帮助那些无力支付数千小时的训练数据(几乎所有人)的民主化深度学习。

为了构建一个免费、开源且足够大以创建有意义产品的语音语料库,我们与 Mozilla 的开放式创新团队合作,推出了 Common Voice 项目,以收集和验证来自世界各地志愿者的语音贡献。今天,该团队正在将大量语音数据发布到 公共领域。在 Open Innovation Medium 博客 上了解更多关于该版本的信息。

硬件

Deep Speech 拥有超过 1.2 亿个参数,训练如此庞大的模型是一项非常计算密集型的任务:如果你不想永远等待结果,你需要大量的 GPU。我们研究过在云端训练,但这在经济上不可行:如果你进行大量训练,专用硬件很快就能收回成本。云端是进行快速超参数探索的好方法,所以要记住这一点。

我们最初使用一台运行四个 Titan X Pascal GPU 的机器,然后又购买了两台服务器,每台服务器都配备了 8 个 Titan XP。我们将这两台 8 GPU 机器作为集群运行,较旧的 4 GPU 机器独立运行,以运行较小的实验和测试代码更改,这些更改需要比我们的开发机器更大的计算能力。这种设置相当高效,对于我们的大型训练运行,我们可以从零开始在大约一周内获得一个良好的模型。

使用 TensorFlow 设置分布式训练是一个艰巨的过程。虽然它拥有所有可用深度学习框架中最成熟的分布式训练工具,但让它真正无错误地工作并充分利用额外的计算能力却很棘手。我们目前的设置之所以能够正常工作,要归功于我的同事 Tilman Kamp 的出色努力,他忍受了与 TensorFlow、Slurm, 甚至 Linux 内核的漫长战斗,直到我们让一切都正常运行。

将所有内容整合在一起

此时,我们有两篇论文来指导我们,一个基于这些论文实现的模型,以及由此产生的数据和训练过程所需的硬件。事实证明,复制一篇论文的结果并不那么简单。绝大多数论文都没有指定它们使用的所有超参数,如果它们确实指定了,也只是指定了一部分。这意味着你必须花费大量的时间和精力进行超参数搜索,才能找到一套好的值。我们最初使用随机和直觉混合选择的测试值,甚至与论文中报道的值相差甚远,可能是由于架构上的细微差异——例如,我们使用了 LSTM (长短期记忆) 单元,而不是 GRU (门控循环单元) 单元。我们花了大量时间对 dropout 比例进行二进制搜索,降低了学习率,改变了权重初始化的方式,还尝试了不同的隐藏层大小。所有这些更改都让我们非常接近我们想要的低于 10% 字词错误率的目标,但还没有达到。

我们的代码中缺少一个重要的优化:将我们的语言模型集成到解码器中。CTC (连接主义时间分类) 解码器的工作原理是,获取模型输出的概率矩阵,并遍历它,根据概率矩阵寻找最有可能的文本序列。如果在时间步长 0 时,字母“C”是最有可能的,在时间步长 1 时,字母“A”是最有可能的,在时间步长 2 时,字母“T”是最有可能的,那么由最简单的解码器给出的转录将是“CAT”。这种策略称为贪婪解码。

A cat with icons of pause buttons where its paws would be.

这是一种将模型输出的概率解码为字符序列的相当不错的方法,但它有一个主要的缺陷:它只考虑网络的输出,这意味着它只考虑来自音频的信息。当同一音频具有两个同样可能的转录(想想“new”与“knew”,“pause”与“paws”)时,模型只能猜测哪一个是正确的。这远非最佳:如果一个句子的前四个词是“the cat has tiny”,我们可以相当肯定第五个词是“paws”,而不是“pause”。回答这类问题是语言模型的工作,如果我们能将语言模型集成到我们模型的解码阶段,我们就能得到更好的结果。

当我们第一次尝试解决这个问题时,我们在 TensorFlow 中遇到了几个障碍:首先,它没有在 Python API 中公开其波束评分功能(可能是出于性能方面的考虑);其次,CTC 损失函数输出的对数概率是(曾经是)无效的

我们决定通过构建类似于拼写检查器的东西来解决这个问题:遍历转录并查看我们是否可以进行一些小的修改来增加该转录是有效英语的可能性,这取决于语言模型。这在纠正输出中的少量拼写错误方面做得相当不错,但随着我们越来越接近我们的目标错误率,我们意识到这还不够。我们必须硬着头皮写一些 C++。

使用语言模型进行波束评分

将语言模型集成到解码器中,涉及每次评估对转录的添加时查询语言模型。回到前面的例子,当查看是否要在“the cat has tiny”之后选择“paws”还是“pause”作为下一个词时,我们会查询语言模型,并将该分数用作权重来对候选转录进行排序。现在我们可以利用来自音频和我们的语言模型的信息来决定哪个转录更有可能。该算法在 Hannun 等人发表的这篇论文 中进行了描述。

幸运的是,TensorFlow 在其 CTC 波束搜索解码器上有一个扩展点,允许用户提供自己的波束评分器。这意味着你只需要编写查询语言模型的波束评分器,然后将其插入即可。对于我们的情况,我们希望该功能公开给我们的 Python 代码,因此我们也将其作为自定义 TensorFlow 操作公开,可以使用 tf.load_op_library 加载。

让所有这些与我们的设置一起工作需要相当多的努力,从与 Bazel 构建系统搏斗数小时,到确保所有代码都能以一致的方式处理 Unicode 输入,以及调试光束评分器本身。该系统需要相当多的部分协同工作

  • 语言模型本身(我们使用 KenLM 来构建和查询)。
  • 我们词汇表中所有单词的 字典树
  • 一个字母文件,它将网络输出的整数标签映射到字符。

虽然添加这么多活动部件确实使我们的代码更难修改和应用于不同的用例(如其他语言),但它也带来了巨大的好处:我们在 LibriSpeech 的测试清理集上的词错误率从 16% 降至 6.5%,这不仅实现了我们的初始目标,而且使我们接近人类级别的性能(根据 Deep Speech 2 论文,为 5.83%)。在一台 MacBook Pro 上,使用 GPU,该模型可以在大约 0.3 倍的实时因子下进行推理,而在仅使用 CPU 时,大约为 1.4 倍。(1 倍的实时因子意味着你可以在 1 秒内转录 1 秒的音频。)

从初始发布我们的模型开始,这是一段令人难以置信的旅程!将来,我们希望发布一个足够快可以在移动设备或 Raspberry Pi 上运行的模型。

如果这种类型的作品对你来说很有趣或有用,请查看 我们在 GitHub 上的仓库 和我们的 Discourse 频道。我们有一个不断壮大的贡献者社区,我们很高兴帮助你为你的语言创建和发布模型。

关于 Reuben Morais

Reuben Morais 是 Mozilla 机器学习团队的高级研究工程师。他目前专注于缩小机器学习研究与现实世界应用之间的差距,为用户带来保护隐私的语音技术。

更多 Reuben Morais 的文章…


21条评论

  1. Hugo

    非常棒的文章,感谢开发这个语音识别模型。
    把我们所有的声音都发送到 Google/Apple/Microsoft 服务器上,这非常令人毛骨悚然,希望我们能够开始构建不依赖于它们的软件,这要归功于这个框架。这是一项非常重要的技术,我很高兴我们现在拥有一个开源解决方案,感谢你!

    2017年11月29日 10:49

  2. Charles Pritchard

    对“Project DeepSpeech”的开发进行了强有力的总结,它是一个开源的语音到文本实现,以及 Common Voice 项目,一个公共领域的语音识别数据语料库。

    Mozilla 研究机器学习团队的故事从一个使用现有的现代机器学习软件的架构开始,然后训练一个深度递归神经网络,从任何地方获取标注的语音语料库,并随后创建 Common Voice 项目,使开发人员更轻松地完成此步骤。

    通过实现来自几篇关于语音到文本的论文的研究,Mozilla 向其他人展示了数据科学工作是什么样子的,并且使其能够被广泛的人访问,将一年的开发工作总结成一个有文档记录的、可复制的实验,供任何对机器学习软件感兴趣的开发人员使用。

    我非常感谢他们做出的认真开发选择,围绕构建一个可读的仓库,同时支持各种硬件;这个项目和这篇文章都是一个很好的研究案例。

    2017年11月29日 21:37

  3. hdnzkwk

    你好。我有一个好主意:你可以在用户设备上使用 WebSpeech 生成带标记的语音,使用用户可用的各种语音合成引擎(尤其是在 Android 上)。你不需要安装或购买它们,只需实现一个 API,允许使用 WebAudio 处理 WebSpeech,以及一个页面从服务器请求文本,朗读文本,保存带有时间的音频,并将音频发送回服务器。

    2017年11月30日 03:40

    1. Reuben Morais

      这绝对是一个值得探索的领域。在这种情况下,必须谨慎处理人工数据,因为模型可能无法从人工数据推广到真实的人类语音。

      2017年12月4日 07:58

  4. joe

    真棒的东西。我要和同事分享这篇文章,让他们更好地理解这项工作所需的努力。我很好奇用多大的团队做这件事花了多长时间?感谢分享!

    2017年11月30日 17:53

    1. Reuben Morais

      我们 4 人的团队(前 6 个月有 5 人)花了不到一年的时间。

      2017年12月4日 07:56

  5. Jaromir

    是否可以从 tatoeba 放入语音?
    这是一个很好的数据

    2017年11月30日 22:34

  6. Vivek Tyagi

    太棒了,Mozilla 语音团队。你们是语音技术的现代先驱,并将它带给了大众。非常感谢你们的开源语音语料库!

    2017年12月1日 22:44

  7. Mike Nelson

    同意。绝对很棒的工作!其他的选择都是基于云的,这意味着我们不仅依赖于 Google/Apple/Microsoft/IBM,而且在大多数情况下还需要付费。如果高质量的语音识别可以在移动设备上使用开源免费模型离线运行,那就太棒了。

    2017年12月2日 12:03

    1. Lesław

      我正在做一个类似的项目。在接下来的 3 到 6 个月内,应该为 Julius 准备一个高质量的声学和语言模型。这一切都要感谢 Mozilla :)

      2017年12月6日 01:46

  8. Ben

    所以,我读了所有这些,其中很多对我来说目前是无法理解的,因为它充满了术语,我发现我有两个未得到解答的问题

    首先,使用这个结果可以创建一台不连接 LAN 或 WAN 的单机语音识别引擎吗?

    其次,当你说它是在“Python”中时,不幸的是,这不再是确定的。Python 2 和 Python 3 在源代码上不兼容。你使用了哪个 Python 版本?

    如果这是一个独立的引擎,或者是一个可以从相同的来源产生的引擎的核心,那么我超级兴奋,非常感谢你。如果不是……好吧,已经有一些发送数据的引擎……而我不会使用它们。:)

    2017年12月2日 13:48

    1. Reuben Morais

      是的,这个模型可以用来做离线语音识别。目前,我们的代码需要 Python 2.7 进行训练,但如果你只是想使用预训练模型,我们提供了 Python 2.7、3.4、3.5 和 3.6 的包。

      2017年12月4日 07:54

      1. Ben

        唯一能想到的词是“太棒了”。:)

        2017年12月4日 15:36

  9. foucault vincent

    Reuben,非常感谢你的辛勤工作
    干得好!!

    2017年12月3日 11:35

  10. Praveen Yadav

    Mozilla 做得太棒了,尤其是 Reuben。

    只是好奇,对 librispeech 训练进行多少轮迭代才能将 WER 降至 6%?

    2017年12月5日 10:20

    1. Reuben Morais

      我不记得具体数字了。在 10 到 15 轮迭代之间。

      2017年12月5日 10:49

  11. Michaela Merz

    很棒的第一步(第二步……第三步?)。我一直在努力让智能设备摆脱它们的“网桥”服务器,以便能够直接在我的 WiFi 环境中控制它们。由于大多数设备使用 ESP8266 芯片,因此这并不太复杂。到目前为止,我仍然必须使用 Alexa 来进行语音识别——但希望不久之后就不需要了。

    一些对未来的建议

    ——能够训练应用程序的单词。我们当然不需要整个数据库来识别物联网环境中常用的单词;
    ——直接麦克风录音;
    ——唤醒词集成。我目前正在使用 kit.ai,它可以进行训练,并且对开发人员免费使用;

    再次——祝贺。我一直在玩现在的原型,迫不及待地想看到这项开发达到一些早期的生产里程碑。

    祝大家节日快乐:D

    Michaela

    2017年12月7日 16:08

  12. Amit

    你好,Reuben,

    你和你的团队做得太棒了。你能分享一下你们团队用于训练的内容量吗?

    2017年12月11日 03:15

    1. Reuben Morais

      使用了大约 3000 小时的语音。

      2017年12月11日 04:27

  13. Borislav Zlatanov

    感谢你做出了这个令人难以置信的贡献,包括算法和开放数据。

    我想知道你们用来计算词错误率的具体方法。似乎各种文章中都提到了词错误率百分比(例如,Google 达到了这个百分比,而 Microsoft 达到了那个百分比),但没有人说明他们计算词错误率的方法。没有说明步骤或工具。

    如果你能提供你们计算 WER 的分步流程,将非常有用。谢谢!

    2017年12月11日 14:31

    1. Reuben Morais

      在这里:https://github.com/mozilla/DeepSpeech/blob/9c338b76dba4f8816f129e0c5219aacace93b022/util/text.py#L85-L108

      2017年12月11日 15:39

本文的评论已关闭。