我已经有一段时间没有进行任何信号处理了,但是我完全被归一化最小均方滤波器实现中的不稳定性和偏差所困扰。
我检查了通常的事情:
- 我实际上是否接近收敛下限(测试信号中 AWGN 的方差)?不。
- 我的步长是否低于(其中只是用作瞬时估计的信号的外积)?是的。
- 我的窗口过去样本的点积是否使用增加延迟指数的约定(“反向”顺序)?是的。
- 当我计算预测值时,我使用的是以前的信号索引,而不是当前的吗?是的。
我通过实现一个简单的一键过滤器缩小了我的问题。我的参考是 Haykin's Adaptive Filter Theory第 324 页上的算法,我正在使用第 280 页上的相同测试条件:
- 输入:一阶 AR 过程,,噪声方差
- 试验次数:100 次试验
- 信号长度:500 个样本
错误
根据 Haykin 的说法,在少于 100 个样本后,我应该低于这不是我所看到的,但我相信它必须是基本的。
以下是 MMSE 和平均绝对滤波器系数误差,可视化:
MMSE 不会呈指数下降,并且滤波器系数与实际 AR 过程值的距离永远不会小于 2。
而事实上,MMSE 仍然比信号末端附近的噪声方差要远得多:
[10.260998119102881, 16.060967587632792, 41.72963567568045, 49.232814770283696, 50.56247908944245, 84.29056731939356, 99.74962522053087, 74.94509263319398, 61.55708377260941, 43.79321013379245, 47.68084407515727, 51.84551183735604, 23.977556992678352, 23.691841969230886, 15.292586007185905, 12.710425182987175, 14.689863202271942, 15.03357374836029, 16.305144820997945, 21.770075252230768, 16.501486407946132, 21.62300216817481, 15.461623713499273, 26.354991476964795, 28.001121132610393, 21.632068009342056, 15.812522324768985, 15.522990356558456, 53.24514663841896, 9.36613637386399, 52.24856602614516, 98.50333720012102, 251.59105479441695, 193.85612892514402, 124.53671103656986, 159.16459102635278, 82.2544192379602, 50.25510472853462, 67.03420998875504, 9.59758344071307, 9.770861267272064, 21.975670899135086, 28.84699022842896, 29.070465314026674, 15.05395348320232, 20.20596174124456, 30.609319675498526, 14.396998393433874, 17.654986587869196, 9.664719322902583]
过滤代码
为了产生上述结果,我尝试实现最简单的 1-tap NLMS 过滤器,如下所示。
extern crate rand;
use std::f64::EPSILON;
use rand::distributions::{IndependentSample, Normal};
extern crate gnuplot;
use gnuplot::{Figure, Caption, Color};
fn main() {
let trial_count = 100;
let signal_len = 500;
let noise_std_dev = 0.96761;
// AR process coefficient [n-1]
let process = [-0.99];
let mut rand_gen = rand::OsRng::new().unwrap();
let mut mmse: Vec<f64> = vec![0.0; signal_len];
let mut avg_filt_err: Vec<f64> = vec![0.0; signal_len];
let noise_dist = Normal::new(0.0, noise_std_dev);
for _ in 0..trial_count {
let mut sig_vec: Vec<f64> = Vec::with_capacity(signal_len);
// Zero padding to start noise process
sig_vec.push(0.0);
for n in 1..signal_len {
let noise = noise_dist.ind_sample(&mut rand_gen);
let p1 = if n > 0 {
-process[0]*sig_vec[n-1]
} else {
0.0
};
sig_vec.push(noise + p1);
}
let step_size = 0.05;
let mut pred_vec: Vec<f64> = Vec::with_capacity(signal_len);
let mut filt_coef: f64 = 0.0;
// Zero padding to start filter process
pred_vec.push(0.0);
for sig_ind in 1..signal_len {
let pred = filt_coef * sig_vec[sig_ind - 1];
pred_vec.push(pred);
let err = sig_vec[sig_ind] - pred;
mmse[sig_ind] += err.powi(2) / trial_count as f64;
filt_coef += step_size * sig_vec[sig_ind - 1] * err /
(sig_vec[sig_ind - 1].powi(2) + EPSILON);
avg_filt_err[sig_ind] += (process[0] - filt_coef).abs() / trial_count as f64;
}
}
let x: Vec<usize> = (0..mmse.len()).collect();
let mut fg = Figure::new();
fg.axes2d()
.lines(&x, &mmse, &[Caption("MMSE"), Color("black")]);
let mut fg2 = Figure::new();
fg2.axes2d()
.lines(&x, &avg_filt_err, &[Caption("Average filter error"), Color("red")]);
fg.show();
fg2.show();
}