LMS自适应滤波

LMS概述

LMS(Least Mean Square), 由 Widrow 和 Hoff 于1960年提出,也称Δ规则。该算法与感知器网络的学习算法在权值调整上都基于纠错学习规则,但 LMS 更易实现,因此得到广泛应用,成为自适应滤波的标准算法。

LMS滤波器是一类能够“学习”未知传递函数的自适应滤波器。 LMS 滤波器使用一种梯度下降法,其中滤波器系数根据瞬时误差信号更新。自适应滤波器常用于通信系统、均衡器和噪声去除。

LMS过滤器由两个组件组成,如下图所示。第一个组件是一个标准的横向或FIR滤波器。第二部分是系数更新机制。LMS滤波器有两个输入信号。“输入”输入FIR滤波器,而“参考输入”对应于FIR滤波器的期望输出。即更新FIR滤波器系数,使FIR滤波器的输出与参考输入匹配。滤波器系数更新机制是基于FIR滤波器输出与参考输入之间的差值。随着滤波器的适应,这个“错误信号”趋于零。LMS处理函数接受输入和参考输入信号,生成滤波输出和误差信号。
在这里插入图片描述

原理解析

函数对数据块进行操作,每次调用函数都会通过过滤器处理blockSize样本。 p S r c pSrc pSrc 指向输入信号, p R e f pRef pRef 指向参考信号, p O u t pOut pOut 指向输出信号, p E r r pErr pErr 指向错误信号。所有数组都包含blockSize值。

这些函数以块为单位进行操作。在内部,过滤器系数 b [ n ] b[n] b[n] 在一个样本一个样本的基础上更新。与归一化 LMS 算法相比, LMS 滤波器的收敛速度较慢。

输出信号 y [ n ] y[n] y[n] 由标准FIR滤波器计算得到

y [ n ] = b [ 0 ] ∗ x [ n ] + b [ 1 ] ∗ x [ n − 1 ] + . . . + b [ n u m T a p s − 1 ] ∗ x [ n − n u m T a p s + 1 ] y[n] = b[0] * x[n] + b[1] * x[n-1] + ... + b[numTaps-1] * x[n-numTaps+1] y[n]=b[0]x[n]+b[1]x[n1]+...+b[numTaps1]x[nnumTaps+1]

误差信号为参考信号 d [ n ] d[n] d[n] 与计算结果 y [ n ] y[n] y[n]之间差值

e [ n ] = d [ n ] − y [ n ] e[n] = d[n] - y[n] e[n]=d[n]y[n]

误差信号被计算出来后,滤波器参数 b [ k ] b[k] b[k] 会被更新

b [ k ] = b [ k ] + e [ n ] ∗ m u ∗ x [ n − k ] , k = 0 , 1 , 2 , . . . , n u m T a p s − 1 b[k] = b[k] + e[n] * mu * x[n-k], k=0,1,2,...,numTaps-1 b[k]=b[k]+e[n]mux[nk],k=0,1,2,...,numTaps1

式中, m u mu mu 为步长,控制系统收敛速度
在APIs中, p C o e f f s pCoeffs pCoeffs 为一个长度为 n u m T a p s numTaps numTaps 的系数数组,其按时间倒序存储

b [ n u m T a p s − 1 ] , b [ n u m T a p s − 2 ] , . . . , b [ 1 ] , b [ 0 ] ] {b[numTaps-1], b[numTaps-2],..., b[1], b[0]]} b[numTaps1],b[numTaps2],...,b[1],b[0]]

** p S t a t e pState pState 为一个长度为 n u m T a p s + b l o c k S i z e − 1 numTaps + blockSize - 1 numTaps+blockSize1 的状态数组,状态缓冲区的样本按顺序存储**

x [ n − n u m T a p s + 1 ] , x [ n − n u m T a p s ] , x [ n − n u m T a p s − 1 ] , . . . , x [ 0 ] , x [ 1 ] , . . . , x [ b l o c k S i z e − 1 ] {x[n-numTaps+1], x[n-numTaps], x[n-numTaps-1],..., x[0], x[1],..., x[blockSize-1]} x[nnumTaps+1],x[nnumTaps],x[nnumTaps1],...,x[0],x[1],...,x[blockSize1]

注意,状态缓冲区的长度超过了样本的系数数组的长度 b l o c k S i z e − 1 blockSize-1 blockSize1。增加的状态缓冲区长度允许循环寻址,这是传统的FIR滤波器,以避免和产生显著的速度提高。在处理每个数据块之后更新状态变量。

代码

Matlab

clear; close all; clc;

t = 0:199;
xs = 10*cos(0.5*t); %xs为理想的余弦信号
noise = randn(1,length(t)); %噪声信号
xn = xs+noise; %输入信号
dn = xs;
[w,en,yn] = LMS_Simple(xn,dn); %引用LMS算法实现滤波

t_new = 0:length(yn)-1;

figure;
subplot(511); plot(t,xs);
grid;title('理想信号');
subplot(512); plot(noise);
grid;title('随机噪声');
subplot(513); plot(t,xn,'r',t,dn,'blue');
grid;title('输入信号和理想信号的对比');
subplot(514); plot(yn);
grid;title('输出信号');
subplot(515); plot(t,xn,'red',t_new,yn,'blue',t_new,en,'yellow');
grid;title('三种信号的比较');
legend('输入信号','输出信号','误差信号');

%LMS算法
function [w,en,yn] = LMS_Simple(xn,dn) %xn为输入信号(行向量), dn为理想信号(行向量)
    M = 30; %滤波器的阶数

    zeroize = zeros( (ceil(length(xn)/M) * M) - length(xn) , 1); % 补零
    xn = cat(1,xn',zeroize);%行向量转置为列向量,补零
    dn = cat(1,dn',zeroize);%行向量转置为列向量,补零

    itr = length(xn); % 使得迭代次数为输入信号xn的长度
    w = zeros(M,itr); % 滤波器的系数矩阵
    en = zeros(itr,1); % 误差信号
    yn = zeros(length(xn)); %滤波器的输出信号

    lambda = max(eig(xn*xn')); %xn的自相关矩阵的最大特征值
    mu = 0.95 * (2/lambda); %求步长,0.95系数可设置,保证小于2/lambda
    %迭代更新滤波器的参数
    for k = M:itr  %要保证输入延时后的信号有效,所以实际的迭代次数只有(itr-M)次,
        x = xn(k:-1:k-M+1); %将输入信号延迟,使得滤波器的每个抽头都有输入
        y = w(:,k-1)'*x;  %计算出滤波器的输出
        en(k) = dn(k)-y;   %得出误差信号
        w(:,k) = w(:,k-1) + mu*en(k)*x;%迭代更新滤波器的系数
        yn(k) = w(:,k)'*x; %滤波器的最终输出
    end
end

---->>代码来源

Python

# -*- coding: utf-8 -*-
"""
Created on Wed Jun  8 15:38:24 2022

@author: heng.zhang
"""
import numpy as np
import matplotlib.pyplot as plt
import scipy.io as scio

# 信号加噪
def awgn(x, snr):
    snr = 10 ** (snr / 10.0)
    xpower = np.sum(np.abs(x) ** 2) / len(x)
    npower = xpower / snr
    if type(x[0]) != np.complex128:
        return x + np.random.randn(len(x)) * np.sqrt(npower)
    else:
        return x + np.random.randn(len(x)) * np.sqrt(npower / 2) + 1j * np.random.randn(len(x)) * np.sqrt(npower / 2)

def lmsFunc(xn, dn, M, mu):
    itr = len(xn)
    en = np.zeros((itr, 1))
    W = np.zeros((M, itr))
    for k in range(M, itr):
        if k==20:
            x = xn[k-1::-1]
        else:
            x = xn[k-1:k-M-1:-1]
        try:
            y = np.dot(W[:, k - 2], x)
            #print(y)
        except:
            pass
        en[k-1] = dn[k-1] - y
        W[:, k-1] = W[:, k - 2] + 2 * mu * en[k-1] * x

    yn = np.ones(xn.shape) * np.nan
    for k in range(M, len(xn) ):
        if k == 20:
            x = xn[k - 1::-1]
        else:
            x = xn[k - 1:k - M - 1:-1]
        yn[k] = np.dot(W[:, -2], x)

    return yn, W, en

if __name__ == '__main__':
    fs = 1 #采样频率
    f0 = 0.02 #信号频率
    n = 1000
    t = np.arange(n)/fs
    xs = np.cos(2*np.pi*f0*t)
    ws = awgn(xs, 20)

    M = 20
    xn = ws
    dn = xs
    mu = 0.001
    yn, W, en = lmsFunc(xn, dn, M, mu)

    plt.figure()
    plt.subplot(211)
    plt.plot(t, ws)
    plt.subplot(212)
    plt.plot(t, yn)

    plt.figure()
    plt.plot(en)
    plt.show()

猜你喜欢

转载自blog.csdn.net/weixin_42762173/article/details/125191205