自适应滤波器更新算法-EP1

article/2025/7/22 6:09:20

自适应滤波器更新算法-EP1

  自适应滤波器是回声消除系统中非常重要的一个功能模块,而对于自适应滤波器来说,如果更新滤波器系数则是关键所在。本文将介绍几种现有的滤波器更新算法,并附上Matlab测试代码。

1、LMS算法

1.1算法原理

  LMS算法即最小均方算法(Least Mean Square),它是由Widrow和Hoff在1960年提出的。将LMS算法应用在滤波器上的结构中,其包含两个主要的部分,第一个部分是LMS算法的部分,另一个部分是常用的滤波器结构即横向有限冲击响应结构,假设n时刻的输入信号向量表达式为
X ( n ) = [ x ( n ) , x ( n − 1 ) , . . . , x ( n − M + 1 ) ] X(n) = [x(n),x(n-1),...,x(n-M+1)] X(n)=[x(n),x(n1),...,x(nM+1)]
其中,M表示滤波器的阶数,是一个固定值,其根据实际需求而定。滤波器的权向量的表达式为

在这里插入图片描述

其中,i是滤波器权向量的下标,即表示 w i ( n ) w_i(n) wi(n) 为第几个滤波器权向量,其取值范围为0~M-1,如 w 0 ( n ) w_0(n) w0(n) 表示的是 x ( n ) x(n) x(n) 所对应的权向量。滤波器输出信号表达式为:

在这里插入图片描述

n时刻期望信号 d ( n ) d(n) d(n) 与算法实际输出信号之间的差值表示为:

在这里插入图片描述

其中误差信号 e ( n ) e(n) e(n) 进入LMS算法的函数模型中,通过该函数模型控制着LMS算法的步长参数,随着每一次迭代系数向量 W ( n ) W(n) W(n) 发生改变,最终 W ( n ) W(n) W(n) 趋近于其最有解,从而使实际输出信号 y ( n ) y(n) y(n) 与期望信号 d ( n ) d(n) d(n) 的差值无限接近与0。

  传统LMS算法的具体步骤如下:

  1. 初始化参数。将自适应滤波器权系数的初始值 W ( 0 ) W(0) W(0) 设置为0,将自适应滤波器的阶数设置为M,选择合适的变化的步长值 μ \mu μ ,为了使算法收敛,步长 μ \mu μ 的取值应为:
    0 < μ < 1 / λ m a x 0<\mu<1/\lambda_{max} 0<μ<1/λmax
    其中 λ m a x \lambda_{max} λmax 表示输入信号 X ( n ) X(n) X(n) 的自相关矩阵的最大特征值。

  2. 计算滤波器的实际输出信号为 : y ( n ) = W T ( n ) X ( n ) y(n) = W^T(n) X(n) y(n)=WT(n)X(n)

  3. 计算自适应滤波器的误差为 : e ( n ) = d ( n ) − y ( n ) = d ( n ) − W T ( n ) X ( n ) e(n) = d(n) - y(n) = d(n) - W^T(n) X(n) e(n)=d(n)y(n)=d(n)WT(n)X(n)

  4. 更新滤波器权系数的值为: W ( n + 1 ) = W ( n ) + μ X ( n ) e ( n ) W(n+1) = W(n) + \mu X(n)e(n) W(n+1)=W(n)+μX(n)e(n)

重复上述步骤2~4,直到滤波器权系数逼近最佳滤波为止。

1.2 算法代码

function [e, y, w] = LMS(d, x, mu, M)
% Inputs:
% d  - 麦克风语音
% x  - 远端语音
% mu - 步长,0.05
% M  - 滤波器阶数,也称为抽头数
%
% Outputs:
% e - 输出误差,近端语音估计
% y  - 输出系数,远端回声估计
% w - 滤波器参数d_length = length(d);if (d_length <= M)  print('error: 信号长度小于滤波器阶数!');return; endif (d_length ~= length(x))  print('error: 输入信号和参考信号长度不同!');return; endxx = zeros(M,1);w1 = zeros(M,1);    % 滤波器权重y = zeros(d_length,1);  % 远端回声估计e = zeros(d_length,1);  % 近端语音估计for n = M:d_lengthxx = x(n:-1:n-M+1);    % 纵向拼接  (40~1)-->(41~2)-->(42~3)....y(n) = w1' * xx;        % 远端回声估计 (40,1)'*(40,1)=1; (73113,1)e(n) = d(n) - y(n);     % 近端语音估计w1 = w1 + mu * e(n) * xx;   % (40,1)w(:,n) = w1;        % (40, 73113)end
end

1.3 算法分析

  LMS算法是一种随机梯度下降算法,随着迭代次数的增加,更新出的权重值无法精确收敛,但是其算法简单,易于实现,算法复杂度也较低。但是算法中的 μ \mu μ 为步长因子,其对于算法的收敛速度、时变系统的跟踪速度和稳态误差这些特征起到关键的影响作用,较小的步长因子 μ \mu μ 会获得较小的稳态误差从而提高算法的精度,同时也会获得较小的收敛速度,使算法收敛的很慢,对于时变系统来说较小的步长因子也会导致跟踪速度的减小。反之,较大的步长因子 μ \mu μ 会带来较大的收敛速度使得算法收敛的很快,同时对于时变系统来说,会提高其跟踪速度,但是会带来较大的稳态误差,降低算法的精度。因此 μ \mu μ 的选取很关键。

2、NLMS算法

2.1算法原理

  归一化最小均方(Normalized Least Mean Squares,NLMS)算法是改进的变步长的LMS算法,对于较大的输入 X ( n ) X(n) X(n) ,会导致梯度噪声的放大,因此需要用输入向量的平方范数进行归一化。根据原LMS算法中误差信号与远端输入信号的乘积,对远端输入信号的平方(功率)进行归一化处理,将固定步长因子的LMS算法变为根据输入信号时变的变步长LMS算法,算法具体针对 μ \mu μ 改进为函数 μ ( n ) \mu(n) μ(n) 如下:
μ ( n ) = μ X T ( n ) X ( n ) + δ \mu(n) = \frac{\mu}{X^T(n)X(n)+\delta} μ(n)=XT(n)X(n)+δμ
其中, μ \mu μ 为自适应常量,取值为0~2, δ \delta δ 为一个较小的正常数,是为了防止输入信号 X ( n ) X(n) X(n) 过小导致分母趋近于0进而带来的算法不稳定性。则滤波器权系数更新公式为:
W ( n + 1 ) = W ( n ) + μ ( n ) X ( n ) e ( n ) W(n+1) = W(n) + \mu(n) X(n)e(n) W(n+1)=W(n)+μ(n)X(n)e(n)
  具体的实现步骤,除了 μ ( n ) \mu(n) μ(n) 的计算外,其他同LMS算法步骤相同。

2.2 算法代码

function[e,y,w] = NLMS(d,x,M)% 输入:% d  - 麦克风语音% x  - 远端语音% M  - 滤波器阶数%% 输出:% e - 近端语音估计% y - 远端回声估计% w - 滤波器参数d_length = length(d);if (d_length <= M)print('error: 信号长度小于滤波器阶数!');return; endif (d_length ~= length(x))  print('error: 输入信号和参考信号长度不同!');return; endxx = zeros(M,1);w1 = zeros(M,1);  %滤波器权重y = zeros(d_length,1); %近端语音e = zeros(d_length,1); %误差for n = 1:d_length%在输入信号x前补上M-1个0,使输出y与输入具有相同长度xx = [xx(2:M);x(n)]; %(39,1) +(1,1) = (40,1)y(n) = w1' *xx;mu = 1/(xx'*xx); %步长,这里简化了mu的计算,没有防止x(n)过小的情况e(n) = d(n) - y(n);  %误差w1 = w1 + mu * e(n) * xx;w(:,n) = w1;end
end

1.3 算法分析

  NLMS算法相对与LMS算法有着更快的收敛速度,同时保留了算法简洁、计算量小、易于实现的优点;但是NLMS算法没有考虑到滤波器阶数增长的问题。随着采样率的提升,滤波器的阶数已经达到千阶,算法复杂度也成倍增长。因此NLMS 算法仅适用于对处理精度和能力要求不是很高的一般场合。

3、PBFDAF算法

3.1 算法原理

参考文献一中对该算法的介绍:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2 算法代码

function [en, yk, W] = myFDAF(d,x,mu,mu_unconst, M, select)
% 参数:
% d                输入信号(麦克风语音)
% x                远端语音
% mu                约束 FDAF的步长
% mu_unconst        不受约束的 FDAF的步长
% M                 滤波器阶数
% select;            选择有约束或无约束FDAF算法x_new = zeros(M,1);     % 将新块的M个样本初始化为0
x_old = zeros(M,1);     % 将旧块的M个样本初始化为0AdaptStart = 2*M;       % 在获得2M个样本块后开始自适应
W = zeros(2*M,1);       % 将2M个滤波器权重初始化为0
d_block = zeros(M,1);   % 将期望信号的M个样本初始化为0power_alpha = 0.5;        % 常数以更新每个frequency bin的功率
power = zeros(2*M,1);   % 将每个bin的平均功率初始化为0
d_length = length(d);             % 输入序列的长度
en = [];                       % 误差向量
window_save_first_M = [ones(1,M), zeros(1,M)]';  % 设置向量以提取前M个元素 (2M,1)for k = 1:d_lengthx_new = [x_new(2:end,:); x(k)];         % 开始的输入信号块 (2M,1)d_block = [d_block(2:end,:); d(k)];     % 开始的期望信号快 (M,1)if mod(k,M)==0                        % If iteration == block length, x_blocks = [x_old; x_new];        % 2M样本的输入信号样本块 (2M,1)x_old = x_new;if k >= AdaptStart                % 频域自适应滤波器% 将参考信号转换到频域Xk = fft(x_blocks);     % (2M,1)% FFT[old block; new block]% Old block 包含M个先前的输入样本 (u_old)% New 包含M个新的输入样本 (u_new)% 计算滤波器估计信号Yk = Xk.*W;                  % 输入和权重向量的乘积(2M,1)*(2M,1)=(2M,1)temp = real(ifft(Yk));            % IFFT 输出的实部 (2M,1)yk = temp(M+1:2*M);               % 抛弃前M个元素,保留后M个元素 (M,1)% 计算误差信号error = d_block-yk;              % 误差信号块 (M,1)Ek = fft([zeros(1,M),error']');   % 在FFT之前插入零块以形成2M块(2M,1)% 更新信号功率估算power = (power_alpha.*power) + (1 - power_alpha).*(abs(Xk).^2); % (2M,1)% 计算频域中的梯度和权重更新if select == 1gradient = real(ifft((1./power).*conj(Xk).* Ek));   % (2M,1)gradient = gradient.*window_save_first_M;   % 去除后一个数据块,并且补零 (2M,1)W = W + mu.*(fft(gradient));    % 权重是频域的 (2M,1)elsegradient = conj(Xk).* Ek;   %  (2M,1)W = W + mu_unconst.*gradient;    % (2M,1)enden = [en; error];             % 更新误差块endend
end% 参考:https://github.com/CharlesThaCat/acoustic-interference-cancellation    

3.3 算法分析

  该算法利用FFT可快速实现卷积运算的特点,在频域进行滤波器的更新,同时使用逐块更新来代替逐点更新,从而大大降低了算法的计算复杂度。但同时其步长因子 μ \mu μ 是由自适应常量和远端信号决定的,是固定的无法根据不同复杂的场景进行变换,该算法应用在WebRTC的AEC算法中。在AEC算法中,其用了延时估计模块来对齐语音信号,并采用了语音检测等模块来去除噪声和无用语音的影响,以提高滤波器更新算法的效果。

续:本文先介绍几种比较经典的自适应滤波器算法,后续将介绍读者阅读论文总结并复现的滤波器算法!!!

参考文献

[1] 葛世超,吕强。《实时语音处理实践指南》。

[2] Soo J S , Pang K K . Multidelay block frequency domain adaptive filter[J]. Acoustics Speech & Signal Processing IEEE Transactions on, 1990, 38(2):373-376.


http://chatgpt.dhexx.cn/article/nDsknTcu.shtml

相关文章

自适应神经网络算法原理,单神经元自适应控制

关于神经网络自适应控制求助 这句话你可以直接用&#xff0c;不用加引用。因为这句话是很容易验证的。在网络层数、隐含层节点数逐渐增加&#xff0c;训练次数增加之后&#xff0c;他的拟合能力也是不断增加的&#xff0c;所以说&#xff0c;他可以以任意精度逼近任何非线性连…

【转载】梯度下降算法的参数更新公式

NN这块的公式&#xff0c;前馈网络是矩阵乘法。损失函数的定义也是一定的。 但是如何更新参数看了不少描述&#xff0c;下面的叙述比较易懂的&#xff1a; 1、在吴恩达的CS229的讲义的第四页直接给出参数迭代公式 在UFLDL中反向传导算法一节也是直接给出的公式 2、例子&#x…

Java中Comparator的个人简单理解(升序降序)与使用

目录 Java自定义排序返回值简单记忆理解实践LInkedList升序&#xff08;默认情况&#xff09;降序 PriorityQueue升序下的小顶堆&#xff08;默认情况&#xff09;降序下的大顶堆 总结补充数组类型自定义排序降序排序 数组 Java自定义排序返回值简单记忆理解 默认情况下&#…

深度残差收缩网络(从信号降噪的角度进行理解)

本文探讨了深度残差收缩网络的另一种理解方式。 传统信号降噪算法的常见步骤是&#xff1a; ① 采用某种信号变换方法&#xff08;例如小波、经验模态分解&#xff09;&#xff0c;将含噪信号变换到另外一种形态&#xff08;例如小波系数、本征模态分量等&#xff09;。在这些…

NIPS 2016 深度学习 迁移学习 ---残差转移网络用于无监督领域自适应

深度学习的成功得益于大量的标注数据&#xff0c;而数据标注是非常消耗资源的。当一个问题中缺少标注数据时&#xff0c;可以从另一个源中所学知识迁移过来&#xff0c;并且用于新问题中。 清华大学的学者提出了一种新的方法&#xff08;https://arxiv.org/pdf/1602.04433.pdf&…

深度残差网络+自适应参数化ReLU激活函数(调参记录21)Cifar10~95.12%

本文在调参记录20的基础上,将残差模块的个数,从27个增加到60个,继续测试深度残差网络ResNet+自适应参数化ReLU激活函数在Cifar10数据集上的表现。 自适应参数化ReLU函数被放在了残差模块的第二个卷积层之后,这与Squeeze-and-Excitation Networks或者深度残差收缩网络是相似…

已知两个长度分别为m 和 n 的升序链表,合并降序链表,求时间复杂度

王道数据结构上一道题&#xff1a; 之前我看到一个电子版的书&#xff0c;上边答案解析写的有点错误&#xff0c; 听说有些同学买的实体书上&#xff0c;答案解析也是这样写的 这个是刊印错误&#xff0c;很显然2Max( m , n )大于等于 m n 而且这个解析也不够清晰。 解析&a…

波束形成 常见自适应波束形成算法信(干)噪比增益影响因素

0、其他补充 均匀线阵波束形成器的信噪比增益上确界可由下式表示&#xff1a; 其中为阵元数&#xff0c;所以为了方便起见&#xff0c;一般的稳健自适应波束形成算法在仿真过程中的阵元数量均设置为10。 阵列的导向矢量可由下式表示&#xff1a; 以首个阵元为参考阵元&#xff…

两个升序链表合并成一个降序链表的时间复杂度

王道考研P7 第六题 【2013年统考真题】已知两个长度分别为m和n的升序链表&#xff0c;若将它们合并为长度为mn的一个降序链表&#xff0c;则最坏情况下的时间复杂度是&#xff08;&#xff09; A. O(n) B. O(mn) C. O(min(m,n)) D. O(max(m,n)) 答案是D 注意&#xff0c;此题…

无线传感器网络路由优化中的能量均衡LEACH改进算法

文章目录 一、理论基础1、LEACH算法概述2、改进的LEACH算法 二、算法流程图三、仿真实验与分析四、参考文献 一、理论基础 1、LEACH算法概述 请参考这里。 2、改进的LEACH算法 改进的LEACH算法&#xff08;LEACH-N&#xff09;主要针对LEACH算法分簇阶段的缺陷而改进的&…

机器学习之自适应增强(Adaboost)

1.Adaboost简介 **Adaptive boosting(自适应增强)是一种迭代算法&#xff0c;其核心思想是针对同一个训练集训练不同的弱分类器&#xff0c;然后把这些弱分类器集合起来&#xff0c;构成一个强分类器&#xff0c;Adaboost可处理分类和回归问题。了解Adaboost算法之前&#xff…

自适应阈值(adaptiveThreshold)分割原理及实现

背景介绍及原理 前面介绍了OTSU算法和最大熵算法&#xff0c;但这两种算法都属于全局阈值法&#xff0c;所以对于某些光照不均的图像&#xff0c;这种全局阈值分割的方法会显得苍白无力&#xff0c;如下图&#xff1a; 显然&#xff0c;这样的阈值处理结果不是我们想要的&…

优化算法+神经网络:神经网络自动参数优化

当智能群优化算法遇上神经网络 优化算法进行神经网络的参数寻优&#xff0c;解放深度调参1.已经实现的Genetic Algorithm优化Neural Network2.已经实现的PSO优化Neural Network3.已实现的SSA[^1]优化Neural Network 三种方法的可视化搜索过程对比三种优化算法性能总结总结目前来…

Java stream().sorted()实现排序(升序、降序、多字段排序)

1 自然排序 sorted()&#xff1a;自然排序&#xff0c;流中元素需实现Comparable接口 package com.entity;import lombok.*;Data ToString AllArgsConstructor NoArgsConstructor public class Student implements Comparable<Student> {private int id;private String …

linux centos查找某个文件,Linux查找命令(文件、文件中的关键字)

1、grep &#xff1a;查找文件中的内容 $ grep [option] pattern [file] 例&#xff1a; $ grep un day Sunday 例: $grep include doulinked.c doulinked1.c doulinked.c:#include doulinked.c:#include doulinked.c:#include doulinked1.c:#include doulinked1.c:#includ…

Linux下查找\命令(收集整理)

以下为总结&#xff0c;其实可直接跳过&#xff0c;查看locate部分&#xff0c;这个是类似windows下verything搜索工具&#xff01; 一.Linux查找文件的相关命令 常 用 命 令 简要中文说明 程序所在目录 whereis 寻找文件工具 /usr/bin find 寻找文件工具 /usr/bin l…

Linux查找命令 which和find命令

目录 前言一、which命令二、find命令 前言 一、which命令 格式&#xff1a; which [选项] 命令|程序名 #默认当找到第一个目标后不再继续查找选项说明-a查找全部内容&#xff0c;而非第一个文件-n<文件名长度>  指定文件名长度&#xff0c;指定的长度必须大于或等于所有…

Linux文件查找的4个命令

1. find find 命令应该是最经典的命令了&#xff0c;谈到搜索工具第一个想到的肯定是 find 命令。但是&#xff0c;find 命令非常强大&#xff0c;想要把它的功能都介绍一遍&#xff0c;恐怕要写好几篇文章。 所以&#xff0c;这里介绍最基本的&#xff0c;根据文件名查找文件…

Linux下的查找命令合集(which/whereis/locate/find)

Linux 下的查找命令有很多&#xff0c;常用的有which、whereis、locate、find。那么这4个命令之间各自有什么特点&#xff0c;又有什么区别&#xff0c;什么时候该用哪个才最合适呢&#xff1f;方便我们在开发和学习中能更加有效的使用。 1、which 该命令主要是用来查找系统P…

【Linux命令】查找文件命令

文章目录 一、查找文件locateupdatedbfind测试条件操作符操作预定义操作自定义操作 find命令选项&#xff08;常用&#xff09; 一、查找文件 locate locate命令会查找其路径名数据库&#xff0c;输出所有包含查找字符串的匹配项&#xff1a; locate settings.xmlupdatedb …