【问题标题】:NLMS Algorithm is not converging, multiple implementation resulting equallyNLMS 算法不收敛,多重实现结果均等
【发布时间】:2015-09-02 06:43:33
【问题描述】:

标准化最小均方算法用于数字滤波,它基本上试图模仿“未知”滤波器,因此它们的差异(被认为是误差)趋于零。收敛的“因素”是误差一开始会很高,随着算法的不断运行,误差会越来越小。

NLMS 和 LMS(它的后继者)的唯一区别是 NLMS 对过滤器的入口进行了归一化处理,因此对高输入功率并不容易。

wiki 页面中的两种算法都有公式:https://en.wikipedia.org/wiki/Least_mean_squares_filter,这与我的实现类似。

我目前正在使用自适应设备,因此我可以将白噪声输入过滤到低通滤波器中,并尝试调整我的算法系数以模仿低通,它在 matlab 中实现:

clear all;close all;clc;

fid = fopen('ruidoBranco.pcm', 'rb');
s = fread(fid, 'int16');
fclose(fid);

itera = length(s);
L = 50;
passo = 0.00000000001;
H = passaBaixa(L,1000,2);
W = zeros(L,1);
y = zeros(itera,1);
sav_erro = zeros(itera,1);

for i=(L+1):itera,
    D=0;
    Y=0;
    for j=1:(L),
        Y = Y + W(j,1)*s(i-j,1);
        D = D + H(j,1)*s(i-j,1);
    end
    erro = D-Y;
    k=passo*erro;
    for j=1:(L),
        W(j,1) = W(j,1)+(k*s(i-j,1)/(s(i-j,1)^2+0.000001));
    end
    sav_erro(i,1) = (erro);
end
subplot(2,1,1);
plot(sav_erro);
subplot(2,1,2);
plot(W);
hold on;
plot(H,'r');

fid = fopen('saidaFIR.pcm', 'wb');
fwrite(fid,sav_erro,'int16');
fclose(fid);

“passaBaixa”函数就是我之前说的低通滤波器:

function H = passaBaixa(M,FC,op)
    iteracoes = M;
    FS=8000;
    FC=FC/FS;
    M=iteracoes;
    H = zeros(iteracoes,1);
    for i=1:iteracoes,                                          
        if(i-M/2==0)
           H(i,1)=2*pi*FC;
        else
            H(i,1)=sin(2*pi*FC*(i-M/2))/(i-M/2);
        end
        if(op==1)
            H(i,1)=H(i,1);
        else if (op==2)
                 H(i,1) = H(i,1)*(0.42-0.5*cos(2*pi*i/M)+0.08*cos(4*pi*i/M));
            else
                 H(i,1)=H(i,1)*(0.54-0.46*cos(2*pi*i/M));
            end
        end
    end
    soma = sum(H);
    for i=1:iteracoes,
        H(i,1)=H(i,1)/soma;
    end
end

文件 ruidoBranco.pcm 只是一个由 80.000 个样本生成的白噪声。

得到的结果如下:

其中上图是误差,下图是低通滤波器(红色)和“自适应”算法滤波器(蓝色)的脉冲响应。

它没有收敛,它应该看起来像这样:

如您所见,上图收敛到几乎为 0 的误差,而下图不再有蓝色,因为它在红色之后(因为它几乎完美地调整了过滤器的系数)

我想知道我的实现是否存在任何明显的错误,也许这可能是未来有类似错误的人的参考。

【问题讨论】:

    标签: algorithm matlab signal-processing


    【解决方案1】:

    解决方法是我没有为算法使用正确的乘法,它需要是一个点积,而不是简单的 2 的幂

    所以修复是在 for 循环中:

    dotprod = dot(s(i-j,1),s(i-j,1));    
    for j=1:(L),
        W(j,1) = W(j,1)+(k*s(i-j,1)/dotprod);
    end
    

    【讨论】:

      猜你喜欢
      • 2019-12-01
      • 2014-12-19
      • 1970-01-01
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-28
      • 1970-01-01
      相关资源
      最近更新 更多