上篇文章(基于混合模型的语音降噪实践)实践了基于混合模型的算法来做语音降噪,有了一定的降噪效果。本篇说说怎么样来提升降噪效果。
算法里会算每个音素的高斯模型参数,也会建一个音素分类的神经网络模型。这些都是依赖于音素对齐的,音素对齐做的越好,每个音素的高斯模型越准确,音素分类模型越收敛准确率越高,从而算法的降噪效果越好。先前做音素对齐用的是开源工具speech-aligner,怎么样让音素对齐做的更好呢?自己做不太现实(不仅周期长,而且相关专业知识积累有限),还得依赖专业工具。调研下来MFA(Montreal-Forced-Aligner,也是基于kaldi的)是目前用的最多的音素对齐工具,且有大厂(比如微软)在用,质量有保证,同时它支持中文和自己训练模型。它不仅支持GMM-HMM,还支持DNN-HMM(官网文档这么说),用DNN-HMM的语音识别效果是好于GMM-HMM的,直观上觉得基于DNN-HMM的音素对齐应该是好于基于GMM-HMM的。我用的MFA是最新版本2.0,训练集还是thchs30(数据集一样,方便跟先前的结果比较),经过5步(monophone->triphone->lda->sta1->sat2)训练后得到了模型,基于这个模型得到了每个文件的音素对齐信息。奇怪的是训练过程中没有经过DNN训练这一步,文档中明明说支持的呀,调查后发现2.0已不支持DNN训练,1.1是支持的,网站上的文档没有更新,作者只是在回答问题时确认了,并且给了理由,如下图:
可以看出是作者不确信DNN训练能否提升对齐质量才在新版本里删掉DNN训练的,同时他认为提升对齐的准确率应该来自其他方面。这与直观的理解有出入,我想他们肯定做过很多次实验才有这个结论的,不然不会在新版本里删掉DNN训练。
MFA和speech-aligner都基于kaldi。MFA有哪些训练步骤比较清晰,可以基于自己的数据集生成模型。而speech-aligner不知道有哪些训练步骤(没调查到相关信息, 后来用以前做kaldi时生成的工具解析了它提供的模型文件,可以确认的是GMM),且只能用它提供的模型,不支持自己训练生成模型。看上去MFA中文音素分类更合理些,不像speech-aligner只根据声韵母分,比如MFA中ting1分成 t i1 ng三个音素,而speech-aligner分成t ing1两个音素。 基于上面的比较,我觉得用MFA(基于大数据集训练自己的模型)音素对齐准确率是优于speech-aligner的。
有了每个语音文件的音素对齐信息后,还像先前那样把属于同一个音素的所有帧放在一起算高斯模型参数,也得到了每个语音文件每帧所属音素label的CSV文件,用来训练音素分类网络模型(模型训练时网络结构、层数等均不改变,唯一改变的是每个语音文件每帧所属音素label的CSV文件)。训练后验证集和测试集下的准确率分别是0.79和0.76,较先前用speech-aligner都有0.1左右的提高。从这结果可以看出MFA的音素对齐效果是好于speech-aligner的。拿一批先前的噪声为NOISEX-92中的white白噪声的语音文件做降噪(这些语料在用speech-aligner时也用过,有降噪后的音频,方便比较),同样用PESQ来做评估,与用speech-aligner时降噪MOS均值提升如下表:
从上表看出,在低SNR(0和5 dB)时,用两种对齐工具MOS值没明显变化,估计是噪声较大,经过两种音素分类网络后音素判别准确率差不多。在高SNR(10和15 dB)时,用MFA的MOS值相比用speech-aligner提升明显。高SNR时,噪声较小,经过MFA对齐的音素分类网络后音素判别准确率高一些,从而也使降噪效果好些。
通过使用新的音素对齐工具明显提升了高SNR下的降噪效果,低SNR下的没提升。怎么样才能让低SNR下的降噪效果也提升呢?我想到了前面做KWS关键词识别时用到的加噪训练方法。语音识别中通过给干净语音叠加噪声去训练,能显著提升带噪语音的识别率。因为用于降噪的文件中的噪声是NOISEX-92中的white白噪声,所以训练时叠加噪声也用这种典型噪声,分别以4种SNR(0/5/10/15 dB)叠加到干净语音中看效果。这里把干净语音和噪声按指定的SNR做叠加简单说一下。以干净语音为基准,保持不变,改变噪声的能量从而满足SNR的要求,然后叠加到干净语音上得到带噪语音。SNR公式是SNR = 10*log10(C/N),其中C和N分别表示干净语音和期望噪声的平均功率。变形得到N = C/10(SNR/10))。假设真实噪声平均功率是P,幅值为n,期望噪声的幅值为x,由于平均功率和幅值是平方的关系,所以N/P = x2/n2,从而求得期望噪声的幅值 。假设原干净语音的幅值为c,所以最终叠加后的语音幅值为 (c + x)。写成python代码大致如下图所示:
训练后得到了新的音素分类网络模型,不管是验证集还是测试集,准确率都比加噪前有所下降。 基于新的模型对先前的带噪语音降噪,发现低SNR下的MOS值有0.1左右的提升,高SNR下的提升不明显,具体如下表:
上表验证了通过加噪训练能提升低SNR下的降噪效果。这里只是实验,只加了一种要降噪的带噪语音里的噪声。实际中各种噪声都有,需要把干净语音叠加多种噪声去训练。为了再提升降噪效果,我又尝试了加大音素分类模型的参数个数(用的是CNN网络,加大网络的层数),从两倍到四倍都试验过,均不能明显提升MOS均值(MOS值提升都小于0.05)。这说明加大模型参数对降噪没什么效果。
总结下,为了提升降噪效果,我做了三种尝试,分别是用更好的音素对齐工具使音素对齐的更准确、加噪训练音素分类网络模型和加大音素分类模型的参数,前两种分别对高SNR和低SNR的语音降噪有效果,第三种没什么效果。加上混合模型的算法本身,各种SNR下的语音降噪MOS值提升在0.4~0.5之间。