ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LOFAR谱线谱增强与特征提取:从强噪声中锁定目标信号

LOFAR谱线谱增强与特征提取:从强噪声中锁定目标信号 在声学信号处理尤其是水下目标的被动识别领域LOFAR谱几乎是绕不开的第一个工具。低频分析记录谱说白了就是把被动接收到的宽带声信号做短时傅里叶变换用时间、频率、强度三张图把目标“画”出来。可很多刚上手的朋友都有同一个困惑程序跑完spectrogram也能画出来但图上全是噪点该有的线谱根本看不出来更别说拿它去做分类识别了。这篇文章我打算沿着一条完整的处理链路讲线谱怎么产生、怎么在强噪声里增强、怎么把增强后的谱图变成分类器能用的特征向量以及整套流程在Matlab里怎么一步步落地。适合正在做水声信号分析、振动故障诊断或者刚接触被动声识别需要搭建算法原型的工程师和研究生参考。我先把结论放在前面LOFAR谱分类识别的核心不是算法多炫而是线谱增强和特征提取这两步做得实不实。谱图质量不行后面接再厉害的深度网络也是白搭。下面按我平时做项目的顺序把每个环节的细节和踩过的坑都铺开讲。1. 先弄懂LOFAR谱线谱是哪来的又藏在哪儿1.1 LOFAR谱的本质一张随时间滚动累积的功率时频图LOFAR谱的数学本质就是短时傅里叶变换STFT后取模平方得到的功率谱密度序列。把一段长时间信号切成一帧一帧每帧加窗做FFT得到这一帧的功率谱然后按时间顺序排起来就构成了一张“频率-时间-强度”的三维图。因为目标自身的辐射噪声里包含大量稳定的单频分量这些分量会在图上形成一条条垂直的亮线专业上叫“线谱”。这张图能做什么完全取决于线谱能不能被看清。以水面和水下运动目标的辐射噪声为例它们的噪声主要由三部分组成宽带连续谱、窄带线谱、以及瞬态冲击成分。连续谱来自流噪声、湍流边界层等大致随频率升高而降低线谱则来自螺旋桨轴频、叶频及其谐波、各种旋转机械的振动基频和谐波。线谱频率稳定、能量集中就像人群里站了一排举着荧光棒的人隔老远你也能把他们辨认出来。分类识别的关键就是把这排“荧光棒”从噪声背景里捞出来。所以LOFAR谱的“显像”能力取决于两个方向的分辨率频率方向要能区分邻近的线谱时间方向要能跟踪线谱的缓慢变化。这两者是互相制约的。1.2 线谱的物理来源轴频、叶频和机械振动谐波线谱不是随便冒出来的它有明确的物理对应关系。螺旋桨转动时轴系每转一圈会产生一次周期扰动对应频率就是轴频一般为几赫兹到几十赫兹。螺旋桨本身有N个叶片每个叶片划过流场都会产生一次扰动所以还存在一个N倍轴频的叶频分量。再加上轴系、主机的各种不平衡和齿轮啮合会产生一系列间隔等于轴频或转频的谐波族。这些分量在线谱上有两个非常明显的特征一是频率位置稳定短时间内几乎不漂移二是谐波结构有规律谱线上各峰之间的频率间隔往往等于某个基频。这两个特征恰恰是做分类识别时最靠得住的“指纹”。例如A类目标的轴频基频在你分析频段内出现5根谐波B类目标只出现2根这两类目标在LOFAR谱上的差异就很明显。我后面讲的线谱增强和特征提取本质上是围绕这两个物理特征来设计的。1.3 画LOFAR谱的核心参数窗长、重叠率和窗函数刚开始做LOFAR谱的人最容易忽略的就是参数选择。频率分辨率由FFT点数决定Δf fs / Nfft而时间分辨率由帧移决定Δt Nfft × (1 - overlap) / fs。窗长越长频率分辨率越细但谱图在时间方向会被平均得越模糊快速变化的瞬态就看不到了。反之窗长短了瞬态清楚了但两个靠得很近的线谱就可能糊成一团。我常用的参数组合在采样率fs10kHz、关心频段在500Hz以内时Nfft取4096或8192窗函数用汉宁窗重叠率取75%。这样频率分辨率能做到1~2.5Hz时间分辨率在0.1秒左右既能把几十赫兹的线谱分清楚又能跟上目标状态的变化。窗函数方面汉宁窗主瓣宽度适中、旁瓣衰减快是最稳妥的选择矩形窗旁瓣太高容易出现频谱泄漏把强线谱的能量“甩”到旁边的频点上形成假峰不推荐用于LOFAR分析。2. 线谱增强从“看不见”到“无处可藏”2.1 多帧非相干积累最朴素但最有效的降噪手段拿到一帧功率谱线谱很可能淹没在噪声里。因为单帧谱的噪声起伏很大尤其是海洋环境噪声近似服从高斯分布时单帧功率谱噪声波动范围能达到十几个dB。这时候最直接的办法就是对同一时间段内的L帧功率谱做平均。原理说穿了不复杂线谱分量在时间上是相干的功率不会因为平均而衰减太多而噪声是随机的正负起伏在平均过程中会互相抵消。若各帧噪声独立同分布M帧平均后噪声功率方差近似降为原来的1/M信噪比改善约10log10(M) dB。我用16帧平均时实测低信噪比段落的线谱增益基本能到8~10dB虽然没有理论值12dB那么高但已经能把很多被噪声盖住的弱线谱拉出背景。这里有个细节平均帧数不是越多越好。目标状态在变比如航速调整导致轴频发生缓慢漂移平均时间过长会把线谱“抹”成一段宽包络反而降低频率测量精度。建议平均时间控制在2~10秒区间具体根据目标的机动特性来调。2.2 自适应线谱增强器从时域把线谱“抽”出来多帧平均属于频域的非相干处理还有一种思路是在时域做自适应线谱增强器也就是常说的ALEAdaptive Line Enhancer。它的结构是一个基于LMS算法的自适应预测器把输入信号延迟D个采样点后作为期望信号用自适应滤波器去预测当前输入。为什么这个方法对线谱有效因为线谱是周期信号有确定的相关性延迟一定点数之后依然能预测出来而宽带噪声相关性很弱延迟几个点之后就完全不相关了。滤波器会逐渐调整权值最终输出里主要保留窄带线谱成分宽带噪声被抑制。ALE的输出再送去做FFT线谱的突出程度会明显提升。ALE有两个关键参数延迟D和步长μ。D太小噪声还没去相关增强效果差D太大会破坏周期信号本身的相位关系。实际我一般取D1~5个采样点步长μ要满足收敛条件μ 2 / (3 × 输入信号功率)。步长太大滤波器震荡步长太小收敛慢线谱还没抽出来目标都跑了。在Matlab里可以直接用dsp.LMSFilter等工具箱组件手写一个延迟模块加滤波器核心也就十几行代码。2.3 谱图形态学增强用图像处理思路清理LOFAR背景还有一种容易被忽略的增强手段把LOFAR谱图当成灰度图像用形态学滤波把连续谱背景“铲平”。水下运动目标的辐射噪声里宽带连续谱通常变化缓慢在频率轴上表现为一个大范围渐变的背景层而线谱是窄而亮的“脊”。用顶帽变换可以把这种缓慢变化的背景减掉只留下局部突出的结构。Matlab里可以直接用imtophat。需要先设定一个结构元素线谱的几何特征是细长竖线所以结构元素一般选沿频率方向的长条比如strel(line, 21, 90)长度21、方向90度这样能匹配垂直方向的窄带结构。顶帽变换对强背景抑制效果很明显原先被连续谱压暗的弱线谱会显眼不少。但要注意结构元素长度不要超过最窄谐波间隔的一半否则两个相邻线谱会被当成一个整体处理掉。3. 特征提取把线谱变成能“说话”的数字3.1 线谱检测的三条准则幅度、稳定性和谐波结构谱图增强完之后下一步是把线谱找出来这一步直接决定后面特征的质量。我的检测流程里通常会设置三条准则缺一不可。第一是幅度准则。在某个频点功率值要明显高于局部噪声底。噪声底可以用该频点附近一个频带内的中位数或均值来估计。高于噪声底6dB以上的峰才考虑列为候选线谱。注意这里要用局部噪声底不能用整段谱的平均因为噪声谱本身不平坦低频段高、高频段低用全局阈值会把低频噪声误判成线谱。第二是稳定性准则。线谱之所以叫“线”就是因为它在足够长的时间里持续存在。如果一个峰只在一两帧里出现大概率是瞬态干扰或者随机噪声尖峰。我一般要求候选频点在时间维度上至少连续或间歇出现在60%以上的帧中才会保留。这个准则能杀掉大量假峰。第三是谐波结构准则。真实的机械线谱不是孤零零一根通常成族出现族内各谱线间隔一致等于某个基频。对候选谱峰做两两差频统计如果某几个峰之间的频差重复出现基本可以确认它们来自同一个谐波族。这个准则对抑制随机干扰特别有效因为噪声产生的峰值频差一般是杂乱的不可能形成规律的等差序列。3.2 基频和叶频的估计方法检测出候选线谱集合后需要估计轴频和叶频。最笨但有效的方法是“差频直方图”。把候选线谱频率两两相减统计各差频出现的次数。由于谐波族内任意两根谱线的间隔都是基频的整数倍所以真实基频对应的差频出现次数一定是最多的之一。举个例子如果检测到频率为23、46、69、92、115Hz的谱线两两差分会得到23、46、69、92以及46、23、46、69等其中23Hz这个差值出现了至少4次。直方图的峰值自然就落在23Hz附近这就是基频的估计值。叶频一般是最强的那根谱线频率或者基频乘以叶片数。可以先估计出基频然后在基频整数倍位置搜索能量最高的峰。如果基频很低只有几赫兹频谱分辨率不够时差频直方图的分辨率也会很粗。这时候可以用Zoom-FFT或线性调频Z变换把目标频段细化或者做抛物线插值来估计谱峰的真实位置。3.3 分类特征向量怎么搭才稳定特征提取的最终输出是一个向量同一类目标在不同航速、不同距离下这个向量要尽量稳定同时不同类目标之间又要有区分度。我常用的特征组合大概有十来个分三组。第一组是线谱本身的结构特征包括检测线谱的总数Nline、最强线谱的频率Fmax、最强线谱信噪比SNRmax、基频估计值F0、谐波数量Nharm。第二组是谱形统计特征包括频谱重心、频谱集中度、谱熵。频谱重心表示能量集中在哪个频段谱熵可以度量谱分布的“乱”与“整”线谱越规整谱熵越低。第三组是稳定性特征比如最强线谱在时间维上的频率抖动方差。因为不同物理结构的振动源其频率稳定性差异很大有的漂移小于0.1Hz有的则在几赫兹范围摆动这个特征在分类时往往很有区分度。搭建特征向量时我的原则是宁多勿缺但进了分类器之前一定要归一化。比如Fmax是几十到几百赫兹谱熵是0到1之间的小数量纲差异很大直接喂给SVM会让大数值特征主导梯度小数值特征等于没参与。归一化用z-score即可Matlab里zscore函数一行搞定。这里还有一个容易被忽略的点特征提取器最好做成流水线函数输入一段时域信号输出一个定长向量。这样不管是后续换数据集、做批量测试还是给分类器造训练样本都能保持一致性。4. 分类识别从特征向量到型号结论4.1 经典分类器选型SVM和KNN怎么选特征向量拿到手之后分类器选型看数据规模。如果每类只有几十上百个样本深度学习基本跑不出效果老老实实用SVM或者KNN。SVM的优势是高维小样本下泛化能力强Matlab里多分类可以直接用fitcecoc内部做一对一或一对多的SVM组合不用自己写OvO那套逻辑。核函数一般先在linear上试如果交叉验证分数上不去再换rbf并调BoxConstraint和KernelScale。KNN的优势是可解释性好适合做基线。你训练完KNN可以直接把决策边界画出来看特征分布不合理一眼就能发现。但它对特征尺度敏感而且样本不均衡时大类的样本容易“淹没”小类。KNN里的k值我一般取5~11之间的奇数太小容易过拟合太大边界太平滑。4.2 样本均衡、归一化与交叉验证的实际操作分类识别的效果很大程度不取决于分类器而取决于训练数据怎么组织。水声目标在低航速、高航速下的LOFAR谱差异很大如果训练集里全是某一航速的数据测试时来一批完全不同特征的样本准确率会很难看。所以在做数据集前我习惯先按目标类型分层再在每层内随机划分训练集和测试集保证每个类型在训练集里都有足够代表。样本不均衡是另一个高频问题。某些类容易采到大量数据某些类只有零星几条。这时候要么对多数类降采样要么对少数类用SMOTE合成新样本千万不要直接拿原始比例去训练。评价指标也不能只看总准确率要看混淆矩阵。尤其是声学目标这种类间相似度高的问题混淆矩阵里哪两个类经常被搞混比总体准确率高几个点重要得多。4.3 走向深度网络CNN和BiLSTM用在什么地方如果数据和算力都允许可以用深度网络做端到端识别。一种做法是把LOFAR谱图作为单通道图像用CNN分类。谱图预处理和普通图像略有不同要先归一化到0~1颜色映射改成灰度避免多余的颜色信息干扰网络。Matlab里可以直接调用trainNetwork搭建一个由卷积层、池化层、全连接层构成的小型网络或者用预训练的GoogLeNet做迁移学习。另一种做法是用BiLSTM处理序列特征。LOFAR谱在时间维上包含目标的机动信息同一个目标改变航速时线谱频率随之慢变。把每一帧的线谱特征构成时间序列输入给双向LSTM网络能同时看到历史和未来帧的上下文对识别机动状态比较有效。Matlab的Deep Learning Toolbox里有lstmLayer配合sequenceInputLayer和fullyConnectedLayer就能搭起来。需要注意深度网络需要的数据量比传统方法大一个数量级小样本场景下效果反而不如SVM。5. Matlab完整流程实战从仿真信号到识别结果一条龙5.1 准备一段带噪声的仿真水声信号为了把整个流程串起来我先生成一段仿真信号。设采样率10kHz时长20秒包含一个基频23Hz的谐波族、一个92Hz的叶频分量再加宽带随机噪声。信号里埋入的线谱信噪比故意放低大约在-5dB左右模拟比较恶劣的环境。fs 10000; T 20; t (0:1/fs:T-1/fs); x 0.5 * randn(size(t)); % 宽带背景噪声 % 基频23Hz幅度递减的6次谐波 f0 23; for k 1:6 freq f0 * k; amp 0.5 / k; x x amp * sin(2*pi*freq*t rand*2*pi); end % 叶频92Hz幅度稍高一些 x x 0.65 * sin(2*pi*92*t rand*2*pi);这段代码里有意识地让噪声幅度大于多数谐波后面看增强效果会更明显。实际拿到真实数据时建议先把数据读进来做直流去除和带通滤波避免低频水流噪声和传感器偏置把线谱盖住。5.2 生成LOFAR谱并做多帧平均增强生成LOFAR谱用spectrogram函数最方便。这里Nfft取4096汉宁窗75%重叠。得到结果后把前50帧大约5秒做平均得到一段增强后的平均功率谱。Nfft 4096; win hann(Nfft, periodic); noverlap Nfft * 0.75; [S, F, Tp] spectrogram(x, win, noverlap, Nfft, fs); Sdb 10*log10(abs(S).^2 eps); Savg mean(abs(S(:, 1:50)).^2, 2); Savgdb 10*log10(Savg eps);画图时我会把LOFAR谱和平均谱放在一个图里先直观看看线谱位置。参数上Nfft的选择要保证频率分辨率能区分23Hz和它的谐波4096点对应的Δf约2.44Hz完全够用。5.3 谱图形态学增强与线谱检测对LOFAR谱图做顶帽变换前先要把Sdb截取到关心频段比如0~500Hz。然后用沿频率方向的结构元素做顶帽运算把连续谱背景去掉。线谱检测用findpeaks峰值突出度比单纯峰值高度更靠谱MinPeakProminence设为噪声底上方一个固定值。Fc F 500; Sdb_crop Sdb(Fc, :); Fc_ax F(Fc); % 顶帽变换去背景 se strel(line, 21, 90); Sdb_tophat imtophat(Sdb_crop, se); % 沿时间平均后再做峰值检测 avg_tophat mean(Sdb_tophat, 2); % 局部噪声底取整段的中位数 noise_floor median(avg_tophat); [peaks, locs] findpeaks(avg_tophat, ... MinPeakHeight, noise_floor 6, ... MinPeakDistance, round(10 / (fs/Nfft)), ... MinPeakProminence, 3); candFreq Fc_ax(locs);这里的MinPeakDistance参数意味着两根线谱之间至少间隔10Hz用来过滤掉主瓣展宽造成的相邻伪峰。若两个真实线谱确实靠得很近这个参数要相应调小。5.4 基频估计与特征向量构建检测出候选线谱后用差频直方图估计基频。对候选频率做两两差频统计出现次数出现次数最多的差频作为基频候选。因为谐波数量多时会随机产生一些倍频差需要再和候选线谱的实际位置做一次验证。diffFreq []; for i 1:length(candFreq) for j i1:length(candFreq) diffFreq [diffFreq, abs(candFreq(j) - candFreq(i))]; end end edges 0:0.5:100; [Ncount, edgesOut] histcounts(diffFreq, edges); [~, idx] max(Ncount); f0_est (edgesOut(idx) edgesOut(idx1)) / 2;得到基频后特征向量按前面第3.3节的内容组装。先算线谱数量、最强谱峰的频率和信噪比、谐波个数再计算频谱重心和谱熵。这一组特征归一化后就可以送入分类器。5.5 训练SVM分类器的完整流程假设历史数据里已经有一批打标好的特征矩阵feat对应标签label。训练和评估的代码很简洁% 特征归一化 featNorm zscore(feat); % 划分训练测试 cv cvpartition(label, HoldOut, 0.3); trainIdx training(cv); testIdx test(cv); % 训练多分类SVM mdl fitcecoc(featNorm(trainIdx,:), label(trainIdx), ... Learners, svm, Coding, onevsone); % 测试 pred predict(mdl, featNorm(testIdx,:)); confMat confusionmat(label(testIdx), pred);混淆矩阵出来后我习惯再算一下每类的召回率和精确率而不是只看对角线上的数字。如果发现某两类总被搞混就回头去看这些样本的LOFAR谱图往往能发现特征构建时漏掉了关键的区分信息。6. 工程落地中的常见问题与避坑手册6.1 常见问题速查表现象可能原因排查与解决建议线谱区附近出现横条纹亮带目标状态变化导致频率漂移或帧长过长时间分辨率不足缩短窗长到0.5~2秒增加重叠率观察漂移是否缓解线谱检测出大量密集伪峰矩形窗或旁瓣泄漏导致的频谱泄漏换汉宁窗或布莱克曼窗检查最强线谱的动态范围增强后线谱依然不清晰平均帧数不够或信号本身信噪比过低增加到30~50帧平均结合ALE时域增强基频估计总是差几赫兹频谱分辨率不足峰值位置量化误差对峰值附近做抛物线插值或提高FFT点数分类准确率卡住不涨特征里混入大量不稳定噪声特征或样本不均衡检查特征稳定性重新做样本分层划分必要时做特征筛选SVM训练特别慢样本量增加后仍用rbf核且没做特征缩放先做标准化线性核能解决就用线性核6.2 频率分辨率不够时的额外手段碰到低频线谱比如基频只有5Hz而Nfft4096在10kHz采样率下分辨率才2.44Hz根本分不清5Hz和7.44Hz的峰。这时有两个选择一是增加Nfft到16384分辨率降到0.6Hz代价是时间分辨率恶化二是用Zoom-FFT或线性调频Z变换只细化目标频段在保持时域分辨率的同时把频率细节拉出来。Matlab里实现CZT很方便直接调用czt函数指定关心的频率范围和分辨率。我通常在发现候选线谱落在某些频段但并不确定时用CZT精确定位计算量比全带大FFT要省不少。6.3 谱图过大导致运行特别慢LOFAR谱动辄上百帧、上千频点如果循环里逐帧做STFT跑起来特别慢。我的建议是第一版直接用spectrogram函数它对计算做了优化如果还需要更快可以只对目标频段做带通滤波降采样降低采样率后再做STFT计算量会下降一两个量级。如果项目对实时性要求高还可以把循环密集的线谱检测部分写成MEXMatlab里调用C编译后的函数可以明显提速。顺带提一句数据读取时的坑很多采集系统会把ADC数据以16进制补码形式保存读进Matlab时一定要注意字节序和符号位处理。看似简单的一个步骤我见过不止一次因为数据按无符号整数读入导致后面所有谱图都出现一条巨大的直流分量怎么滤波都消不掉。6.4 样本量少时的一些实操建议真实场景里打标的声学样本通常很缺。遇到这种情况我一般先对历史谱图跑一遍无监督聚类比如kmeans把谱图粗分成若干簇再从每个簇里挑一部分人工确认标签。这样标注效率比自己从头翻谱图高很多。分类器方面小样本下SVM配线性核、留一交叉验证是比较稳的组合不要去碰深度网络参数太多容易在几十个样本上直接过拟合到“整个训练集都能背下来”。再说一个很实际的小技巧感觉特征区分度不够的时候把增强前后的平均谱图打印出来肉眼先看一遍。线谱分析这个领域视觉判断往往是最快的排查手段。有些问题在波形图上很隐蔽但在LOFAR谱图上一眼就能看出是哪个频段的干扰。我自己在项目里踩过最大的坑不是算法不会写而是参数不匹配导致线谱检测把“噪声峰”当成“信号峰”后面所有特征都被带偏。后来定下一个习惯每一批数据进来先随机抽几段画平均谱人工确认参数下检测的线谱位置是否符合物理常识再批量跑流程。多花这十分钟后面省下的处理时间能翻倍。整个流程做到这里LOFAR谱的增强和特征提取就已经不是黑盒了。你完全可以按照上面这段链路把仿真信号换成自己的实测数据把基频、谐波数量这些特征按实际目标类型重新设计一组然后搭出属于自己的分类识别原型。实践的时候记得一个原则宁可把增强和检测做扎实也不要一上来就用复杂的分类器弥补前面步骤的粗糙。数据干净了最简单的线性SVM也能给出很可靠的结果。
返回列表