首页/文章/ 详情

LMS主动降噪

3月前浏览612

在NVH工程领域,主动降噪技术相较于传统被动降噪,其降噪收益更为显著。例如,针对某一低频噪声峰值,主动降噪可实现5dB左右的明显衰减;而基于传递路径的结构优化,由于单个噪声峰值往往是多个传递路径共同作用的结果,并非由某一单一零部件或单体路径单独贡献,因此在制定可工程化的NVH优化方案时,难以获得显著的降噪效果。即便叠加多个结构优化方案,最终的主观噪声评价也无法实现质的提升,验收结果往往仅处于可接受的边缘。

在此背景下,LMS(Least Mean Square,最小均方)算法作为一种基于随机梯度下降的自适应滤波算法,被广泛应用于主动降噪系统中。该算法通过实时调整滤波器系数,使系统输出的“抗噪声”信号能够最大程度抵消原始噪声,最终让误差麦克风检测到的残余噪声趋近于零。当然这个基础算法有些弊端,因此在LMS算法的基础上已衍生出多种改进算法,本文将从公式和数值计算两个维度,详细解析这一基础算法的核心逻辑。

1.下面引入具体的物理表现讲解上述流程图运行逻辑:

设X(n)为轮芯振动参考信号,P(z)为车身结构声学传递路径;轮芯振动经传递路径激励车身壁板,最终向乘员舱辐射形成人耳处噪声,记为期望信号d(n)。

W(z)为自适应滤波器(如三阶滤波器初始权值可设为[0,0,0])。参考信号X(n)经滤波器加权输出控制信号:y(n)=wT(n)x(n),y(n)作为抵消反向声波,用于抵消舱内原始噪声d(n)。

定义残余误差信号:e(n)=d(n)−y(n)=d(n)−wT(n)x(n)

以参考信号X(n)驱动LMS算法完成滤波器权值自适应更新,权值迭代基础公式为:w(n+1)=w(n)−μ∇J(w)式中:μ为固定学习率;代价函数采用均方误差J(w)=E[e2(n)],工程中用瞬时误差平方近似数学期望,即J(w)≈e2(n);∇J(w)为代价函数对权向量的梯度。

梯度方向是代价函数增长最快的方向,迭代公式中引入负梯度,使滤波器权值沿代价函数最快下降的方向更新。对梯度求解并化简后,得到LMS标准权值更新公式:w(n+1)=w(n)+μe(n)x(n)

2.以下是上述流程的具体运行的计算过程,可以帮助更好的理解算法原理:

基础前提设

1.3阶横向滤波器W(行向量),初始权重W(0)=[0,0,0]

2.LMS更新公式:W(n+1)=W(n)+μ⋅e(n)⋅x(n),μ=0.1

3.信号链路划分三条并行通路:

通路①原生噪声通路:轮芯振动参考信号x(t)经车身/空气路径传递,形成人耳处原始噪声d(t);

通路②降噪抵消通路:参考信号经滤波器权重运算,输出抵消声y(t),误差信号e(t)=d(t)−y(t);

通路③LMS权重更新通路:参考输入向量+误差信号,实时迭代更新滤波器权重,实现自适应降噪。

第一时刻t=0~t=0.001s

  1. 通路①原生噪声

轮芯初始振动:x(t=0)=2

经物理路径传递延时0.001s,人耳处原始噪声:d(t=0.001)=2.1(这里经过路径传递数值2.1只是举个例子,输入和输出有强相关性)

  1. 通路②抵消输出运算当前滤波器初始权重:W(t=0)=[0,0,0]

参考信号延时向量:x(t=0)=[2,0,0](参考输入向量,新样本移入、旧样本移出)

抵消声输出:y(t=0.001)=WT(0)⋅x(0)=0

残余误差信号:e(t=0.001)=d(0.001)−y(0.001)=2.1−0=2.1

  1. 通路③LMS权重迭代

代入LMS更新公式:

W(0.001)=W(0)+μ⋅e(0.001)⋅x(0)=[0,0,0]+0.1×2.1×[2,0,0]=[0.42,0,0]

第二时刻:t=0.001~t=0.002s

  1. 通路①原生噪声

下一时刻轮芯振动:x(t=0.001)=2.05

经固定路径延时传递,人耳处原始噪声:d(t=0.002)=2.13

  1. 通路②抵消输出运算

滤波器更新后权重:W(t=0.001)=[0.42,0,0]

参考信号滑动更新:新样本移入、旧样本移出,重构延时向量x(t=0.001)=[2.05,2,0]

抵消声输出:

y(t=0.002)=WT(t=0.001)⋅x(t=0.001)=0.861

残余误差信号:

e(t=0.002)=d(t=0.002)−y(t=0.002)=2.13−0.861=1.269

  1. 通路③LMS权重迭代

以上一时刻权重为基础,结合当前误差、参考向量更新:

W(t=0.002) =W(t=0.001)+μ⋅e(t=0.001)⋅x(t=0.001)=[0.42,0,0]+0.1×2.1×[2.05,2,0]=[0.8505,0.42,0]

3.以下给出过程代码,可直接在python里运行

import numpy as np
import matplotlib.pyplot as plt

# =====================解决Matplotlib中文显示问题=====================
plt.rcParams['font.sans-serif'] = ['SimHei''Microsoft YaHei''WenQuanYi Zen Hei']   
plt.rcParams['axes.unicode_minus'] = False 
plt.rcParams['font.family'] = 'sans-serif'
# ==========================================================================

class LMSFilter:
    
"""
    
标准LMS自适应滤波器实现。
    
适用于实时或离线处理,用于系统辨识、噪声消除等场景。
    """

    
def __init__(self, filter_order, step_size=0.01):
        
"""
        
初始化滤波器。
        
参数:
            filter_order (int): 
滤波器阶数(抽头数)。阶数越高,模型能力越强,但计算量越大,收敛可能越慢。
            step_size (float): 
步长参数 μ。必须在稳定范围内 (0 < μ < 2/输入功率)。通常从0.01这样的小值开始尝试。
        """
        
self.order = filter_order
        
self.mu = step_size
        
初始化滤波器权重为零向量
        
self.weights = np.zeros(filter_order)
        
用于存储最近的输入样本,构成输入向量x(n)
        
self.input_buffer = np.zeros(filter_order)

    
def adapt(self, desired, reference):
        
"""
        
处理一个采样点,并更新滤波器。
        
参数:
            desired (float): 
期望信号 d(n),即主输入(如带噪语音)。
            reference (float): 
参考输入 x(n),与干扰噪声相关(如参考麦克风采集的噪声)。
        
返回:
            output (float): 
滤波器输出 y(n)
            error (float): 
误差信号 e(n),通常作为系统输出(降噪后的信号)。
        """
        
更新输入缓冲区:将新参考样本移入,最旧的样本移出
        
self.input_buffer[1:] = self.input_buffer[:-1]
        
self.input_buffer[0] = reference

        
计算滤波器输出:权重向量与输入向量的内积
        
output = np.dot(self.weights, self.input_buffer)

        
计算瞬时误差
        
error = desired - output

        
# LMS核心:更新权重向量-input_buffer 参考信号序列
        
self.weights += self.mu * error * self.input_buffer

        
return output, error

    
def filter(self, desired_signal, reference_signal):
        
"""
        
批量处理整个信号序列。
        
参数:
            desired_signal (np.array): 
期望信号序列。
            reference_signal (np.array): 
参考信号序列。必须与desired_signal长度相同。
        
返回:
            output_signal (np.array): 
滤波器输出序列(预测的噪声)。
            error_signal (np.array): 
误差信号序列(估计的干净信号)。
            weights_history (np.array): 
权重向量的历史记录,用于分析收敛过程。
        """
        
n_samples = len(desired_signal)
        output_signal = np.zeros(n_samples)
        error_signal = np.zeros(n_samples)
        
可选:记录权重变化,用于调试和分析
        
weights_history = np.zeros((n_samples, self.order))

        
for in range(n_samples):
            output_signal[i], error_signal[i] = 
self.adapt(desired_signal[i], reference_signal[i])
            weights_history[i, :] = 
self.weights

        
return output_signal, error_signal, weights_history


def test_lms_basic():
    
"""基础测试:滤除一个正弦波干扰。"""
    
np.random.seed(42)  确保结果可复现
    
Fs = 1000 采样率
    
t = np.arange(01.0/ Fs)  # 1秒时长

    # 
生成干净信号(我们想保留的): 10Hz正弦波
    
clean = 0.5 * np.sin(* np.pi * 10 * t)
    
生成干扰噪声: 50Hz正弦波
    
noise = 0.8 * np.sin(* np.pi * 50 * t)
    
主输入:干净信号与噪声的混合
    
desired = clean + noise
    
参考输入:我们得到的噪声参考,可能与实际噪声有幅度和相位差异
    # 
这里模拟一个简单的线性失真:幅度变化+加一点随机扰动
    
reference = 1.2 * noise + 0.05 * np.random.randn(len(t))

    
创建并应用LMS滤波器
    
lms = LMSFilter(filter_order=32step_size=0.02)
    
我们关心的是error_signal,即降噪后的输出
    
_, error_signal, weights_history = lms.filter(desired, reference)

    
可视化结果
    
fig, axes = plt.subplots(31figsize=(108))
    axes[
0].plot(t, desired, 'b'alpha=0.7label='带噪信号(Desired)')
    axes[
0].plot(t, clean, 'r--'linewidth=2label='原始干净信号(目标)')
    axes[
0].set_ylabel('幅度')
    axes[
0].set_title('输入信号对比')
    axes[
0].legend()
    axes[
0].grid(True)

    axes[
1].plot(t, error_signal, 'g'label='LMS输出(Error)')
    axes[
1].plot(t, clean, 'r--'linewidth=2label='原始干净信号')
    axes[
1].set_ylabel('幅度')
    axes[
1].set_title('降噪效果对比')
    axes[
1].legend()
    axes[
1].grid(True)

    
绘制某个权重系数的收敛过程
    
axes[2].plot(weights_history[:, 5], 'm')  跟踪第6个权重的变化
    
axes[2].set_xlabel('采样点')
    axes[
2].set_ylabel('权重值')
    axes[
2].set_title('滤波器权重收敛过程(示例: w[5])')
    axes[
2].grid(True)

    plt.tight_layout()
    plt.show()

    
计算并打印性能指标:均方误差(MSE)改善
    
mse_before = np.mean((desired - clean) ** 2)
    mse_after = np.mean((error_signal - clean) ** 
2)
    
print(f"降噪前MSE:{mse_before:.6f}")
    
print(f"降噪后MSE:{mse_after:.6f}")
    
print(f"MSE改善{10 * np.log10(mse_before / mse_after):.2f} dB")


if __name__ == "__main__":
    test_lms_basic()


来源:NVH振动噪声
Abaqus振动pythonUMLMS声学材料NVH控制DAP
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2026-05-21
最近编辑:3月前
NVH仿真试验
本科 NVH整车性能开发
获赞 127粉丝 217文章 40课程 16
点赞
收藏
作者推荐
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈