ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ITD固有时间尺度分解:原理、Python实现与故障诊断实战

ITD固有时间尺度分解:原理、Python实现与故障诊断实战 简介ITD分解技术是机械设备故障诊断中常用的时差分信号处理方法能够将复杂故障信号拆分为基频、高频及噪声等多种分量便于定位异常状态与故障源。压缩包提供完整的ITD分解算法工具集共5个文件均为MATLAB的m脚本涵盖基础分解、极值点提取、包络处理等核心函数并附带开箱即用的示例程序适合从事信号处理、故障诊断研究的学生和工程师快速上手验证。包体仅4KB结构精简可直接嵌入自有分析流程。目前已有452人学习下载代码量虽小但完整实现了从极值检测到分量重构的ITD分解链条并针对宽频响应场景进行了优化可作为理解Widevcb算法和改进故障特征提取的实用参考。1. ITD 分解能解决什么问题拿到一段轴承振动信号最麻烦的不是看波形而是把故障冲击从背景噪声里剥出来。ITD 分解Intrinsic Time-scale Decomposition固有时间尺度分解是一种专门做这件事的非平稳信号分解方法它把原信号分解成若干个按频率从高到低排列的固有旋转分量PRC和一个单调趋势项不需要 EMD 那种反复迭代求包络的过程计算量小、速度快在故障信号分解和在线诊断场景里很实用。下面从算法原理讲起到 Python 实现、故障特征提取、参数调优代码可以直接复用参数怎么调、坑在哪里都会讲清楚。2. ITD 分解的核心算法与参数2.1 ITD 分解的数学定义基线提取与固有旋转分量ITD 的思路可以概括成一句话信号减去一条“基线”减剩下的部分就是最快尺度上的固有旋转分量对基线重复做同样的事就得到下一层分量。设原始信号为 x(t)先找到它的全部局部极值点记极值点时刻为 τ₁, τ₂, …, τₙ对应幅值为 X(τ₁), …, X(τₙ)。基线 L(t) 的意义是信号里的慢变成分。最常见且稳定的构造方式是相邻极值点之间的线性插值当 t 落在 [τₖ, τₖ₊₁] 时L(t) X(τₖ) [X(τₖ₊₁) − X(τₖ)]·(t − τₖ)/(τₖ₊₁ − τₖ)。然后用原信号减去基线得到第一个固有旋转分量 PRC₁(t) x(t) − L(t)。继续把 L(t) 当新信号做同样的操作依次得到 PRC₂、PRC₃……直到残差单调或极值点少于 3 个为止。最终结果可以写成x(t) PRC₁(t) PRC₂(t) … PRCₙ(t) r(t)这里有一个值得注意的区别原始论文中的基线提取算子并不是简单的分段线性插值它会在极值点处加入一项比例控制用来应对冲击信号造成的过冲而在工程代码里线性插值已经能保留绝大部分故障特征实现简单、数值稳定是开源实现和诊断项目中最常用的替代。真正决定分解质量的不是这个细微差异而是极值点选取是否干净、边界外延是否处理得当。2.2 为什么故障信号分解更常用 ITD 而不是 EMD故障信号分解最常面对的信号是振动传感器采集到的冲击、调制、谐波和噪声叠加。EMD 在理论上也能画出包络但它要把信号反复包络、筛分直到满足本征模态条件成本高且容易模态混叠故障冲击越强包络迭代越容易在冲击点附近产生多余振荡。ITD 一个分量只需一轮极值分解不要求包络计算复杂度低得多。从工程选型的角度可以把几个常见方法用对照表摆在一起指标ITDEMD/EEMDVMD求解方式单轮极值分解迭代筛选变分优化分量个数由终止条件自动决定自动但易混叠需要预设 K计算速度快慢中等冲击敏感性敏感且不易过冲敏感但易混叠依赖频带先验边界效应程度较轻较重可控但需调参这张表对应的是默认参数下的对比。实际项目中常把 ITD 当第一道分解器使用它速度快适合对长信号做扫查先找出明显含冲击的分量再用 VMD 对某个窄频带做二次分解。EEMD 是在 EMD 上叠加多次白噪声再取平均本质上是把模态混叠问题交给统计平均去解决代价是计算量再放大一个量级在线场景基本不可接受。这正是故障诊断研究里大量论文直接用 ITD 做振动和电流信号预分解的原因。2.3 ITD 分解需要设置的关键参数ITD 是从数据本身找极值来分解的方法它的三个参数决定了分解质量并且之间有联动关系。第一个是最大分解层数 max_comps。常见做法是取 3 到 6 层。层数太多最后几个分量会退化为噪声的极值插值结果把随机成分当成模态输出。更稳的是用残差能量占比提前终止# 停止条件示例残差能量降到原始信号能量的 2% 以下就停止 energy_x np.sum(x * x) energy_r np.sum(residual * residual) if energy_r 0.02 * energy_x: break这个条件的物理含义是残差已经没有足够能量继续携带故障信息再分解出来的分量贡献可以忽略。第二个是极值最小间隔 min_distance。采样率高了以后噪声会产生大量相邻很近的伪极值导致第一个 PRC 全被毛刺占满。经验上按采样率折算10 kHz 采样下 min_distance 取 20 到 50 比较合理能压住高频毛刺又不至于吞掉几毫秒宽的冲击脉冲。注意 scipy 的 argrelextrema 中 order 参数的实际效果是要求局部极值左右各留 n 个点所以真实最小极值间隔约为 2×order1 个点。第三个是终止极值点数。残差只剩 1 到 2 个极值点时不存在振荡结构循环必须停止。把这三个参数组合进同一个函数就是下一章的最小可运行实现。3. 用 Python 实现 ITD 信号分解最小可运行代码3.1 一个 60 行内的 ITD 分解函数把上一章的参数落到代码上一个可以直接用的 ITD 分解函数如下import numpy as np from scipy.signal import argrelextrema def itd_decompose(x, max_comps4, min_distance1): ITD 信号分解返回 PRC 分量列表和残差趋势项。 x np.asarray(x, dtypenp.float64) n len(x) components [] residual x.copy() for _ in range(max_comps): # 提取局部极大值与局部极小值 idx_max argrelextrema(residual, np.greater, ordermin_distance)[0] idx_min argrelextrema(residual, np.less, ordermin_distance)[0] # 合并排序得到时间上递增的极值点序列 ext_idx np.sort(np.concatenate([idx_max, idx_min])) if len(ext_idx) 4: # 极值点不足终止分解 break # 相邻极值点间线性插值生成基线 baseline np.interp(np.arange(n), ext_idx, residual[ext_idx]) components.append(residual - baseline) residual baseline return components, residual这段代码有三个关键点。第一idx_max 和 idx_min 各自有序但合并后必须整体排序否则 np.interp 的横坐标不递增会出错排序后极值点自然交替因为信号的导数符号在相邻极值点之间必然翻转。第二np.interp 在端点处使用最外侧两个极值点做外推这是边界效应的来源缓解方法在第 5 章。第三极值点少于 4 个时直接保留为趋势项components 的长度就是 ITD 实际产出的 PRC 个数。3.2 在仿真信号上验证分解结果用一个能反映轴承故障典型特征的仿真信号来验证10 kHz 采样、20 Hz 故障特征频率、1200 Hz 载波衰减振荡的周期性冲击同时叠加 50 Hz 谐波和随机噪声。仿真和分解代码如下fs 10000 t np.arange(0, 1.0, 1/fs) fault_freq 20 # 故障特征频率 carrier 1200 # 结构共振载波频率 N len(t) x np.zeros(N) for start in np.arange(0, 0.95, 1/fault_freq): idx int(start * fs) seg np.arange(int(0.03 * fs)) x[idx:idx len(seg)] np.exp(-seg / (0.005 * fs)) * np.cos(2*np.pi*carrier*seg/fs) x x 0.3*np.sin(2*np.pi*50*t) 0.05*np.random.randn(N) comps, res itd_decompose(x, max_comps4, min_distance20) for i, c in enumerate(comps): k ((c - c.mean())**4).mean() / (c.std()**4 1e-12) print(fPRC{i1} kurtosis {k:.2f})这段代码跑完后PRC1 或 PRC2 的峭度会明显大于 3说明 ITD 把周期冲击单拎了出来。将 min_distance 从 20 调到 200 再跑一次冲击脉冲会被当作平坦极值处理峭度骤降这就反向验证了极值参数对冲击尺度选择的影响。峭度的定义在有冲击分量时会大幅偏离 3因此它既是分量筛选指标也是参数生效的指示器。3.3 代码运行逻辑与参数怎么调整ITD 的循环顺序是从高频到低频第一轮 residual 是原信号因此 PRC1 是原信号去掉慢变基线后最快的振荡第二轮 residual 是上一轮基线PRC2 是下一尺度的振荡。这个输出顺序和 EMD 一致习惯上用峭度从前往后扫就能定位故障分量。参数调节遵循三个经验。第一PRC1 全是细密毛刺而且幅值小说明 min_distance 太小把高频噪声当成极值分解了调大 2 到 5 倍再试。第二PRC1 里的脉冲包络变宽、边沿不陡说明 min_distance 过大把冲击脉冲顶部的真实极值滤掉了需要调小。第三分解到第 4 层残差振幅还是很大先检查预处理有没有去趋势不要急着加大 max_comps趋势会稳定占据第一层基线导致后面的分量全是趋势的残余。预处理方面至少要做去均值推荐再用 scipy.signal.detrend 把线性漂移去掉否则基线会被趋势项带偏第一个 PRC 会丢失真实的高频冲击。4. 故障信号分解实战从 ITD 分量里找出故障特征4.1 拿到 widevcb 这类采样文件后的标准处理流程实际工程里的故障信号不会像仿真数据这么干净。以断路器、真空断路器机构振动信号为例文件命名里往往带设备编号和工况标识比如 widevcb_xxx数据里混有分合闸电流干扰、机械振动和环境噪声。对这些信号做 ITD 分解之前先按下述顺序过一遍读取文件后先打印前 100 个采样点确认数据是纯二进制帧还是文本行采样率写在文件头还是单独配置里对信号做 scipy.signal.detrend 去均值和线性趋势若已知冲击频带比如 1–5 kHz先用 4 阶 Butterworth 带通滤波再做 ITD 分解分解后按 4.2 节流程筛选 PRC 并做包络谱。这个流程里最容易做错的是第 3 步带通滤波在这里只是粗筛用高阶滤波器会产生振铃在强冲击前后制造出多余的伪极值点ITD 会把振铃当成真实振荡分出来实际效果反而比不过只去趋势后直接分解、再靠峭度挑分量。4.2 分量筛选的量化指标与包络谱验证方法分解出的 4 个 PRC 不能全部吃进故障识别模型要按可量化的步骤筛。工程上三步走步骤计算内容筛选逻辑1峭度峭度大于 3 且明显高于其他分量者优先2能量占比选择能量占原信号比例较大的分量3包络谱在故障特征频率及其倍频处有峰的分量入选对选中的 PRC 求 Hilbert 包络谱是验证故障特征的决定性一步from scipy.signal import hilbert def envelope_spectrum(x, fs): analytic hilbert(x) env np.abs(analytic) spec np.abs(np.fft.rfft(env)) freq np.fft.rfftfreq(len(env), 1/fs) return freq, spec freq, spec envelope_spectrum(comps[0], fs) for h in range(1, 4): target h * fault_freq band (freq target - 0.5) (freq target 0.5) if band.any(): print(f{target} Hz 幅值: {spec[band].max():.3f})这段代码的逻辑很直接Hilbert 变换先构造解析信号取模得到包络曲线再对包络做 FFT。如果 ITD 成功把周期冲击分隔到某个 PRC 中该 PRC 的包络会在故障特征频率的基频和倍频处出现明显谱峰若谱峰不明显说明该分量选错了需要回到筛选表换一个 PRC。4.3 故障信号分解里最常见的三类坑实际故障数据不比仿真数据温顺有三类问题反复出现。第一类是冲击段处的基线畸变强冲击让极值点在局部过密基线在冲击点附近出现反向小尖峰PRC 波形看起来像把脉冲抠掉了一块。处理办法是提高 min_distance让 ITD 在更宽的尺度上提取冲击如果冲击本身只有 2 到 3 个极值点就需要先带通滤波把载波提出来再分解。第二类是边界效应它表现为 PRC 在信号首尾部分的幅值明显高于中段这是端点外推导致的系统性误差。判断办法是对每个分量分别计算首尾段的方差与中段方差比值超过 2 就可以认定边界污染。第三类是只盯着峭度选分量。噪声尖峰和真实冲击都有高峭度但噪声尖峰在包络谱上不会形成稳定的倍频峰。所以筛选顺序必须是峭度初筛、包络谱终审两步都过了才交给故障判别逻辑。5. ITD 分解的边界效应处理与批量应用技巧5.1 用镜像延拓消除端点外推误差边界效应在故障冲击信号上几乎不可避免镜像延拓是成本最低的缓解方式。做法是把信号首尾各复制一段镜像拼到两端延拓后的信号做 ITD最后只切回原范围。延拓长度取信号长度的 5% 通常就够ext int(len(x) * 0.05) x_ext np.concatenate([x[:ext][::-1], x, x[-ext:][::-1]]) comps_ext, res_ext itd_decompose(x_ext, max_comps4, min_distance20) comps [c[ext:ext len(x)] for c in comps_ext] res res_ext[ext:ext len(x)]这段代码切回的时机必须放在全部 ITD 完成之后不能边分解边切否则下一轮基线又会在新边界产生同样的问题。5.2 用残差能量做自适应停止max_comps 固定成常数在批量处理时并不安全。更稳的方式是同时判断残差能量占比和极值点数量当残差能量低于原信号能量的 1%或者极值点少于 4 个就提前终止。噪声段的残差能量占比下不来这个停止条件不会误触发但对于纯噪声数据ITD 本来就不该强行分出 4 层。5.3 批量处理时的收敛检查建议批量处理几百个文件时ITD 的分量数不会完全一致因为每段数据的极值密度不同。建议为每个文件记录两列实际 PRC 个数和残差能量占比然后画散点图。多数正常工况样本会聚成一带明显离群的点往往不是故障而是数据截断、通道饱和或传感器掉线造成极值不足。把这些离群文件单独提出来和原始波形人工过一遍通常比直接对全部结果做包络谱更快定位到采集问题。这个检查应在参数定稿前做否则参数本身也带着噪声段拟合的风险。本文还有配套的精品资源点击获取
返回列表