☰
HOSA工具箱3/2谱分析:从双谱到高阶谱故障诊断
2026/10/9 18:28:47 网站建设 项目流程

简介:这是一套高阶谱分析(HOSA)工具箱的实现与配套学习资源,面向信号处理、机械故障诊断、通信及生物医学等领域的研究者,用于计算高阶累积量与谱,揭示非线性、非高斯信号的统计特征。压缩包共147个文件,约2.74MB,主体为m格式的MATLAB函数与演示脚本,同时包含mat数据文件、dat示例数据以及asv自动保存文件,另附pdf/doc使用说明和dll编译组件,便于直接运行与二次开发。资源提供一至四阶谱计算、多通道联合分析、GUI可视化、数据预处理与结果评估等完整功能模块,配合太阳黑子、猞猁数量等经典数据集,可按示例脚本快速上手。已有112人浏览学习,适合需要开展高阶谱实验或课程设计的高年级本科生、研究生与工程师。

1. 为什么需要3/2谱:功率谱看不到的信号耦合,HOSA工具箱来补

功率谱就像把一个信号拍扁了看,只告诉你哪个频率上有能量,却把两个频率之间的“勾结”全藏了起来。我在处理某公司齿轮箱振动数据时,设备有明显的调制故障,功率谱上却只有几个孤零零的峰,压根看不出耦合关系。换成双谱分析后,耦合频率组合直接以谱峰形式跳出来。做这种分析,MATLAB 的 HOSA 工具箱是绕不开的一套工具。这份 hosa.rar 资源包含了完整的 HOSA 工具箱代码,还附带了 3/2 谱对照分析示例——把二阶谱(功率谱)和三阶谱(双谱)放在一起,让信号的非线性特征一目了然。适合做振动故障诊断、生物医学信号、水声和雷达信号处理的一线工程师和相关专业学生,解压后添加路径,就能直接复用双谱估计、累积量计算这些底层函数。

2. HOSA 工具箱的核心:高阶谱理论与函数地图

2.1 从功率谱到高阶谱:双谱和它背后的数学直觉

功率谱的数学定义是自相关函数 r(τ) 的傅里叶变换,它只保留了信号的幅度-频率关系,相位信息被完全丢弃。因此,遇到相位耦合(比如二次相位耦合,QPC)这类现象时,功率谱只会显示三个独立的谱峰,但无法告诉你这三个峰之间是否存在因果与驱动关系。

双谱(Bispectrum)是三阶累积量的二维傅里叶变换,定义式是:

B(f1, f2) = E[X(f1) · X(f2) · X*(f1+f2)]

这里 X(f) 是信号的傅里叶系数,E[·] 表示期望。注意到这个式子比功率谱多了一个频率维度,并且引入了 X*(f1+f2) 这一项,它直接包含了频率相加后的相位关系。如果信号中同时存在 f1、f2、f1+f2 三个频率分量,且相位满足 φ(f1) + φ(f2) = φ(f1+f2),那么 (f1, f2) 位置的双谱会出现明显峰值;如果相位随机独立,双谱幅值则趋近于零。这个性质让双谱天然适合检测非线性耦合,以及抑制高斯分布的噪声和干扰。

为什么标题里叫“3/2谱”?我个人的理解是:这套工具箱里既给出二阶谱(功率谱),也给出三阶谱(双谱),两个维度一起用,所以资源名写成“3/2谱”。实际工程中,双谱也常被当作“三阶谱”来理解,而双相干谱(Bicoherence)则是双谱除以两个功率谱的几何平均,数值落在 [0,1],用来度量耦合强度。这套工具在高阶统计量分析里属于标准配置。

双谱还有一个容易忽略的对称性:对实信号而言,B(f1,f2) 在三角区域 f1 ≥ f2 ≥ 0 且 f1 + f2 ≤ fs/2 内可以完全表示整个双谱,其他区域的值都能通过对称性推导出来。这意味着你不需要绘制整个二维平面,只需要看主三角区域,能省一半以上计算量。在 HOSA 工具箱的绘图 demo 里,你会看到很多图只画了三角区域,就是这个原因。

从相位关系来看,功率谱丢失的相位信息,双谱完整保留。比如两个频率分量的相位差如果是固定的,双谱相位谱上会呈现规律的条纹;如果相位是随机抖动的,双谱幅值就会显著衰减。这个特点使得双谱能够区分“真正的相位耦合”和“偶然一起出现”的频率组合,后者往往是设备松动、非平稳转速造成的假象。

2.2 工具箱里有什么:文件清单与三个必用函数

解压 hosa.rar 后,主目录一般是 hosa 文件夹,里面是一堆 .m 文件。下表列出我在项目里最常碰到的几个函数:

文件/目录作用
bispecd.m直接用 FFT 方法估计双谱,速度较快
bispeci.m用间接法估计双谱,适合小样本、低信噪比
bicoher.m计算双相干谱,输出归一化的耦合强度
cum3est.m直接估计三阶累积量,是双谱的基础
cum2est.m估计二阶累积量,相当于自相关
cum4est.m估计四阶累积量,可用于更高阶谱分析
harmest.m估计谐波信号参数,带幅值和相位
demo/官方示例脚本,包含 QPC 生成和双谱估计的完整流程

这些函数并不是孤立的:cum3est 为 bispecd 提供三阶累积量,bispecd 再对累积量做二维 FFT;bicoher 内部会调用多次 cum2est 来估计功率谱。所以如果你想改算法,可以从底层 cum3est 入手;如果只是常规分析,直接用 bispecd 或 bicoher 就够了。

拿到工具箱以后,第一步永远是加路径。我一般把 hosa 文件夹复制到 D 盘某个固定目录,然后执行:

% 把 hosa 工具箱加入 MATLAB 工作路径 addpath('D:\tools\hosa'); % 验证关键函数是否被正确识别 exist('bispecd', 'file')

addpath 的作用是让当前 MATLAB 会话能直接调用 hosa 目录下的函数,不需要把文件复制到当前工作目录。exist('bispecd','file') 返回 2 表示找到 .m 文件,返回 0 就说明路径没加对。这里有个容易忽略的点:hosa.rar 解压后可能内层还套一层目录,比如 hosa/hosa 或者 hosa/toolbox,addpath 必须指向真正包含 bispecd.m 的那一层。Windows 系统下路径分隔符用反斜杠,Linux/Mac 下用正斜杠。

另外,官方工具箱里的函数名都是小写,和 Windows 文件系统不冲突,但如果你在 MATLAB 里用不同大小写调用,可能会出现“找不到文件”的情况。我就遇到过一次,写了 Bispecd 导致报错,改成 bispecd 之后立刻正常。这是初学者经常掉进去的坑。

一个测试习惯:每次加完路径,运行help bispecd,能弹出帮助信息就说明工具箱可用。如果报“未定义”,先检查路径,再检查函数名大小写。

% 在命令行查看帮助,确认参数顺序 help bispecd

帮助信息里会列出 nfft, wind, nsamp, overlap, flag 这些参数的用法。完整函数列表可以用 dir 查看:

% 列出 hosa 目录下所有 .m 文件 dir('D:\tools\hosa\*.m')

在入手任何一个函数之前,我强烈建议先运行 demo 文件夹里的脚本。demo 脚本里包含了信号生成、参数设置、绘图和保存的完整流程,直接改数据路径就能套用到自己的数据上。许多看起来复杂的参数组合,在 demo 里会有明确注释。

三个必用函数里,bispecd 是最核心的。它适合中等长度数据(几千到几万点),FFT 分段平均能够抑制噪声。bicoher 是特征提取时的首选,因为它的输出在 [0,1] 之间,不用受信号幅度影响。cum3est 则是当你需要自己控制累积量滞后范围时才会用,比如分析短数据或者处理非平稳信号时,手动设置 nlag 比默认值更可靠。

3. 实战第一步:把数据送进双谱估计器

3.1 构造测试信号:二次相位耦合怎么造

为了验证双谱能不能抓出耦合,先构造一个带二次相位耦合(QPC)的合成信号。QPC 是指三个频率分量 f1、f2、f3=f1+f2,且相位满足 φ3=φ1+φ2。这种信号在齿轮箱磨损、谐波调制、电力系统谐波中非常典型。我们生成一个采样率 1000 Hz、长度 1024 点的信号:

fs = 1000; % 采样率(Hz) N = 1024; % 总采样点数 n = 0:N-1; % 离散时间索引 f1 = 50; f2 = 120; f3 = f1 + f2; % 三个频率 phi1 = 0.3; phi2 = 0.7; phi3 = phi1 + phi2; % 相位耦合关系 % 三个正弦分量叠加,附加少量高斯噪声模拟实测环境 x = cos(2*pi*f1*n/fs + phi1) + cos(2*pi*f2*n/fs + phi2) + ... cos(2*pi*f3*n/fs + phi3) + 0.1*randn(1,N);

这里的 phi3 被刻意设成 phi1+phi2,目的是制造一个强耦合。0.1*randn 是方差为 0.01 的高斯白噪声,用来模拟真实传感器噪声。注意 randn 每次运行结果不同,如果希望结果可复现,可在代码前加rng(10)。我用rng(10)固定随机数种子,这样别人复现时双谱图和我完全一致。

为什么要先用合成信号?因为真实数据里你永远不知道真正的相位关系是什么,也就无法验证双谱算出来的结果对不对。合成信号的耦合关系是已知的,如果双谱在预期位置出现峰值,说明整个处理和参数设置没问题,再切换到现场数据就有底了。

运行下面这段代码,先在频域看一眼这个信号:

% 验证信号包含的三个频率成分 X = fft(x); f = (0:N-1) * fs / N; plot(f, abs(X)); xlabel('频率 (Hz)'); ylabel('幅值');

结果应该是在 50、120、170 Hz 三个位置出现谱峰,但功率谱上它们彼此独立,看不出 170 是由 50 和 120 耦合出来的。这正是引入双谱的原因。

3.2 调用 bispecd 估计双谱并解读输出

HOSA 工具箱里最常用的双谱估计函数是 bispecd,直接基于 FFT 的分段平均。调用格式如下:

% 固定随机种子,保证可复现 rng(10); % 估计双谱 [Bspec, w] = bispecd(x, 256, 5, 0, 0, 'biased'); % w 是归一化频率向量,范围 0~1

参数含义:

  • x 是需要分析的信号,必须是实信号;
  • nfft=256 是 FFT 长度,也是双谱的频率分辨率;
  • wind=5 是双谱平滑窗的宽度,窗越大谱越平滑,但分辨率会下降;
  • nsamp=0 表示不额外分段,直接使用整段数据;
  • overlap=0 表示分段之间无重叠(此处由于 nsamp=0 而不生效);
  • flag='biased' 表示使用有偏累积量估计,这也是大多数场景下的默认选择,方差较小。

输出参数里,Bspec 是二维复数矩阵,元素是 (f1,f2) 处的双谱幅值;w 是归一化频率的向量,长度 nfft,实际频率为 w*fs。注意 Bspec 满足共轭对称性,我们通常只观察第一象限的部分。

如果运行过程中报“Undefined function 'bispecd'”,基本就是路径问题,回到 2.2 节检查 addpath。如果报“Error using .* Output argument 1 is not assigned”,多半是 nfft 设置过小或者 x 中有 NaN,需要先做数据清洗。

关于 nfft 的选择,我一般遵循一个经验:nfft 不要超过数据长度的 1/4。1024 点数据用 nfft=256,刚好让每个频带内有 4 个独立样本;如果 nfft 太大,比如 512,双谱图会充满虚假细节,反而看不清主峰。如果数据很短(比如只有 256 点),我建议 nfft 取 64,然后增加 wind 平滑窗到 7 或 9,用平滑来弥补短数据的方差。

3.3 绘制双谱图:等高线图与对数色标

双谱矩阵是复数值,直接看实部或虚部都不直观,一般取幅值或对数幅值。我习惯用等高线图表示,因为它能清楚显示峰值的坐标位置:

% 绘制双谱幅值的等高线图 figure; % w 已经归一化,乘以 fs 得到真实频率 contour(w*fs, w*fs, abs(Bspec), 16); xlabel('f1 (Hz)'); ylabel('f2 (Hz)'); title('双谱等高线图');

运行这段代码,应该能在 (50,120) 附近看到一个明显的谱峰,因为 f3=170 = 50+120,相位关系也满足耦合条件。而 (120,50) 等位置会出现对称的峰,这是因为双谱的共轭对称性。如果只想要主区域,可以用 axis 限制到 [0 fs/2]。

对数色标更适合观察动态范围大的双谱。把幅值取 log10 再画伪彩图:

% 对数幅值伪彩图 figure; imagesc(w*fs, w*fs, 10*log10(abs(Bspec)+eps)); axis xy; colorbar; xlabel('f1 (Hz)'); ylabel('f2 (Hz)'); title('双谱对数幅值图');

加 eps 是为了避免 log10(0) 出现无穷大。imagesc 默认屏幕像素坐标,axis xy 把它翻转到频率坐标方向。如果用 surf 画三维图,旋转视角后更能体现峰值形态,但打印论文时等高线图更常用。

我还会在图上把峰值位置标注出来,方便和理论值对照:

% 标注峰值坐标 [~, idx] = max(abs(Bspec(:))); [i1, i2] = ind2sub(size(Bspec), idx); hold on; plot(w(i1)*fs, w(i2)*fs, 'r*', 'MarkerSize', 10);

这段代码通过 abs(Bspec(:)) 找出全图最大幅值的位置,用红星标注。对于 QPC 信号,红星基本会落在 (50,120) 附近。如果落点偏差超过一个频率格(比如 nfft=256 时频率分辨率为 fs/nfft≈3.9 Hz),说明数据或者参数有问题,需要回头检查。

4. 特征提取:从双谱到双相干谱和相位谱

4.1 双相干谱(bicoherence):压制高斯噪声的特征

双谱的数值大小受信号幅度影响很大,不同工况下比较双谱幅值没有意义。工程上更常用双相干谱(bicoherence),它是双谱的归一化版本,取值在 0~1 之间,代表耦合强度。HOSA 工具箱里对应的函数是 bicoher:

% 计算双相干谱 [bic, w] = bicoher(x, 256, 5, 0, 0, 'biased'); % 绘制双相干谱等高线 figure; contour(w*fs, w*fs, abs(bic), 16); colorbar; xlabel('f1 (Hz)'); ylabel('f2 (Hz)'); title('双相干谱');

双相干谱的定义是 bic(f1,f2) = |B(f1,f2)|^2 / ( P(f1)·P(f2)·P(f1+f2) ),其中 P 是功率谱。由于分母做了归一化,高斯噪声的影响被进一步压制。刚才构造的 QPC 信号,在 (50,120) 处的双相干值应接近 1,而噪声区域接近 0。这个特征适合作为故障指标:如果某一对频率的耦合强度超过 0.5,就认为存在显著二次相位耦合。

注意 bicoher 输出的是复数,取 abs 后才是幅值。有些版本可能直接输出实数值,建议用help bicoher确认。我踩过的坑是:拿着双相干的复数矩阵直接当实数存成 .mat,下一次加载时才发现是 complex 类型,后续分类器报错。所以习惯上我都会先 abs(bic) 再保存。

在实际故障诊断里,我不会肉眼去看每一张图,而是设定一个窗口比如 f1 在 40~60 Hz,f2 在 110~130 Hz,窗口内取双相干的峰值作为特征。代码如下:

% 在指定频率窗口内提取最大双相干值 idx1 = find(w*fs >= 40 & w*fs <= 60); idx2 = find(w*fs >= 110 & w*fs <= 130); crop = abs(bic(idx1, idx2)); qpc_score = max(crop(:)); % qpc_score 就是该频窗内的耦合强度特征

这里 idx1 和 idx2 是索引向量,bic(idx1, idx2) 取的是矩阵的一个子块,再对所有元素取最大值。qpc_score 接近 1 表示强耦合,接近 0 表示弱耦合。如果设备正常运行时不耦合,出现故障后这个值跳升,就是一个非常稳定的预警指标。

4.2 相位谱与对称性:识别非线性系统的类型

双谱的实部与虚部分别包含了相位信息。提取双谱的相位谱 angle(Bspec),可以判断系统是否具有二次非线性。比如一个具有二次非线性的系统,其双谱相位在耦合频率附近会有规律性。直接绘制相位谱:

% 双谱相位谱 figure; imagesc(w*fs, w*fs, angle(Bspec)); axis xy; colorbar; colormap(jet); xlabel('f1 (Hz)'); ylabel('f2 (Hz)'); title('双谱相位谱(弧度)');

相位谱上的周期性条纹往往暗示着信号中有准周期的相位结构。另一个对称性细节:双谱在 f1=f2 的对角线上具有特殊约束,当信号是尺度变化过程时,对角线上会出现显著峰。不要把这个和功率谱在 f=0 处的直流混淆。实际分析时,我会把双谱幅值、双相干谱和相位谱三张图并列放在一起看,先定位耦合频率,再看耦合强度,最后看相位规律,这样基本能判断故障类型。

对于更复杂的非线性,比如三阶非线性引起的三谱(trispectrum),HOSA 工具箱里也有 cum4est 支持四阶累积量,可以类推构造四阶谱。不过四阶谱的维度是三维,可视化难度大,常见做法是固定一个频率切二维平面。

相位谱还有一个用途:验证双谱估计是否受到边界效应影响。如果信号分段时没有加窗,相位谱边缘会出现梳状抖动,这时可以给信号加汉宁窗,或者减少 nfft。我在一次分析轴承故障数据时,相位谱出现规律性条纹,一开始以为是非线性特征,后来发现是分段时没有去均值导致的伪影,去掉均值后条纹消失。所以看到任何规律性图案,先怀疑前处理而不是故障本身。

5. 避坑与常见问题:HOSA 工具箱使用中的五个坑

5.1 坑一:路径没设置就报错“Undefined function 'bispecd'”

现象:执行 bispecd(x,...) 时 MATLAB 报未定义函数,或者 try addpath 后仍找不到。

原因:我把 hosa.rar 解压后直接双击某个脚本,但脚本所在目录并不是工具箱函数所在目录。有些子文件夹是嵌套的,导致 addpath 加错层级。

解决:先which bispecd,如果返回空,说明路径没对。用dir检查当前目录下是否真的有 bispecd.m,把 addpath 指向该文件所在目录。另外要注意 MATLAB 会缓存路径,addpath 后如果仍找不到,执行rehash或重启 MATLAB。在团队协作时,最好把 addpath 写进项目启动脚本里,避免每台电脑手动敲。

5.2 坑二:数据长度和 FFT 点数不匹配导致双谱分辨率“稀释”

现象:双谱图看起来一片模糊,找不到尖锐峰值。

原因:nfft 选得太大,但数据段长度太短。nfft 表示频率细分,如果数据只有 256 点,nfft 设为 1024,那么每个频带的样本数不足,估计方差急剧增大,谱峰被平滑掉。

解决:我一般让 nfft 不超过数据长度的 1/4,且至少保证每个频带有 4~8 个独立样本。比如 1024 点数据,nfft 取 256 或 128。如果信号非常长,可以分段并重叠,overlap 取 0.5 左右,既能平滑又不至于损失太多信息。还可以通过 wind 参数调节平滑窗,wind 从 3 增加到 7,双谱图会明显变平滑,但峰值也会变矮,需要根据具体信号调整。

5.3 坑三:直接对原始信号调用 cum3est,结果全是 NaN

现象:运行 cum3est 后输出矩阵里有 NaN 或数量级异常大的数。

原因:信号未去除均值。三阶累积量对直流分量非常敏感,均值一旦没去干净,结果会指数级膨胀。

解决:在估计之前对信号做去均值处理:x = x - mean(x);。如果数据来自传感器还带有趋势项,最好先高通滤波或做一次趋势移除。我习惯把去均值写成一行并注释,方便后续排查。另外,如果信号里含有极少数异常尖峰,累积量会被这些尖峰主导,建议在去均值后加一步中值滤波,或者直接剔除超过 3σ 的样本。

5.4 坑四:分段重叠率过高,双谱被过度平滑

现象:双相干谱几乎所有区域都接近 0.5,看不出主峰和背景的区别。

原因:用 bispecd 时,nsamp 和 overlap 参数配合不当。如果分段重叠率超过 0.9,各段信号高度相关,等效独立段数少,统计平均的效果变差,谱被“淹死”。

解决:overlap 一般取 0 到 0.5 之间。我常用的配置是 nsamp = 256, overlap = 0.3。如果总数据量很大,nsamp 可以设为 1024,overlap 0.5。记住:重叠率越高,估计越平滑,但峰也会被压低,需要在平滑和峰值度之间权衡。有时候我甚至会把 overlap 设成 0,用更长的数据段来保证统计量,效果也不错。

5.5 坑五:程序在旧版 HOSA 能跑,新版 MATLAB 报错

现象:同一个脚本,换台电脑跑就报错,提示函数名有改动。

原因:有些老版本的 HOSA 函数内部用了已废弃的 built-in 函数,比如mpower之类的旧接口;另外,新版 MATLAB 对复数矩阵的索引规则更严格,某些老代码会触发警告或错误。

解决:先查help,看当前工具箱函数是否接受该参数形式。如果函数内部报错,可以在命令行输入dbstop if error定位到具体行,再做局部修改。常见做法是把累积量估计部分替换成 cum3est + fft,绕开旧函数。或者从项目下载资源中看是不是有对应的版本说明,尽量在 R2016a~R2020b 范围内使用。我自己的经验是:HOSA 在 R2018b 上跑最稳,后来换 R2022a 时需要把部分函数的sum调用改成显式循环。遇到函数内部报错时,which bispecd -all可以检查有没有版本冲突,比如安装了多个 hosa 目录。

6. 进阶:用 HOSA 工具箱做批量特征提取和自定义谱估计算法

6.1 批量处理多段信号的循环写法

现场数据往往是长采集记录,需要切段逐一计算 3/2 谱特征。把上面的流程封装成函数,在循环里调用,是标准做法:

% 批量计算双相干特征 fs = 1000; % 采样率 nwin = 1024; % 每段长度 overlap = 0.5; % 重叠率 step = round(nwin*(1-overlap)); segments = buffer(x, nwin, nwin-step); % 分帧 num_seg = size(segments, 2); qpc_features = zeros(num_seg, 1); for k = 1:num_seg seg = segments(:, k); seg = seg - mean(seg); % 去均值 [bic, w] = bicoher(seg, 256, 5, 0, 0, 'biased'); % 提取目标频窗的峰值 idx1 = find(w*fs >= 45 & w*fs <= 55); idx2 = find(w*fs >= 115 & w*fs <= 125); qpc_features(k) = max(max(abs(bic(idx1, idx2)))); end

这里用 buffer 函数分帧,step 计算无重叠区。注意 buffer 默认把单行信号变成多列,每一列是一段。循环内先去了均值,再调用 bicoher。提取峰值时使用双层 max,得到矩阵最大值。这段代码可以直接跑在故障监控系统里,每段计算一次耦合特征,再送入分类器。如果信号采样率不是 1000 Hz,需要把 45~55 这些窗口值换算成实际索引,而不是硬写。

6.2 用 HOSA 函数搭自己的估计链:从累积量到双谱

如果 bispecd 因为某些原因不适用,可以直接用底层函数搭一条估计链。先计算三阶累积量,再做二维 FFT 得到双谱:

% 使用 cum3est 计算三阶累积量 nsamp = 1024; overlap = 0; nlag = 50; maxlag = 50; cum3 = cum3est(x, nsamp, overlap, nlag, maxlag, 'biased'); % 对累积量做二维FFT得到双谱 Bself = fft2(cum3); % 重新排列零频到中心,便于显示 Bself = fftshift(Bself);

cum3est 的前几个参数分别是段长、重叠、滞后数等。具体以 help cum3est 为准。这条链更接近数学定义,适合修改算法细节,比如换成非均匀 FFT,或者只计算负频率区域。缺点是速度比封装后的 bispecd 慢不少,且需要自己处理边界效应。如果数据长、频率带窄,封装函数优先。

一个能提高结果可信度的验证技巧:把同一个信号用 bispecd 和自建链分别算双谱,相减后取模的最大值。如果边界处差异大于 0.1,说明累积量滞后或去均值没做干净。从那以后,我每次换电脑或者换 MATLAB 版本,都会先把这段对照验证跑一遍,确认工具箱和自建函数结果一致,再放心做后续特征提取。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询