RNNoise: Learning Noise Suppression(深度学习噪声抑制)(2)

1、 网络结构

网络结构
原始语音模型
RNNoise分为三层嵌入式网络,由全连接层,GRU网络构成
包含了215个units
4个hidden layers
Largest:96 units

GRU VS LSTM

GRU容易执行去噪任务,需要更少的计算资源,较少参数,训练快
RNN可以对时间序列建模,而噪声抑制需要在时域获得良好的噪声估计。很长时间以来,RNN的能力受到很大的限制,因为它们长期不能保存信息,并且由于当通过时间反向传播时涉及的梯度下降过程是非常低效的(消失的梯度问题)。门控单元(LSTM和GRU)解决了简单RNN不能长期保存信息和梯度消失的问题。与简单RNN相比,GRU有两个额外的门。复位门决定是否将状态(记忆)用于计算新状态,而更新门决定状态将根据新输入改变多少。当更新门关闭时,GRU可以长时间地记住信息。

网络顺序

首先对语音数据分帧,每帧10ms,160个数据点,对这个数据点提取42维的特征,输入网络,经过第一层GRU,输出24维与原始输入42维concate进入第二层GRU,输出48维与原始输入concate,进入第三层GRU,最终输出22维的点(每个点是语音还是噪声的概率),将这个结果作为权重对原始输入进行加权,最后拟合出256的频谱用于恢复时域语音信号,这个信号就是降噪后的结果。

2、 数据集

需要准备好训练集,在本项目中可以很简单的准备训练数据和label,只需要两个长文件,一个是仅包含噪声的文件,noise_only.wav,一个是仅包含语音的文件speech_only.wav,在训练开始前,需要将噪声加入到语音,合成含噪语音noisy.wav,
将这个noisy.wav的特征送入到网络。
噪声Noise_only:人群噪声(30min),街道汽车噪声(20min),路面噪声(10min), 16k
语音Speech_only : Haitian_data 60min, 16k (可以尝试各种开源语音数据集,讯飞有很多)
需要去噪的语音Noisy:lumian,tingche, gaojia 16k(用于测试)

3、 更改采样率

工程的音频限制为单声道,16bit,采样率48k,需要修改训练数据
**下载语音转换工具:

~/rnnoise$ git clone https://github.com/smallmuou/wavutils

~/rnnoise/wav$ ../wavutils/bin/wavinfo speech_only.wav**

运行以下脚本

xx@ubuntu::~/bin$ wavinfo no_music.wav

+++++++++++++++++++++++++
+ WAVEFORM INFORMATION +
+++++++++++++++++++++++++
Audio Format: 1 (0x0001)
Num Channels: 1 (0x0001)
Sample Rate: 16000 (0x00003e80)
its Per Sample: 16 (0x0010)
PCM Size: 140592720 (0x08614650)

xx@ubuntu:~/bin$ pcm2wav 1 48000 16 noise_only.pcm noise_only.wav

+++++++++++++++++++++++++
+ WAVEFORM INFORMATION +
+++++++++++++++++++++++++
Audio Format: 1 (0x0001)
Num Channels: 1 (0x0001)
Sample Rate: 48000 (0x0000bb80)
Bits Per Sample: 16 (0x0010)
PCM Size: 365189238 (0x15c45876)

4、 训练过程

(1) step 1 转换为pcm格式

~/rnnoise/wavutils/bin/wav2pcm speech_only.wav speech_only.pcm
~/rnnoise/wavutils/bin/wav2pcm noise_only.wav noise_only.pcm
~/rnnoise/wavutils/bin/wav2pcm speech_noise.wav speech_noise.pcm

**[INFO] Successfully convert noise_only.pcm to noise_only.wav.**

(2) step2 提取特征

Ubuntu下,运行在RNNoise工程目录中的src中的compile.sh,编译denoise.c :获得denoise_training可执行文件。在Windows下直接生成解决方案,debug文件夹有denoise.exe 可执行文件。
需要修改stdout->fout,否则会在shell里乱输出乱码。修改原始count=50000000,太多帧运行时间是10倍,但是我们没有10倍的语音,效果不明显。修改为500000。

~/rnnoise/src/   $./compile.sh
~/rnnoise/src/denoise_training speech_only.pcm noise_only.pcm output.f32
-> "matrix size: 500000 x 87" 

输入noise_only.wav和speech_only.wav,利用denoise.c 提取特征,设定500000帧,可读取83分钟音频,获得文件output.f32,包含500000x87的矩阵,占用170M,运行时间大约为5分钟

(3) step 3 数据转换

RNNoise的training文件夹下,利用bin2hdf5.py 将二进制数据转换成h5数据。方便在python下训练。文件大小170M几乎不变,仅 增加2k。

 ~/rnnoise/training/bin2hdf5.py output.f32 500000 87 denoise_data9.h5

(4) step 4 训练神经网络

在tensorflow框架下,keras和theano作为后端训练一个包含三个GRU的神经网络。输入42维特征,输出22维的G(类似概率值的增益系数,用于调整原始输入的频谱数据)。500000帧的数据分为250个sequence,每个sequence包含2000个42维的数据。其中225份为训练集,25份为验证集。迭代120次。每次迭代用时40秒。整个过程80分钟。输出权重文件newweights9i.hdf5,占用1079k。

~/rnnoise/training/rnn_train.py
-> denoise_data9.h5 -> newweights9i.hdf5

Using Theano backend.
Build model...
Loading data...
done.
250  sequences
250 train sequences.  x_shape = (250, 2000, 42)  y_shape = (250, 2000, 22)
Train...
Train on 225 samples, validate on 25 samples
Epoch 1/120
32/225 [===>..........................] - ETA: 39s - loss: 9.1596 - denoise_output_loss: 0.6047 - vad_output_loss: 6.22

(5)step 5 获取权重数据

~/rnnoise/training/dump_rnn.py newweights9i.hdf5 rnn_data.c rnn_data.h

将训练获得的权重数据写入到工程文件rnn_data.c,rnn_data.h
但是作者给出的 dump_rnn.py 无法运行,需要修改python文件并添加函数,得到修改后的dump_rnn.py
++++++++++++++++++++++++++++++++++++

from keras.constraints import Constraint
def mean_squared_sqrt_error(y_true, y_pred):
return K.mean(K.square(K.sqrt(y_pred) - K.sqrt(y_true)), axis=-1)

+++++++++++++++++++++++++++++++++++++

def my_crossentropy (y_true, y_pred):
return K.mean(2*K.abs(y_true-0.5) * K.binary_crossentropy(y_pred, y_true), axis=-1)

++++++++++++++++++++++++++++++++++++++

def mymask (y_true):
return K.minimum(y_true+1., 1.)

++++++++++++++++++++++++++++++++++++++

def msse (y_true, y_pred):
return K.mean(mymask(y_true) * K.square(K.sqrt(y_pred) - K.sqrt(y_true)), axis=-1)

++++++++++++++++++++++++++++++++++++++

def mycost(y_true, y_pred):
return K.mean(mymask(y_true) * (10K.square(K.square(K.sqrt(y_pred) - K.sqrt(y_true))) + K.square(K.sqrt(y_pred) - 
K.sqrt(y_true)) + 0.01K.binary_crossentropy(y_pred, y_true)), axis=-1)

+++++++++++++++++++++++++++++++++++++++

def my_accuracy (y_true, y_pred):
		return K.mean(2*K.abs(y_true-0.5) * K.equal(y_true, K.round(y_pred)), axis=-1)

+++++++++++++++++++++++++++++++++++++++

class WeightClip (Constraint):
		def init (self, c=2,name='WeightClip'):
		self.c = c

+++++++++++++++++++++++++++++++++++++++

获得rnn_data.c, 409kb,rnn_data.h 1kb。

4、 降噪

用新的rnn_data.c和rnn_data.h替换工程文件rnn_data.c, rnn_data.h。
在denoise_demo.c 里修改音频输入为48k,输出为16k。(用一个简单的方法每三个点取一个值,进行降采样)
将if training =1,denoise.c的if training=0。
然后make clean,make。
得到降噪后的wav文件。5分钟的语音降噪过程为1分钟。

Ubuntu:rnnoise_demo speech_noise.pcm denoised_speech_noise.pcm
Windows:denoise.exe speech_noise.pcm denoised_speech_noise.pcm。

参考文档

RNNoise: Learning Noise Suppression
https://people.xiph.org/~jm/demo/rnnoise/

1、 The code: RNNoise Git repository :
https://git.xiph.org/?p=rnnoise.git;a=summary
(Github mirror:https://github.com/xiph/rnnoise/)
2、J.-M. Valin, A Hybrid DSP/Deep Learning Approach to Real-Time Full-Band Speech Enhancement, arXiv:1709.08243 [cs.SD], 2017.
https://arxiv.org/pdf/1709.08243.pdf
3、 Jean-Marc’s blog post for comments
https://jmvalin.dreamwidth.org/15210.html

  • 6
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 34
    评论
评论 34
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值