3. RLS算法

任务目标

实现递归最小二乘(RLS)自适应滤波器,在相同输入条件下与LMS滤波器对比收敛速度与稳态误差,验证RLS收敛更快但稳态误差更低的特性。

核心原理与实现

RLS通过递推更新逆相关矩阵P(n)和增益向量k(n),使代价函数为指数加权误差平方和。遗忘因子λ控制历史数据权重,通常取0.99~1.0。本案例使用系统辨识场景:未知FIR滤波器h*,自适应滤波器w(n)逼近该未知系统。

完整代码(Python + NumPy)

import numpy as np
import matplotlib.pyplot as plt

def rls_filter(x, d, M, lam=0.99, delta=1.0):
    """RLS自适应滤波器
    x: 输入信号, d: 期望信号, M: 滤波器阶数
    lam: 遗忘因子, delta: 正则化初始值
    返回: 误差序列e, 权重历史w_history
    """
    N = len(x)
    w = np.zeros(M)
    P = np.eye(M) / delta
    e = np.zeros(N)
    w_history = np.zeros((N, M))
    
    for n in range(N):
        x_n = x[max(0, n-M+1):n+1][::-1]
        if len(x_n) < M:
            x_n = np.pad(x_n, (M-len(x_n), 0))
        
        # 先验误差
        y = np.dot(w, x_n)
        e[n] = d[n] - y
        
        # 增益向量
        Pi = np.dot(P, x_n)
        k = Pi / (lam + np.dot(x_n, Pi))
        
        # 更新权重和逆相关矩阵
        w = w + k * e[n]
        P = (P - np.outer(k, np.dot(x_n, P))) / lam
        
        w_history[n] = w
    return e, w_history

def lms_filter(x, d, M, mu):
    """LMS自适应滤波器(用于对比)"""
    N = len(x)
    w = np.zeros(M)
    e = np.zeros(N)
    w_history = np.zeros((N, M))
    
    for n in range(N):
        x_n = x[max(0, n-M+1):n+1][::-1]
        if len(x_n) < M:
            x_n = np.pad(x_n, (M-len(x_n), 0))
        
        y = np.dot(w, x_n)
        e[n] = d[n] - y
        w = w + 2 * mu * e[n] * x_n
        w_history[n] = w
    return e, w_history

# ===== 仿真参数 =====
np.random.seed(42)
N = 2000          # 样本数
M = 4             # 滤波器阶数
h_true = np.array([0.5, -0.3, 0.8, 0.2])  # 未知系统

# 生成输入信号(白噪声)和期望信号
x = np.random.randn(N)
d = np.convolve(x, h_true)[:N] + 0.01 * np.random.randn(N)  # 加观测噪声

# 运行RLS和LMS
e_rls, w_rls = rls_filter(x, d, M, lam=0.99, delta=1.0)
mu = 0.02  # LMS步长(保证收敛)
e_lms, w_lms = lms_filter(x, d, M, mu)

# ===== 验证:权重收敛轨迹 =====
print("RLS最终权重:", w_rls[-1])
print("LMS最终权重:", w_lms[-1])
print("真实权重:  ", h_true)

# ===== 绘图对比 =====
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.semilogy(np.abs(e_rls)**2, label='RLS')
plt.semilogy(np.abs(e_lms)**2, label='LMS')
plt.xlabel('迭代次数 n'); plt.ylabel('瞬时误差平方')
plt.legend(); plt.grid(True); plt.title('收敛速度对比')

plt.subplot(1, 2, 2)
for i in range(M):
    plt.plot(w_rls[:, i], '--', label=f'RLS w{i}')
    plt.plot(w_lms[:, i], ':', label=f'LMS w{i}')
plt.axhline(y=h_true[0], color='k', linewidth=0.5)
plt.xlabel('迭代次数 n'); plt.ylabel('权重值')
plt.legend(loc='center right', fontsize=8)
plt.grid(True); plt.title('权重收敛轨迹')
plt.tight_layout()
plt.savefig('rls_vs_lms.png', dpi=100)
plt.show()

运行与验证

  1. 依赖安装:pip install numpy matplotlib
  2. 运行方式:将代码保存为 rls_lms_compare.py,执行 python rls_lms_compare.py
  3. 通过判定标准:
    • 终端输出RLS最终权重与真实权重 [0.5, -0.3, 0.8, 0.2] 的误差小于0.05(RLS收敛后接近真值);
    • 左图显示RLS误差平方曲线约在50次迭代内快速下降至10⁻⁴以下,LMS需数百次迭代才接近该水平;
    • 右图显示RLS权重轨迹在约100次迭代内稳定至真实值附近,LMS轨迹收敛明显更慢且存在更大波动。

关键说明

  • RLS的初始正则化参数 delta 取1.0(信噪比较高时),若噪声大需增大至10~100;
  • 遗忘因子 λ=0.99 在平稳系统中接近1.0可获得更低稳态误差,非平稳环境可调至0.95~0.98;
  • LMS步长 mu=0.02 需满足 0 < mu < 1/λ_max(输入功率约1,故上限约0.5),此处取值保证稳定但收敛慢,用于突出对比。
RLS vs LMS 收敛特性示意 迭代次数 n 误差平方 (log) 10⁰ 10⁻² 10⁻⁴ 10⁻⁶ LMS RLS ~50次迭代收敛 ~500次迭代收敛 RLS稳态误差更低