基于网页的语音命令识别

作者:smus(原文链接

翻译:刘通

原标题:Web-based voice command recognitions

 

上一次我们将音频buffer转成了图像,这一次,我们将采取这些图像,并使用deeplearn.js训练一个神经网络。结果是一个浏览器上的demo,你可以说出“yes”或者“no”的指令,然后像这样实时的显示出识别结果:

recognition1

虽然它离完美还差的很远,但却是在网上进行各种音频识别的一个很好的起点。现在让我们深入了解一下这是如何工作的。

快速入门:培训和测试一个指令识别器

下面是如何训练yes/no分类器的方法:

1. 跳转到模型训练页。这会花一点时间来下载训练数据(yes/no)。

2. 点击训练按钮,你会看到一个显示训练进度的图表。一旦你准备好了(会花一点时间,具体时间长短取决于你的硬件),停止训练,并且点击保存权重(文件)按钮。这会下载一个JSON文件。

recognition2

3. 然后进入推导demo页,点击加载权重(文件)按钮,并且选择已下载的JSON文件来加载训练后的模型。

4. 点击开关,对麦克风进行访问授权,并且试着说“yes”或“no”。您将在页面底部显示的麦克风电平和置信度等级。

recognition3

以上是如何训练示例的说明。如果你对此感兴趣,就请继续下面的内容。

数据预处理及加载

训练一个神经网络需要大量的训练数据。在实际情况中,可能需要数百万个示例,但是我们将要使用到的数据集要比现代标准规范的小,只有大概65,000个含标签示例。每一个示例都是一个独立的wav文件,其文件名中包含了标签。

加载每个训练wav文件作为一个独立的请求是非常慢的。每个请求的开销很小,但是除服几千次时,耗费的时间就很多了。一个简单的优化使加载数据变得更快的方法是将所有具有相同标签的示例放入到同一个长音频文件中。解码音频文件是很快的,所以将长文件分割成一秒长一个的缓冲区。进一步优化的方式是使用压缩的音频格式,比如mp3。scripts/preprocess.py会为你做这个级联,产生非常好的结果

当我们对原始音频“注水”之后,我们将原始数据的缓冲区处理为特征。我们使用在上一篇文章中提到的音频特征提取器来完成这项工作,该工具使用原始音频,并成成一个log-mel谱图。这相对来说较慢,并且占了加载数据集的大部分时间。

训练模型的考虑

对于yes/no识别器,我们只有两个关心的命令,“yes”和“no”。但是我们也想要察觉到其他语音以及静默段。我们把一组随机话语作为“other”类别。这个例子也是由预处理脚本生成的。

因为我们正在处理的是真正的麦克风,所以我们从来都不会听到真正的静默段。相反,“silence”是由于糟糕的麦克风质量所产生的某种程度上的环境噪声。幸运的是,训练数据还包括背景噪声,我们将这些噪音与各种训练样例混合在一起。我们还生成一组静音示例,其中只包含了背景噪音。一旦我们准备好了样品,我们就可以生成最终的声谱图作为我们的输入。

为了生成这些最终的声谱图,我们需要决定缓冲区和跳变的长度。合理的缓冲区长度为1024,跳变长度为512。由于我们正在处理的是16000Hz采样率的音频,所以窗口持续时间约为60ms,且每隔30ms采样一次。

一旦我们拥有了标记后的声谱图,我们就需要将输入和标签转为深度学习序列。标签字符串“yes”,“no”,“other”和“silence”将被one-hot编码为四个整数的Array1Ds,意思是“yes”对应于[1,0,0,0],而“否”为[0,1,0,0]。来自特征提取器的声谱图需要被转换成Array3D,其可以作为模型的输入。

我们正在训练的模型由两个卷积层和一个完全连接层组成。我直接从deeplearn.js的MNIST例子中取得了这个架构,根本不是为了处理这个声谱图而定制的。因此,性能与现有技术的语音识别会差的远。我相信如果我们按照这篇文章中的做法来做会得到更好的结果。现实世界中的语音识别器可能根本不使用卷积,而是选择更适合处理时间序列数据的LSTM

最后,我要告诉机器学习框架如何训练模型。从ML的角度说,我们需要设置超参数,其中包括设置学习速率(每个步骤中要有多少个梯度)和batch的大小(一次取多少个示例)。然后我们就有了这样一个对比:

recognition4

在训练过程中,梯度下降算法试图使成本最小化,就像蓝线展示的那样。我们也用橙色来绘制正确度。我们使用测试集中的随机自己,因为推导需要时间,我们希望尽快进行训练。

在我们对测试准确性满意了之后,就可以保存模型的权重并使用他们来推断结果了。

保存和加载模型权重

模型由其体系结构和其承载节点的权重来定义。权重是模型训练过程中学到的价值,并不是所有的节点都有权重。ReLUs和扁平化节点就没有。但卷积和完全连接节点既有权重(weights)又有偏差(bias)。这些权重是任意形状的张量。为了保存和加载模型,我们需要能够保存图形及其权重。

因为这些原因,保存和加载模型是十分重要的:

1. 训练模型需要时间,所以你可能想要训练一下,把权重保存下来,休息一下,然后从你刚才停下来的地方继续。而这也就是所谓的检查点。

2. 为了推断,有一个可以加载和运行的独立模型是很有用的。

在撰写本文时,deeplearn.js还没有设置序列化模型和模型权重的工具。对于这个例子,我已经实现了一种加载和保存权重的方法,假设模型体系结构本身是硬编码的。GraphSaverLoader类可以从本地存储或文件中进行保存和加载。最终,我们将需要一种不菲吹灰之力的方式来保存和加载模型及其相应的权重。我对于机器学习未来的发展感到非常的兴奋。

 

填写常用邮箱,接收社区更新

WebRTC 中文社区由

运营