zoukankan      html  css  js  c++  java
  • 基于混合模型的语音降噪效果提升

    上篇文章(基于混合模型的语音降噪实践)实践了基于混合模型的算法来做语音降噪,有了一定的降噪效果。本篇说说怎么样来提升降噪效果。

    算法里会算每个音素的高斯模型参数,也会建一个音素分类的神经网络模型。这些都是依赖于音素对齐的,音素对齐做的越好,每个音素的高斯模型越准确,音素分类模型越收敛准确率越高,从而算法的降噪效果越好。先前做音素对齐用的是开源工具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之间。

  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/talkaudiodev/p/15024732.html
Copyright © 2011-2022 走看看