变步长与频域自适应算法

固定步长的收敛矛盾

标准 LMS 算法和 NLMS 算法都使用固定的步长参数 $\mu$。步长大小的选择直接影响算法性能,但存在一个根本矛盾:

  • 大步长:收敛速度快,能够快速追踪环境变化,但稳态误差大,滤波精度低
  • 小步长:稳态误差小,滤波精度高,但收敛速度慢,对突变响应迟缓

这个矛盾在回声消除、主动噪声控制等应用中尤为突出——系统启动时需要快速收敛,稳态后则希望维持低误差。固定步长无法同时满足两阶段的需求。

图1 - 固定步长矛盾示意:

mermaid
flowchart TD
    START["算法启动"] --> BIG{"步长 μ 大?"}
    BIG -->|"是"| FAST["收敛快 ✓<br/>但稳态误差大 ✗"]
    BIG -->|"否"| SLOW["稳态精度高 ✓<br/>但收敛慢 ✗"]
    FAST --> DILEMMA["鱼和熊掌<br/>不可兼得"]
    SLOW --> DILEMMA
    DILEMMA --> VSS["变步长方案<br/>μ(n) 随误差动态变化"]

    classDef problem fill:#f44336,color:#fff
    classDef solution fill:#4CAF50,color:#fff
    class FAST,SLOW,DILEMMA problem
    class VSS solution

变步长算法原理

变步长算法的核心思想:步长不再固定,而是根据某种误差度量动态调整。误差大时步长大以加速收敛,误差小时步长小以降低稳态波动。

变步长的一般形式可表示为:

$$ \mu(n) = f(e(n)) $$

其中 $f(\cdot)$ 是一个单调非递减函数,$e(n)$ 是当前时刻的误差信号。$f$ 的设计决定了算法的具体行为。

图3 - 变步长行为对比:

mermaid
flowchart TD
    subgraph 启动阶段
        S1["误差大 → μ 自动增大<br/>→ 快速收敛"]
    end
    subgraph 稳态阶段
        S2["误差小 → μ 自动减小<br/>→ 低稳态误差"]
    end
    subgraph 突变场景
        S3["误差突增 → μ 再次增大<br/>→ 快速重新跟踪"]
    end
    S1 --> S2 --> S3 --> S2

    classDef phase fill:#9C27B0,color:#fff
    class S1,S2,S3 phase

下面的双图动画展示了误差 e(n) 和步长 μ(n) 如何同步变化——误差大时步长自动增大,误差小时步长自动减小:

自适应步长 · μ(n) 随误差 e(n) 调节
误差 e(n)
步长 μ(n)
迭代次数 n
μ(n) = μmax · (1 − e−β·e(n)²) μmax = 0.05, β = 10

基于误差能量的变步长

一种直观的方案是将步长与误差能量关联:

$$ \mu(n) = \alpha \cdot \left(1 - \exp(-\beta \cdot e^2(n))\right) $$

逐项拆解这个公式:

数值例子:取 $\alpha=0.01,;\beta=100,;e=0.1$,则

$$ \mu = 0.01 \times (1 - \exp(-100 \times 0.01)) = 0.01 \times (1 - e^{-1}) \approx 0.0063 $$

其中 $\alpha$ 控制步长的上限(最大步长),$\beta$ 调节误差到步长的响应曲线斜率。$\beta$ 越大,小误差下步长的衰减越快。

该方案的特性:

Sigmoid 函数变步长

另一种常见方案引入 Sigmoid 函数,在误差绝对值上构造步长曲线:

$$ \mu(n) = \alpha \cdot \left(\frac{2}{1 + \exp(-\beta |e(n)|)} - 1\right) $$

Sigmoid 变步长的特点是误差很小时步长趋近于零,误差增大后步长快速接近 $\alpha$。相比指数型,Sigmoid 在中低误差区间有更陡的过渡带,适合对收敛速度要求更激进的应用场景。

变步长算法的参数调整需要根据具体信号特性进行。参考原则:$\alpha$ 不应超过稳定条件允许的最大步长,$\beta$ 则通过实验或离线数据预分析来确定。

频域自适应滤波

当自适应滤波器的阶数 $N$ 较大时(典型如声学回声消除场景,$N$ 可达 1024 甚至 4096),时域算法的计算量成为瓶颈。

时域卷积的计算代价

时域 FIR 滤波器的每次迭代涉及一次完整的卷积运算。对于 $N$ 阶滤波器:

但每输出一个采样点需要一次迭代,因此每采样点的计算量为 $O(N)$。对于长滤波器,累积开销不可忽视。

FFT 将卷积变为乘法

频域算法绕过时域卷积,利用 FFT 将信号变换到频域,在频域完成滤波和权重更新:

  1. 信号分块:将输入信号 $x(n)$ 分成每块 $L$ 个采样点的数据块,频域算法以块为单位处理
  2. FFT 变换:对每个数据块做 $M$ 点 FFT(通常 $M = 2L$,采用重叠保留法避免循环卷积)
  3. 频域滤波:频域中滤波是逐点乘法:$Y(k) = X(k) \cdot W(k)$,其中 $X(k)$ 和 $W(k)$ 分别是输入和权重的频域表示
  4. IFFT 转回时域:将频域输出反变换回时域,取有效部分作为该块的输出
  5. 频域权重更新:误差信号也经 FFT 转到频域,在频域完成梯度计算和权重更新

图2 - 频域块处理流水线:

mermaid
flowchart TD
    A["输入信号 x(n)<br/>时域连续"] --> B["分块<br/>每块 L 个样本"]
    B --> C["FFT<br/>时域→频域"]
    C --> D["频域乘法<br/>Y(k) = X(k)·W(k)"]
    D --> E["IFFT<br/>频域→时域"]
    E --> F["重叠保留<br/>取有效输出"]
    F --> G["输出 y(n)"]

    classDef time fill:#2196F3,color:#fff
    classDef freq fill:#f44336,color:#fff
    classDef out fill:#4CAF50,color:#fff
    class A,B,F,G time
    class C,D,E freq

每次块处理的计算复杂度包括两次 FFT(前向)、一次 IFFT(反向)以及频域乘法,总计 $O(M \log M)$。由于每 $L$ 个采样点才做一次块处理,分摊到每个采样点的复杂度为 $O(\log M)$。相比时域的 $O(N)$,当 $N = 1024$ 时频域算法可将计算量降低一到两个数量级。

用具体数字感受差异:

频域算法的权衡

频域算法的优势以额外的延迟和内存为代价:

适用场景选择

时域变步长算法和频域块算法适用于不同的场景: