您的位置:首页 > 编程语言 > MATLAB

音频噪声抑制(4):普通最小均方误差(LMS)算法

2016-12-13 12:54 232 查看

引言

前面讲了基于Weiner滤波器的噪声抑制方法。

Reivew:用维纳滤波器实现噪声抑制

维纳滤波器有一些假设条件,比如信号平稳(这就导致解方程算滤波器系数的时候,自相关矩阵与绝对时间无关)、噪声和有用信号不相关…

其实,这些条件在实际中并不是那么容易满足的。

因此,用维纳滤波器来实现信号去噪,效果不是特别理想。

于是就有人提出自适应滤波器,“自动”去更新滤波器的系数,使它自己去“适应”信号的一些特性。

自适应滤波器有许多种,这里挑最简单的基于“最小均方误差”准则的自适应滤波器来讲了。

LMS滤波器基本原理

原理的话,每一本现代信号处理的书上都讲得很清楚了。
归根结底:这是一个需要“训练”(或者说“学习”)的滤波器,在“学习”的过程中,希望把滤波器的输出与期望信号(训练信号)之差,作为算法的反馈,
不断地更新滤波器的系数,以使得在某种意义下,实现最优滤波。
LMS,顾名思义,最小均方误差。
另外,利用梯度下降法,可以简单地求出目标函数(均方误差是关于滤波器系数w)的极值。
一系列简单推导,可得出LMS算法。



w是滤波器系数,
x是滤波器输入,
d是训练信号,
x和w的内积(滤波器与输入信号的卷积)是滤波器的输出,
u是步长(1个正数)。

理论上,u越小,最终求出的极值点结果越精确,但所需要达到极值点的时间就变长了。
有最优的一个u,但其实吧,我感觉也就是理论上提供一种可能性,意思是,
u在每一次迭代的过程中,在理论上都有个最优值。
但实际上,为了求最优值,又需要一大堆的已知条件,而这些条件其实并不是那么好“知道”;
就算是知道了,求最优的u,也会耗费大量的时间。
所以,自己看着办了……
有资料建议,



滤波器阶数,初值,自己设置了。有可能陷入局部极值。这不知道了。试,效果出来就OK了。
Tail & error。

举例:噪声抑制

1. LMS的训练过程。

%% LMS滤波去噪
% 作者:qcy
% 版本号:v1.0
% 版本说明:本M文件提供训练阶段。
% 时间:2016年10月29日19:02:44

% 好像提升并不是很明显啊!!
% why...?????? and 如何改进???
%【问】 是不是不应该用非语音段进行滤波???

close all;clear; clc;

%% 导入音频
filedir=[];                             % 设置路径
filename='bluesky1.wav';                % 设置文件名
fle=[filedir filename];                 % 构成完整的路径和文件名
[s, fs] = audioread(fle);               % 读入数据文件

s=s-mean(s);                            % 消除直流分量
s=s/max(abs(s));                        % 幅值归一
N=length(s);                            % 语音长度
time=(0:N-1)/fs;                        % 设置时间刻度
SNR = 5;                                % 设置信噪比
r2=randn(size(s));                      % 产生随机噪声
b=fir1(32,0.5);                         % 设计FIR滤波器,代替H
r21=filter(b,1,r2);                     % FIR滤波
[r1,r22]=add_noisedata(s,r21,fs,fs,SNR);% 产生带噪语音,信噪比为SNR 

%% 训练阶段
h_length = 100;
h = zeros(h_length,1); % 滤波器的初始化
miu = 1e-4;

y_out = zeros(size(s));
Ntimes = 3;
err2 = zeros(length(s)*Ntimes,1);
counter = 1;
% 开始滤波
for kk = 1:Ntimes
for k = h_length : N
idx = k: -1 :(k-h_length+1);
r1_in_sub = r1(idx);
filter_out = h.' * r1_in_sub;
y_out(k) = filter_out;
dk = s(k);
err = dk - filter_out;
err2(counter) = err^2;
h = h + miu * err * r1_in_sub;
counter = counter + 1;
end
end

% sound(s,fs);
% sound(r1,fs);
% sound(y_out,fs);

%% 作图
figure
plot(err2);
grid on;
title('均方误差');

figure;
subplot 311; plot(time,s,'k'); ylabel('幅值')
ylim([-1 1 ]); title('原始语音信号');
subplot 312; plot(time,r1,'k'); ylabel('幅值')
ylim([-1 1 ]); title('带噪语音信号');
subplot 313; plot(time,y_out,'k');
ylim([-1 1 ]); title('LMS滤波输出语音信号');
xlabel('时间/s'); ylabel('幅值')

尽管听起来,似乎有一定的改良,但是去噪效果还是不明显!
我暂时不知道为什么。而且,很多书上都回避了普通LMS来去噪的例子。
连去噪前后信号波形图都没有给出。更不要说什么均方误差了。

我在想,是不是在训练的过程中,整个语音信号中,说话不能有停顿啊?
从我的均方误差的图中,似乎看得出来,似乎有一个逐渐变小的过程,但是突然又会变大。
假设,期望信号中,有非常微弱的部分(说话间隙),基本就是0了。
这时滤波器为了让均方误差最小,是不是系数要全为0啊?
那这样的训练过程……
是不是最终导致去噪效果不佳的原因?





所以,是不是还需要做一个端点检测,把真正的语音段全部提取出来,以此作为训练信号呢?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  matlab 去噪 filter 算法 LMS