RNNoise: Learning Noise Suppression
原文链接:https://people.xiph.org/~jm/demo/rnnoise/![Banner](https://i-blog.csdnimg.cn/blog_migrate/12336c34f6be775f42bce4dc630e6a84.jpeg)
上图显示了前后音频(移动鼠标时)噪声抑制的频谱图。
深层次学习是一种新思想的新版本:人工神经网络。虽然自六十年代以来一直存在,近年来有什么新的呢?
我们现在知道如何使它们比两个隐藏层更深
我们知道如何使复发网络在过去很长时间记住模式
我们有实际训练他们的计算资源
循环神经网络(RNN)在这里非常重要,因为它们可以对时间序列建模,而不是仅仅考虑输入和输出帧。这对噪声抑制特别重要,因为我们需要时间来获得良好的噪声估计。很长时间以来,RNN的能力受到很大的限制,因为它们长期不能保存信息,并且由于当通过时间反向传播时涉及的梯度下降过程是非常低效的(消失的梯度问题)。这两个问题都通过发明门控单元来解决,如长期记忆(LSTM),门控循环单元(GRU)及其许多变体。
![recurrent units](https://i-blog.csdnimg.cn/blog_migrate/498b163c61a3d4348d4cecc976fef017.png)
将简单的循环单元与GRU进行比较。区别在于GRU的r和z门,这使得有可能学习更长期的模式。两者都是基于整个层的先前状态和输入计算的软开关(0到1之间的值),具有S形激活功能。当更新门z在左边时,状态可以在很长一段时间内保持恒定,直到一个条件使z转向右边。
混合方法
由于深入学习的成功,现在在整个问题中抛出深层神经网络是很受欢迎的。这些方法称为端到端 - 这是神经元一直下降。端对端方法已被应用于语音识别和语音合成一方面,这些端到端系统已经证明了深层神经网络可以有多强大。另一方面,这些系统有时可能是次要的,而且在资源方面是浪费的。例如,噪声抑制的一些方法使用具有数千个神经元和数千万个权重的层来执行噪声抑制。缺点是不仅运行网络的计算成本,还有模型本身的大小,因为您的磁带库现在有数千行代码以及几十兆字节(如果不是更多)的神经元权重。
单位定义问题
为了避免产生大量的输出 - 因此大量的神经元 - 我们决定不直接使用样本或频谱。相反,我们考虑遵循巴克量表的频段,一个与我们感知到的声音相匹配的频率比例。我们使用总共22个频段,而不是480(复杂)频谱值,我们将不得不考虑。
![frequency bands](https://i-blog.csdnimg.cn/blog_migrate/279af0bc8c230da7859e5351e45e8eed.png)
Opus乐队的布局与实际的Bark比例。对于RNNoise,我们使用与Opus相同的基本布局。由于我们与乐队重叠,Opus乐队之间的界限成为重叠的RNNoise乐队的中心。由于耳朵在那里的频率分辨率较差,频段的频率较高。在低频下,乐队更窄,但并不像巴克比例那样窄,因为我们没有足够的数据来做出很好的估计。
当然,我们无法从22个频段的能量重建音频。我们可以做的是计算一个应用于每个频带信号的增益。您可以将其视为使用22频段均衡器,并快速更改每个频段的电平,以便衰减噪声,但让信号通过。
使用每频带增益有几个优点。首先,它使得一个更简单的模型,因为有更少的乐队计算。第二,它不可能产生所谓的音乐噪声伪影,其中只有单个音调在其邻居被衰减的同时才能通过。这些文物在噪音抑制中很常见,相当烦人。要是足够宽阔的乐队,我们要么让整个乐队穿过,要么全部剪下来。第三个优点来自于我们如何优化模型。由于增益总是在0和1之间,所以简单地使用S形激活函数(其输出也在0和1之间)来计算它们确保我们永远不会做一些非常愚蠢的事情,比如添加不在第一名。
对于输出,我们还可以选择整流的线性激活函数来表示在0和无穷大之间的dB的衰减。 为了更好地优化训练中的增益,损失函数是应用于提高到功率α的增益的均方误差(MSE)。 到目前为止,我们发现α= 0.5在感知上产生最好的结果。 使用α→0将等效于最小化对数光谱距离,并且是有问题的,因为最佳增益可以非常接近零。
由于我们计算的输出是基于22个频段,所以输入频率分辨率更高是没有意义的,所以我们使用相同的22个频带将频谱信息提供给神经网络。因为音频具有巨大的动态范围,所以计算能量的日志而不是直接馈送能量要好得多。而在我们这样做的时候,它永远不会用DCT来去除相关的特征。所得到的数据是基于Bark量表的倒谱,其与语音识别中非常常用的Mel-Frequency倒谱系数(MFCC)密切相关。
除了我们的倒谱系数,我们还包括:
前6个系数跨帧的第一和第二个导数
音调周期(1 /基频)
6个乐队的音高(声音强度)
一种特殊的非平稳性值,可用于检测语音(但超出本演示范围)
这使得神经网络共有42个输入特征。
深层建筑
我们使用的深层建筑灵感源于传统的噪音抑制方法。大部分工作是由3个GRU层完成的。下图显示了我们用于计算频带增益的层次,以及架构如何映射到噪声抑制中的传统步骤。当然,像神经网络通常情况一样,我们没有实际的证据证明网络正在使用它的层次,而是我们尝试的拓扑结构比其他人更好的事实使得认为它的行为与我们设计的一样它。
![network topology](https://i-blog.csdnimg.cn/blog_migrate/eb154f59db1865e0b3eb9fd72907eed0.png)
这些都是关于数据的
有时甚至深层神经网络也可能很笨。 他们非常擅长他们所了解的知识,但是他们可能会对他们所知道的投入产生惊人的错误。 更糟糕的是,他们真的很懒惰的学生。 如果他们可以在训练过程中使用任何漏洞,以避免学习困难,那么他们会。 这就是为什么训练数据的质量至关重要。
一个广为流传的故事是,很久以前,一些军队的研究人员正试图训练一个神经网络来识别在树上伪装的坦克。 他们拍摄了有和没有坦克的树木,然后训练了一个神经网络来识别那些有坦克的人。 网络成功超越了预期! 只有一个问题。 由于有坦克的照片是在多云的天气下拍摄的,而没有坦克的照片是在阳光明媚的日子拍摄的,所以网络真正学到的是如何从阳光灿烂的日子开始阴天。 虽然研究人员现在意识到了这个问题,并避免了这样明显的错误,但它们的更微妙的版本仍然会发生(而且在过去已经发生了)。
在噪声抑制的情况下,我们不能仅仅收集可用于监督学习的输入/输出数据,因为我们很少同时获得干净的语音和嘈杂的语音。 相反,我们必须从清晰的语音和噪音的单独记录中人为地创建数据。 棘手的部分是获得各种各样的噪音数据,以增加语音。 我们还必须确保覆盖各种录音条件。 例如,仅在全频段音频(0-20 kHz)下训练的早期版本将在8 kHz低通滤波时失效。
与语音识别常见的不同,我们选择不将倒谱平均归一化应用于我们的特征,并保留代表能量的第一个倒谱系数。 因此,我们必须确保数据包括所有现实级别的音频。 我们还对音频应用随机滤波器,使系统对各种麦克风频率响应(通常由倒谱平均归一化处理)具有鲁棒性。
由于我们的频带的频率分辨率太粗,无法滤除音调谐波之间的噪声,所以我们使用基本的信号处理。 这是混合方式的另一部分。 当有相同变量的多个测量值时,提高精度(降低噪声)的最简单方法就是计算平均值。 显然,只是计算相邻音频样本的平均值不是我们想要的,因为它会导致低通滤波。 然而,当信号是周期性的(例如有声语音)时,我们可以计算由音调周期偏移的采样的平均值。 这导致梳状滤波器,其使音调谐波通过,同时衰减它们之间的频率 - 噪声在哪里。 为了避免信号失真,对于每个频带,梳状滤波器被独立地应用,并且其滤波器强度取决于音调相关性和神经网络计算的频带增益。
我们目前使用FIR滤波器进行音高滤波,但也可以(并在TODO列表中)使用IIR滤波器,如果强度太高,则会导致更高的失真风险,从而产生较大的噪声衰减。
从Python到C
神经网络的所有设计和训练都是使用真棒的Keras深度学习库在Python中完成的。由于Python通常不是实时系统的首选语言,所以我们必须在C中实现运行时代码。幸运的是,运行神经网络比培训一个简单得多,所以我们只需要实现feed前向和GRU层。为了更轻松地将重量适合于合理的占地面积,我们在训练期间将权重的大小限制为+/- 0.5,这使得可以使用8位值轻松存储它们。所得到的模型仅适用于85 kB(而不是将重量存储为32位浮点数所需的340 kB)。
C代码可以使用BSD许可证。尽管在撰写本演示文稿时,代码尚未优化,但它在x86 CPU上的运行速度比实时性要快60倍。它甚至比Raspberry Pi 3上的实时速度快7倍。具有良好的矢量化(SSE / AVX),应该可以使其比现在快四倍。
给我看样品!
好的,这很好,所有,但它实际上是如何发声的?以下是RNNoise的一些实例,可以消除三种不同类型的噪音。在训练期间都不使用噪音和干净的讲话。
Suppression algorithm
- No suppression
- RNNoise
- Speexdsp
Noise level (SNR)
- 0 dB
- 5 dB
- 10 dB
- 15 dB
- 20 dB
- Clean
Noise type
- Babble noise
- Car noise
- Street noise
Evaluating the effect of RNNoise compared to no suppression and to the Speexdsp noise suppressor. Although the SNRs provided go as low as 0 dB, most applications we are targeting (e.g. WebRTC calls) tend to have SNRs closer to 20 dB than to 0 dB.
那么你应该听什么呢?听起来很奇怪,你不应该期待着增加清晰度。人类非常善于理解噪音中的语音,增强算法(特别是不允许前瞻性地去除噪声的算法)只能破坏信息。那么为什么我们这样做呢?为了质量增强的言论听起来更不方便,可能导致听众疲劳减轻。
实际上,还有几个实际上可以帮助清晰度的情况。第一种是视频会议,当多个扬声器混合在一起时。对于该应用,噪声抑制可防止所有非活动扬声器的噪声与主动扬声器混合,从而提高质量和可读性。第二种情况是当语音通过低比特率编解码器时。那些倾向于降低嘈杂的语音,而不是干净的语音,所以删除噪音可以使编解码器做得更好。
尝试在你的声音!
对上述样品不满意? 您可以从麦克风实际录制,并使您的音频实时降噪(近)。 如果您点击下面的按钮,RNNoise将在浏览器中执行Javascript中的噪声抑制。 该算法实时运行,但我们有意延迟几秒钟,以便更容易听到去噪输出。 确保戴耳机,否则您会听到反馈回路。 要开始演示,请选择“无抑制”或“RNNoise”。 您可以在两者之间切换以查看抑制的效果。 如果您的输入没有足够的噪音,您可以通过点击“白噪声”按钮人工添加。
如果你认为这项工作是有用的,那么有一个简单的方法来帮助它更好的完成!所需要的只是一分钟的时间。点击下面的链接,让我们从你所在的地方记录一分钟的噪音。该噪声可用于改善神经网络的训练。作为一个副作用,这意味着当您使用它进行视频会议(例如WebRTC)时,网络将会知道您有什么样的噪音,并可能会做得更好。我们对任何可以使用语音进行通信的环境感兴趣。这可以是你的办公室,你的车,在街上,或任何你可以使用你的手机或电脑的地方。
捐一分钟的噪音!
从哪里来
如果您想更多地了解RNNoise的技术细节,请参阅本文(尚未提交)。该代码仍然在积极的开发(没有冻结的API),但已经在应用程序中可用。它目前的目标是VoIP /视频会议应用程序,但通过一些调整,它可能适用于许多其他任务。一个明显的目标是自动语音识别(ASR),虽然我们只能去噪嘈杂的语音并将输出发送到ASR,但这是次优的,因为它丢弃了有关过程的固有不确定性的有用信息。当ASR不仅知道最可能干净的讲话,而且还可以依赖于这一估计值时,这是更有用的。 RNNoise的另一个可能的“重新定位”是为电动乐器创造一个更加智能的噪音门。所有它应该采取的是良好的训练数据和一些代码的变化,将一个Raspberry Pi变成一个真正好的吉他噪音门。任何人我们还没有考虑过许多其他潜在的应用程序。
如果您想对此演示进行评论,可以在这里进行。
-Jean-Marc Valin(jmvalin@jmvalin.ca)2017年9月27日
其他资源
代码:RNNoise Git仓库(Github镜像)
J.-M。 Valin,A Hybrid DSP / Deep Learning Approach to Real-time Full-Band Speech Enhancement,arXiv:1709.08243 [cs.SD],2017。
让 - 马克的博文发表评论
致谢
特别感谢Michael Bebenita,Thomas Daede和Yury Delendik的帮助。感谢Reuben Morais对Keras的帮助。