主要内容

使用深度学习网络去噪语音

这个例子展示了如何使用深度学习网络去噪语音信号。该示例比较了应用于同一任务的两种网络类型:全连接网络和卷积网络。

简介

语音去噪的目的是去除语音信号中的噪声,同时提高语音的质量和清晰度。这个例子展示了如何使用深度学习网络从语音信号中去除洗衣机的噪音。该示例比较了应用于同一任务的两种网络类型:全连接网络和卷积网络。

问题总结

考虑以下8千赫采样的语音信号。

[cleanAudio, fs] = audioread (“SpeechDFT-16-8-mono-5secs.wav”);声音(cleanAudio fs)

在语音信号中加入洗衣机的噪音。设置噪声功率使信噪比(SNR)为0 dB。

噪音= audioread (“洗衣机- 16 - 8 mono - 1000 - secs.mp3”);从噪声文件中的随机位置提取噪声段。ind = randi(numel(noise) - numel(cleanAudio) + 1,1,1);noiseSegment =噪音(ind:ind + numel(cleanAudio) - 1);speechPower =总和(cleanAudio。^ 2);noisePower =总和(noiseSegment。^ 2);noisyAudio = cleanAudio + sqrt(speakhpower /noisePower)*noiseSegment;

听嘈杂的语音信号。

声音(noisyAudio fs)

想象原始信号和噪声信号。

t = (1/fs)*(0:numel(cleanAudio) - 1);图(1)tiledlayout(2,1) nexttile plot(t,cleanAudio) title(“干净的声音”网格)noisyAudio nexttile情节(t)标题(“嘈杂的声音”)包含(“时间(s)”网格)

语音去噪的目的是去除语音信号中的洗衣机噪声,同时最小化输出语音中不需要的伪影。

检查数据集

此示例使用Mozilla Common Voice数据集的一个子集[1训练和测试深度学习网络。该数据集包含48千赫的受试者说短句的录音。下载数据集并解压缩下载的文件。

downloadFolder = matlab.internal.examples.downloadSupportFile (“音频”“commonvoice.zip”);dataFolder = tempdir;unzip(downloadFolder,dataFolder) dataset = fullfile(dataFolder,“无法推进”);

使用audioDatastore为训练集创建一个数据存储。若要以牺牲性能为代价加快示例的运行时,请设置speedupExample真正的

adsTrain = audioDatastore (fullfile(数据集,“训练”), IncludeSubfolders = true);speedupExample =真正的如果adsTrain = shuffle(adsTrain);adsTrain =子集(adsTrain 1:1000);结束

使用获取数据存储中第一个文件的内容。

[音频、adsTrainInfo] =阅读(adsTrain);

听语音信号。

声音(音频、adsTrainInfo.SampleRate)

绘制语音信号。

图(2)t = (1/ adstraaininfo . samplerate) * (0:numel(audio)-1);情节(t,音频)标题(“例如语音信号”)包含(“时间(s)”网格)

深度学习系统概述

基本的深度学习训练方案如下所示。注意,由于语音通常低于4khz,您首先将干净和噪声音频信号降低到8khz,以减少网络的计算负载。预测器和目标网络信号分别是噪声音频信号和干净音频信号的幅值谱。网络的输出是去噪后信号的幅值谱。回归网络使用预测器输入来最小化输出和输入目标之间的均方误差。使用输出幅度频谱和噪声信号的相位将去噪音频转换回时域[2].

您可以使用短时傅里叶变换(STFT)将音频转换到频域,其窗口长度为256个样本,重叠率为75%,以及一个汉明窗口。通过删除与负频率对应的频率样本(因为时域语音信号是真实的,这不会导致任何信息丢失),可以将谱向量的大小减少到129。预测器输入由8个连续的噪声STFT向量组成,因此每个STFT输出估计都是基于当前的噪声STFT和之前的7个噪声STFT向量来计算的。

STFT目标和预测

本节演示如何从一个训练文件中生成目标信号和预测信号。

首先,定义系统参数:

windowLength = 256;赢得=汉明(windowLength,“周期”);重叠=圆(0.75 * windowLength);fftLength = windowLength;inputFs = 48 e3;fs = 8 e3;numFeatures = fftLength/2 + 1;numSegments = 8;

创建一个dsp。SampleRateConverter(DSP系统工具箱)对象将48 kHz音频转换为8 kHz。

src = dsp.SampleRateConverter (InputSampleRate = inputFs OutputSampleRate = fs,带宽= 7920);

使用从数据存储中获取音频文件的内容。

音频=阅读(adsTrain);

确保音频长度是采样速率转换器抽取因子的倍数。

decimationFactor = inputFs / fs;L =地板(元素个数(音频)/ decimationFactor);音频=音频(1:decimationFactor * L);

转换音频信号到8khz。

音频= src(音频);重置(src)

从洗衣机噪声矢量中创建一个随机噪声段。

Randind = randi(numel(噪声)- numel(音频),[1 1]);noiseSegment =噪声(randind:randind + numel(audio) - 1);

在语音信号中加入噪声,使其信噪比为0 dB。

noisePower =总和(noiseSegment。^ 2);cleanPower =总和(音频。^ 2);noiseSegment = noiseSegment。* sqrt (cleanPower / noisePower);noisyAudio = audio + noiseSegment;

使用stft(信号处理工具箱)从原始和噪声音频信号中生成幅值STFT向量。

cleanSTFT = stft(音频、窗口=赢得OverlapLength =重叠,fftLength = fftLength);cleanSTFT = abs (cleanSTFT (numFeatures-1:最终,));noisySTFT = stft (noisyAudio窗口=赢,OverlapLength =重叠,fftLength = fftLength);noisySTFT = abs (noisySTFT (numFeatures-1:最终,));

从噪声STFT中生成8段训练预测信号。连续预测因子之间的重叠为7段。

noisySTFT = [noisySTFT(:,1:numSegments - 1),noisySTFT];stftSegments = 0 (numFeatures,numSegments,size(noisySTFT,2) - numSegments + 1);index = 1:size(noisySTFT,2) - numSegments + 1 stftSegments(:,:,index) = noisySTFT(:,index:index + numSegments - 1);结束

设定目标和预测指标。这两个变量的最后一个维度对应于由音频文件生成的不同预测器/目标对的数量。每个预测器是129 × 8,每个目标是129 × 1。

目标= cleanSTFT;大小(目标)
ans =1×2129 544
预测= stftSegments;大小(预测)
ans =1×3129 8 544

使用高数组提取特征

为了加快处理速度,可以使用高数组从数据存储中所有音频文件的语音段中提取特征序列。与内存中数组不同,在调用收集函数。这种延迟计算使您能够快速处理大型数据集。当您最终请求使用收集, MATLAB结合排队计算在可能的情况下,并获得通过数据的最小次数。如果您有并行计算工具箱™,您可以在本地MATLAB会话或本地并行池中使用高数组。如果您安装了MATLAB®并行服务器™,您还可以在集群上运行高数组计算。

首先,将数据存储转换为一个高数组。

T = tall(adsTrain)
使用“本地”配置文件启动并行池(parpool)…连接到平行池(工人数量:6)。T = M×1高细胞数组{234480×1双}{210288×1双}{282864×1双}{292080×1双}{410736×1双}{303600×1双}{326640×1双}{233328×1双}::::

显示显示还不知道行数(对应于数据存储中的文件数)M。M是一个占位符,直到计算完成。

从高表中提取目标和预测量STFT。此操作将创建用于后续计算的新高数组变量。这个函数HelperGenerateSpeechDenoisingFeatures控件中已突出显示的步骤STFT目标和预测部分。的cellfun命令适用于HelperGenerateSpeechDenoisingFeatures到数据存储中每个音频文件的内容。

(目标,预测)= cellfun (@ (x) HelperGenerateSpeechDenoisingFeatures (x,噪音,src), T, UniformOutput = false);

使用收集评估目标和预测指标。

(目标,预测)=收集(目标,预测);
通过1 / 1:在52秒内完成评估在1分53秒内完成

将所有特征归一化为零均值和统一标准差是一种很好的做法。

分别计算预测器和目标的均值和标准差,并用它们对数据进行归一化。

预测=猫({}):3,预测指标;noisyMean =意味着(预测(:));noisyStd =性病(预测(:));predictors(:) = (predictors(:) - noisyMean)/noisyStd;目标=猫({}):2、目标;cleanMean =意味着(目标(:));cleanStd =性病(目标(:));targets(:) = (targets(:) - cleanMean)/cleanStd;

将预测器和目标重塑为深度学习网络所期望的维度。

预测=重塑(预测、大小(预测,1),大小(预测,2),1,大小(预测,3));目标=重塑(目标1 1、大小(目标1),大小(目标2));

在培训期间,您将使用1%的数据进行验证。验证对于检测网络过度拟合训练数据的情况非常有用。

将数据随机分为训练集和验证集。

第1 = randperm(大小(预测,4));L =圆(0.99 *大小(预测,4));trainPredictors =预测(:,:,:,第1 (1:L));trainTargets =目标(:,:,:,第1 (1:L));validatePredictors =预测(:,:,:,第1 (L + 1:结束));validateTargets =目标(:,:,:,第1 (L + 1:结束));

全连通层语音去噪

首先考虑由完全连接的层组成的去噪网络。完全连接层中的每个神经元都连接到前一层的所有激活。全连接层将输入乘以一个权重矩阵,然后添加一个偏置向量。权重矩阵和偏置向量的维数由该层中的神经元数量和来自前一层的激活数量决定。

定义网络的层。指定输入大小为图片大小NumFeatures——- - - - - -NumSegments(本例中为129 * 8)。定义两个隐藏的完全连接层,每个层有1024个神经元。由于是纯线性系统,在每个隐藏的完全连接层后面都有一个整流线性单元(ReLU)层。批处理归一化层归一化输出的均值和标准差。添加129个神经元的完全连接层,然后是回归层。

layers = [imageInputLayer([numFeatures,numSegments]) fullyConnectedLayer(1024) batchNormalizationLayer reluLayer fullyConnectedLayer(1024) batchNormalizationLayer reluLayer fullyConnectedLayer(numFeatures) regressionLayer];

接下来,为网络指定培训选项。集MaxEpochs3.使网络对训练数据进行3次传递。集MiniBatchSize128这样网络就能同时观察128个训练信号。指定情节作为“训练进步”生成随迭代次数增加而显示训练进度的图。集详细的禁用将与图中显示的数据相对应的表输出打印到命令行窗口。指定洗牌作为“every-epoch”在每个历元的开始打乱训练序列。指定LearnRateSchedule“分段”每经过一定的代数(1)时,将学习率降低指定的系数(0.9)。集ValidationData到验证预测器和目标。集ValidationFrequency使验证均方误差在每个历元计算一次。本例使用自适应力矩估计(Adam)求解器。

miniBatchSize = 128;选择= trainingOptions (“亚当”...MaxEpochs = 3,...InitialLearnRate e-5 = 1,...MiniBatchSize = MiniBatchSize,...洗牌=“every-epoch”...情节=“训练进步”...Verbose = false,...ValidationFrequency =地板(大小(trainPredictors 4) / miniBatchSize),...LearnRateSchedule =“分段”...LearnRateDropFactor = 0.9,...LearnRateDropPeriod = 1,...ValidationData = {validatePredictors, validateTargets});

使用指定的训练选项和层架构训练网络trainNetwork.由于训练集很大,训练过程可能需要几分钟。下载和加载预先训练的网络,而不是从零开始训练网络,设置downloadPretrainedSystem真正的

downloadPretrainedSystem =如果downloadPretrainedSystem下载文件夹= matlab.internal.examples.downloadSupportFile(“音频”“SpeechDenoising.zip”);dataFolder = tempdir;unzip(downloadFolder,dataFolder) netFolder = fullfile(dataFolder,“SpeechDenoising”);s =加载(fullfile (netFolder“denoisenet.mat”));denoiseNetFullyConnected = s.denoiseNetFullyConnected;cleanMean = s.cleanMean;cleanStd = s.cleanStd;noisyMean = s.noisyMean;noisyStd = s.noisyStd;其他的denoiseNetFullyConnected = trainNetwork (trainPredictors、trainTargets层,选择);结束

计算网络中完全连接层的权重数。

numWeights = 0;指数= 1:元素个数(denoiseNetFullyConnected.Layers)如果isa (denoiseNetFullyConnected.Layers(指数),“nnet.cnn.layer.FullyConnectedLayer”) numWeights = numWeights + nummel (denoiseNetFullyConnected.Layers(index).Weights);结束结束disp ("权重数= "+ numWeights);
权重数= 2237440

基于卷积层的语音去噪

考虑一个使用卷积层而不是全连接层的网络[3.].二维卷积层对输入应用滑动滤波器。该层通过沿着输入的垂直和水平方向移动滤波器来卷积输入,并计算权值和输入的点积,然后添加一个偏见项。卷积层通常比全连通层包含更少的参数。

定义[中描述的全卷积网络的层3.],由16个卷积层组成。前15个卷积层为3层一组,重复5次,滤波器宽度分别为9、5、9,滤波器数量分别为18、30、8。最后一个卷积层的滤波器宽度为129和1个滤波器。在这个网络中,卷积只在一个方向上执行(沿频率维度),并且对于除第一个层外的所有层,沿时间维度的滤波器宽度设置为1。与全连接网络类似,卷积层之后是ReLu层和批归一化层。

layers =[imageInputLayer([numFeatures,numSegments]) convolution2dLayer([9 8],18,Stride=[1 100],Padding= .“相同”) repmat(...[convolution2dLayer(1[5] 30步=[100],填充=“相同”) batchNormalizationLayer reluLayer convolution2dLayer([9 1],8,Stride=[1 100],Padding=“相同”) batchNormalizationLayer reluLayer convolution2dLayer([9 1],18,Stride=[1 100],Padding=“相同”) batchNormalizationLayer reluLayer],4,1) convolution2dLayer([5 1],30,Stride=[1 100],Padding=“相同”) batchNormalizationLayer reluLayer convolution2dLayer([9 1],8,Stride=[1 100],Padding=“相同”) batchNormalizationLayer reluLayer convolution2dLayer([129 1],1,Stride=[1 100],Padding=“相同”) regressionLayer);

训练选项与完全连接网络的选项相同,除了验证目标信号的维度被排列成与回归层预期的维度一致。

选择= trainingOptions (“亚当”...MaxEpochs = 3,...InitialLearnRate e-5 = 1,...MiniBatchSize = MiniBatchSize,...洗牌=“every-epoch”...情节=“训练进步”...Verbose = false,...ValidationFrequency =地板(大小(trainPredictors 4) / miniBatchSize),...LearnRateSchedule =“分段”...LearnRateDropFactor = 0.9,...LearnRateDropPeriod = 1,...ValidationData={validatePredictors,permute(validateTargets,[3 1 2 4])});

使用指定的训练选项和层架构训练网络trainNetwork.由于训练集很大,训练过程可能需要几分钟。下载和加载预先训练的网络,而不是从零开始训练网络,设置downloadPretrainedSystem真正的

downloadPretrainedSystem =如果downloadPretrainedSystem下载文件夹= matlab.internal.examples.downloadSupportFile(“音频”“SpeechDenoising.zip”);dataFolder = tempdir;unzip(downloadFolder,dataFolder) netFolder = fullfile(dataFolder,“SpeechDenoising”);s =加载(fullfile (netFolder“denoisenet.mat”));denoiseNetFullyConvolutional = s.denoiseNetFullyConvolutional;cleanMean = s.cleanMean;cleanStd = s.cleanStd;noisyMean = s.noisyMean;noisyStd = s.noisyStd;其他的denoiseNetFullyConvolutional = trainNetwork(trainPredictors,permute(trainTargets,[3 1 2 4]),layers,options);结束

计算网络中完全连接层的权重数。

numWeights = 0;指数= 1:元素个数(denoiseNetFullyConvolutional.Layers)如果isa (denoiseNetFullyConvolutional.Layers(指数),“nnet.cnn.layer.Convolution2DLayer”) numWeights = numWeights + nummel (denoiseNetFullyConvolutional.Layers(index).Weights);结束结束disp (卷积层中的权重数=+ numWeights);
卷积层中的权重数= 31812

测试去噪网络

读入测试数据集。

adsTest = audioDatastore (fullfile(数据集,“测试”), IncludeSubfolders = true);

从数据存储中读取文件的内容。

[cleanAudio, adsTestInfo] =阅读(adsTest);

确保音频长度是采样速率转换器抽取因子的倍数。

L =地板(元素个数(cleanAudio) / decimationFactor);cleanAudio = cleanAudio (1: decimationFactor * L);

转换音频信号到8khz。

cleanAudio = src (cleanAudio);重置(src)

在这个测试阶段,你用训练阶段没有使用过的洗衣机噪音破坏语音。

噪音= audioread (“洗衣机- 16 - 8 mono - 200 - secs.mp3”);

从洗衣机噪声矢量中创建一个随机噪声段。

randind = randi(numel(noise) - numel(cleanAudio), [1 1]);noiseSegment =噪声(randind:randind + numel(cleanAudio) - 1);

在语音信号中加入噪声,使其信噪比为0 dB。

noisePower =总和(noiseSegment。^ 2);cleanPower =总和(cleanAudio。^ 2);noiseSegment = noiseSegment。* sqrt (cleanPower / noisePower);noisyAudio = cleanAudio + noiseSegment;

使用stft从噪声音频信号中生成幅值STFT向量。

noisySTFT = stft (noisyAudio窗口=赢,OverlapLength =重叠,fftLength = fftLength);noisyPhase =角(noisySTFT (numFeatures-1:最终,));noisySTFT = abs (noisySTFT (numFeatures-1:最终,));

从噪声STFT中生成8段训练预测信号。连续预测因子之间的重叠为7段。

noisySTFT = [noisySTFT(:,1:numSegments-1) noisySTFT];predictors = 0 (numFeatures,numSegments,size(noisySTFT,2) - numSegments + 1);index = 1:(size(noisySTFT,2) - numSegments + 1) predictors(:,:,index) = noisySTFT(:,index:index + numSegments - 1);结束

用训练阶段计算的均值和标准差对预测因子进行归一化。

predictors(:) = (predictors(:) - noisyMean)/noisyStd;

计算去噪后的幅值STFT预测用两个训练过的网络。

预测=重塑(预测,[numFeatures numSegments 1、大小(预测,3)));STFTFullyConnected =预测(denoiseNetFullyConnected、预测);STFTFullyConvolutional =预测(denoiseNetFullyConvolutional、预测);

用训练阶段使用的平均值和标准偏差来衡量输出。

STFTFullyConnected(:) = cleanStd*STFTFullyConnected(:) + cleanMean;STFTFullyConvolutional(:) = cleanStd*STFTFullyConvolutional(:) + cleanMean;

将单侧STFT转换为中心STFT。

STFTFullyConnected = (STFTFullyConnected。”)。* exp (1 j * noisyPhase);STFTFullyConnected =[连词(STFTFullyConnected (end-1: 1:2,:)); STFTFullyConnected);STFTFullyConvolutional =挤压(STFTFullyConvolutional)。* exp (1 j * noisyPhase);STFTFullyConvolutional =[连词(STFTFullyConvolutional (end-1: 1:2,:)); STFTFullyConvolutional);

计算去噪后的语音信号。istft执行逆STFT。利用带噪声的STFT向量的相位重构时域信号。

denoisedAudioFullyConnected = istft (STFTFullyConnected窗口=赢,OverlapLength =重叠,fftLength = fftLength ConjugateSymmetric = true);denoisedAudioFullyConvolutional = istft (STFTFullyConvolutional窗口=赢,OverlapLength =重叠,fftLength = fftLength ConjugateSymmetric = true);

绘制干净、噪声和去噪的音频信号。

t = (1 / fs) *(0:元素个数(denoisedAudioFullyConnected) 1);图(3)tiledlayout(4,1) nexttile plot(t,cleanAudio(1:numel(denoisedAudioFullyConnected))) title(“干净的演讲》网格)nexttile情节(t, noisyAudio(1:元素个数(denoisedAudioFullyConnected)))标题(《吵闹的演讲》网格)denoisedAudioFullyConnected nexttile情节(t)标题(去噪语音(全连通层)网格)denoisedAudioFullyConvolutional nexttile情节(t)标题(去噪语音(卷积层)网格)包含(“时间(s)”

绘制干净、噪声和去噪的谱图。

h =图(4);tiledlayout (4,1) nexttile光谱图(fftLength cleanAudio,赢,重叠,fs);标题(“干净的演讲》网格)nexttile光谱图(noisyAudio赢,重叠,fftLength, fs);标题(《吵闹的演讲》网格)nexttile光谱图(denoisedAudioFullyConnected赢,重叠,fftLength, fs);标题(去噪语音(全连通层)网格)nexttile光谱图(denoisedAudioFullyConvolutional赢,重叠,fftLength, fs);标题(去噪语音(卷积层)网格)p = get (h,“位置”);集(h,“位置”,[p(1) 65 p(3) 800]);

听那嘈杂的讲话。

声音(noisyAudio fs)

从具有完全连接层的网络中收听去噪后的语音。

声音(denoisedAudioFullyConnected fs)

收听来自卷积层网络的去噪语音。

声音(denoisedAudioFullyConvolutional fs)

听干净的演讲。

声音(cleanAudio fs)

可以通过调用来测试数据存储中的更多文件testDenoisingNets.该函数生成上面突出显示的时域和频域图,并返回干净的、有噪声的和去噪的音频信号。

[cleanAudio, noisyAudio denoisedAudioFullyConnected denoisedAudioFullyConvolutional] = testDenoisingNets (adsTest、denoiseNetFullyConnected denoiseNetFullyConvolutional, noisyMean, noisyStd, cleanMean, cleanStd);

实时应用程序

上一节中的程序将噪声信号的整个频谱传递给预测.这不适用于需要低延迟的实时应用程序。

运行speechDenoisingRealtimeApp举例说明如何模拟一个流媒体、实时版本的去噪网络。该应用程序使用完全连接层的网络。音频帧长度等于STFT跳大小,即0.25 * 256 = 64个样本。

speechDenoisingRealtimeApp启动一个设计用于与模拟交互的用户界面(UI)。UI使您能够调优参数,结果立即反映在模拟中。您还可以启用/禁用操作去噪输出的噪声门,以进一步降低噪声,以及调整噪声门的攻击时间、释放时间和阈值。你可以听嘈杂的,干净的或去噪的音频从UI。

该范围绘制干净,噪声和去噪信号,以及噪声门的增益。

参考文献

[1]https://voice.mozilla.org/en

[2]“基于深度学习的语音去噪实验”,刘丁,Paris Smaragdis, Minje Kim, INTERSPEECH, 2014。

[3]“基于全卷积神经网络的语音增强”,Park Se Rim, Jin Won Lee, INTERSPEECH, 2017。

另请参阅

功能

相关的话题

Baidu
map