Engee 文档
Notebook

自适应信号滤波的LMS和NLMS算法比较

自适应滤波是数字信号处理的关键技术,在降噪、回声消除、系统识别等诸多领域都有应用。 在本文中,我们将介绍两种经典的自适应滤波算法-Lms(最小二乘)及其修改NLMS(归一化LMS),使用EngeeDSP包在Engee语言中实现。
Lms(Least Mean Squares)是一种随机梯度算法,可使所需信号与自适应滤波器输出之间的均方根误差最小化。 更新权重的基本方程:

w(n+1)=w(n)+μ·e(n)·x(n)

哪里:

-w(n)是步骤n处滤波器权重的向量
-μ为适配步骤
-e(n)是误差(期望和实际输出之间的差)
-x(n)为输入向量

NLMS算法

NLMS(归一化LMS)是对LMS的修改,其中适应步骤由输入信号功率归一化:

w(n+1)=w(n)+(μ/(x∈(n)x(n)+ε))·e(n)·x(n)

其中ε是一个小常数,以防止除以零。

第一个例子的分析

第一个代码比较具有变化幅度的信号上的LMS和NLMS:

``'茱莉亚
x_window=0.05randn(102410)。重复(0.5。+0.5罪。(2π(0:1024*10-1)/10240), 内=1)
d_window=filt(FIRFilter([0.5, -0.3, 0.2, 0.1, -0.05]), x_window)


它正在这里创建:

1. 具有由正弦波调制的振幅的噪声信号
2. 通过FIR滤波器滤波获得的"所需"信号

通过计算自适应滤波器在每帧上的频率响应并使用曲面图可视化来执行分析。

In [ ]:
using EngeeDSP, DSP, FFTW, Plots

frameSize = 500
Fs = 8192
x_window = 0.05 * randn(1024*10) .* repeat(0.5 .+ 0.5sin.(2π*(0:1024*10-1)/10240), inner=1)
d_window = filt(FIRFilter([0.5, -0.3, 0.2, 0.1, -0.05]), x_window)

HA = EngeeDSP.LMSFilter(
    Algorithm = "LMS",
    FilterLength = 32,
    StepSize = 1.0,
    LeakageFactor = 1.0,
    InitialValueOfFilterWeights = 0,
    AdaptPort = false, 
    ResetPort = "None",
    OutputFilterWeights = true
)

numFrames = length(d_window) ÷ frameSize
response = zeros(512, numFrames)
t_frame = (0:frameSize:length(d_window)-1)/Fs

i = 1
for start_idx in 1:frameSize:length(x_window)-frameSize+1
    end_idx = start_idx + frameSize - 1
    x_frame = x_window[start_idx:end_idx]
    d_frame = d_window[start_idx:end_idx]
    
    if i == 1
        setup!(HA, x_frame, d_frame)
    end
    
    y, e, w = step!(HA, x_frame, d_frame)
    response[:,i] = 20*log10.(abs.(fft([w; zeros(512-length(w))])))
    i += 1
end

p1 = surface(t_frame, Fs*(0:511)/512, response,
    title="LMS Algorithm Response",
    xlabel="Time (s)", ylabel="Frequency (Hz)", zlabel="Power (dB)",
    camera=(-70, 18), zlims=(-80, 2))

HA = EngeeDSP.LMSFilter(
    Algorithm = "Normalized LMS",
    FilterLength = 32,
    StepSize = 0.3,
    LeakageFactor = 1.0,
    InitialValueOfFilterWeights = 0,
    AdaptPort = false,  
    ResetPort = "None",
    OutputFilterWeights = true
)

response = zeros(512, numFrames)

i = 1
for start_idx in 1:frameSize:length(x_window)-frameSize+1
    end_idx = start_idx + frameSize - 1
    x_frame = x_window[start_idx:end_idx]
    d_frame = d_window[start_idx:end_idx]
    
    if i == 1
        setup!(HA, x_frame, d_frame)
    end
    
    y, e, w = step!(HA, x_frame, d_frame)
    response[:,i] = 20*log10.(abs.(fft([w; zeros(512-length(w))])))
    i += 1
end

p2 = surface(t_frame, Fs*(0:511)/512, response,
    title="NLMS Algorithm Response",
    xlabel="Time (s)", ylabel="Frequency (Hz)", zlabel="Power (dB)",
    camera=(-70, 18), zlims=(-80, 2))

plot(p1, p2, layout=(1,2), size=(1000,400))
Out[0]:
  1. LMS算法:

    -使用固定的适应步骤(µ=1.0)
    -可对输入信号幅度的变化敏感
    -适应速度更快,但可能不太稳定

  2. NLMS算法:

    -使用归一化适应步骤(µ=0.3)
    -自动调整到输入信号电平
    -振幅变化时更稳定的操作

第二个例子的分析

第二个代码检查lms滤波器在静止和非静止信号上的行为:

``'茱莉亚
x=0.05randn(102410)
d_stat=filt(FIRFilter([0.5, -0.3, 0.2, 0.1, -0.05]), x)
d_nonstat=filt(FIRFilter([0.8, -0.2, 0.0, 0.1, -0.1]), x)


这里:

1. 固定情况:不可变系统(一个FIR滤波器)
2. 非平稳情况:系统正在变化(另一个FIR滤波器)

In [ ]:
using EngeeDSP, DSP, FFTW

frameSize = 500
Fs = 44100
x = 0.05 * randn(1024*10)
d_stat = filt(FIRFilter([0.5, -0.3, 0.2, 0.1, -0.05]), x)
d_nonstat = filt(FIRFilter([0.8, -0.2, 0.0, 0.1, -0.1]), x)

HA = EngeeDSP.LMSFilter(
    Algorithm = "LMS",
    FilterLength = 32,
    StepSize = 1.0,
    LeakageFactor = 1.0,
    InitialValueOfFilterWeights = 0,
    AdaptPort = false,
    ResetPort = "None",
    OutputFilterWeights = true
)

t_frame = (0:frameSize:length(x)-1)/Fs
response = zeros(512, length(t_frame))
i = 1
for start_idx in 1:frameSize:length(x)-frameSize+1
    end_idx = start_idx + frameSize - 1
    x_frame = x[start_idx:end_idx]
    d_frame = d_stat[start_idx:end_idx]
    
    if i == 1
        setup!(HA, x_frame, d_frame)
    end
    
    y, e, w = step!(HA, x_frame, d_frame)
    response[:,i] = 20*log10.(abs.(fft([w; zeros(512-length(w))])))
    i += 1
end

p1 = surface(t_frame, Fs*(0:511)/512, response,
    title="Stationary Signal Response",
    xlabel="Time (s)", ylabel="Frequency (Hz)", zlabel="Power (dB)",
    camera=(-70, 18), zlims=(-80, 2))

    response = zeros(512, length(t_frame))
i = 1
for start_idx in 1:frameSize:length(x)-frameSize+1
    end_idx = start_idx + frameSize - 1
    x_frame = x[start_idx:end_idx]
    d_frame = d_nonstat[start_idx:end_idx]
    
    y, e, w = step!(HA, x_frame, d_frame)
    response[:,i] = 20*log10.(abs.(fft([w; zeros(512-length(w))])))
    i += 1
end

p2 = surface(t_frame, Fs*(0:511)/512, response,
    title="Non-Stationary Signal Response",
    xlabel="Time (s)", ylabel="Frequency (Hz)", zlabel="Power (dB)",
    camera=(-70, 18), zlims=(-80, 2))

plot(p1, p2, layout=(1,2), size=(1000,400))
Out[0]:
  1. 静止信号:

    -滤波器成功收敛到最优解
    -频率响应随时间稳定

  2. 非平稳信号:

    -过滤器正试图适应不断变化的系统
    -特征不断变化,体现非平稳性

结论

给出的示例演示了自适应滤波器的关键特性。 LMS和NLMS之间的选择取决于信号特性和系统要求。 NLMS在信号强度变化时提供更稳定的操作,而经典的LMS在计算资源有限的条件下可能更可取。 非静止系统的分析需要一种特殊的方法,可以作为进一步研究的主题。
此外,根据他们的经验,可以得出以下结论:

  1. NLMS对于具有变化幅度的信号是优选的。

  2. 当使用非固定系统时,可能需要:

    -减少适应步骤
    -使用可变间距的算法
    -定期过滤器复位

  3. 动力学中频率响应的可视化是一个强大的分析工具