辛几何模态分解原文解读——辛几何模式分解及其在旋转机械复合故障诊断中的应用
1. 研究背景与现有方法的局限性
时间序列分析在工程应用中扮演着重要角色。将时间序列分解为一系列简单的分量,并通过判断、重构和识别有用的分量,可以获得关于原始系统演化行为的最本质信息。然而,在实际应用中,测量信号通常由具有复杂时域波形、时变幅度和频率的不同模式组成。这些振荡信号包含大量有价值的系统状态信息,因此需要进一步研究。为了获取特定分量的所有特性,我们需要将其从信号中分离出来。可靠的信号分解方法应该能够有效提取现有模式,将它们相互分离并去除噪声信号。然而,几乎所有现有的方法都至少存在以下一种缺陷:(1)需要用户定义参数,且对参数非常敏感,无法自适应选择参数;(2)在处理含噪声信号时效果不佳,即没有噪声鲁棒性;(3)对于复杂波形,会将其强制分解为多个不准确的分量。
1.1 小波变换的局限性
小波变换可以将时间序列分解为不同频带或不同分辨率的尺度分量,同时提供时间序列的时域和频域定位信息。这使得小波分析具有多尺度和"数学显微镜"的特点,能够识别时间序列中的突变分量。然而,小波分析本质上是一种可调窗口的傅里叶变换。由于小波基函数长度有限,小波变换会产生能量泄漏,难以在时域和频域中分析信号。此外,一旦选择了小波基和分解尺度,结果就是一个固定频带的信号,这仅与采样频率有关,而与信号本身无关。因此,小波变换的有限长度可能导致不必要的泄漏,并将完整的分量分解为几个不准确的分量。
1.2 经验模态分解(EMD)及其改进方法的局限性
经验模态分解(EMD)方法可以自适应地将幅度调制和频率调制信号分解为一系列固有模态函数(IMFs),每个固有模态函数的频率分量与采样频率及信号本身的自变化有关。此外,该方法不需要用户定义参数,基于数据自身的时间尺度特性进行分解。这与基于小波基函数的小波变换方法本质上不同。理论上,EMD方法可以应用于分解任何类型的信号,在处理非线性和非平稳信号方面具有明显优势。然而,EMD中使用的三次样条在每次筛选中拟合上下包络,这可能导致包络不足、包络过度和模式混叠。因为EMD对噪声敏感,因此Wu和Huang提出了一种改进的EMD方法,称为集合经验模态分解(EEMD),以克服EMD的上述缺点。EEMD的思想是通过向原始信号添加个体独立实现的高斯白噪声信号,并重复应用EMD来获得最终模式。EEMD分解原理如下:当额外的高斯白噪声均匀分布在整个时频空间时,时频空间由滤波器划分为不同尺度的分量组成。当信号与均匀分布的高斯白噪声耦合时,不同尺度的信号区域会自动映射到与高斯白噪声相关的适当尺度。当然,每个独立测试可能产生强烈的噪声结果,这是因为每个额外的噪声分量都包含信号和额外的高斯白噪声。由于每个独立测试中的噪声不同,通过足够测试的集合平均,噪声将被消除。因此,EEMD可以通过添加白噪声来减弱噪声对原始信号分解的影响。即便如此,EEMD对强噪声信号仍不具备良好的噪声鲁棒性。此外,它包含两个非自适应参数,控制附加噪声的标准差,对结果有一定影响。
1.3 固有时间尺度分解(ITD)及其改进方法的局限性
针对上述方法的不足,Frei等人提出了一种新的自适应分析方法,称为固有时间尺度分解(ITD),它可以自适应地将非平稳信号分解为几个彼此独立的适当旋转分量(PRCs)。与EMD和EEMD相比,ITD在端点效应和计算效率方面具有明显优势。此外,ITD克服了EMD中的端点效应、过度包络、模式混叠和IMF准则等问题。ITD方法已应用于机械故障诊断领域,因为ITD方法能够分析非平稳和非线性信号。但该方法未能阐明算法本身和PRC的物理意义。此外,基线信号是通过对振动信号进行线性变换获得的,这导致PRC的瞬时幅度和频率失真。由于ITD方法存在一些问题,其进一步应用受到限制,已有人提出了一些改进的ITD方法。在文献中提出了使用三次样条代替线性变换获取包络信号的方法,称为局部特征尺度分解(LCD),用于获取固有尺度分量(ISCs)。文献中还使用了三次B样条插值来获得平滑的单分量包络信号。这两种改进的ITD方法解决了瞬时幅度和频率中的毛刺和失真问题。三次样条插值方法具有良好的收敛性和更高的平滑性,但在三次样条插值中会产生模式混叠,特别是在强噪声信号中。
1.4 奇异谱分析(SSA)的局限性
与先前的信号处理方法不同,奇异谱分析(SSA)是一种基于奇异值分解的谱估计方法,包括嵌入维度的选择、奇异值分解和分量重构。SSA最初应用于数学分析领域,随后被引入机械振动信号分析领域。然而,SSA强烈依赖于嵌入维度大小(窗口函数长度)的经验选择来构造轨迹矩阵,并基于轨迹矩阵的主分量进行奇异值分解、特征重组和信号重构,这极大地影响了其最终分析结果。此外,SSA主要用于特定时间序列的重构和振动信号的噪声减少,但不能实现自适应频带分割。此外,SSA是一种基于奇异值分解的线性技术,一些研究表明,在分析非线性结构时可能导致误导性结果。
2. 辛几何模式分解(SGMD)的理论基础
基于辛几何的分析方法是一种新的分析方法,可以保护相空间的几何结构。基于辛几何的分析方法主要用于解决动力学和控制系统中2n×2n矩阵或哈密顿矩阵的特征值问题,已迅速扩展到描述偏微分方程、奇异微分方程和其他系统。但很少有文献使用辛几何分析非线性系统数据。在辛几何分析方法中,辛几何相似变换可以保持测度并使原始时间序列的本质特性保持不变,因此适合分析非线性系统过程。
考虑到先前信号分析方法的缺点和辛几何的优势,本文提出了一种新的时间序列分解方法,称为辛几何模式分解(SGMD),它使用辛几何相似变换求解哈密顿矩阵的特征值,并通过其对应的特征向量重构单个分量信号。因此,这些特征向量中的每一个都可以转换为重构的时间序列,统称为辛几何分量(SGCs)。此外,SGMD采用辛几何相似变换,具有保持原始时间序列本质特性不变和抑制模式混叠的优点。同时,辛几何相似变换可以有效地重构现有模式并去除噪声,而无需任何用户定义的参数。与小波变换、EEMD、LCD和SSA相比,SGMD在保持原始时间序列的本质特性不变和不需要任何用户定义参数的噪声鲁棒性方面具有明显优势。
在介绍SGMD方法分析之前,首先介绍过程中涉及的一些定义和定理:
定义1:S作为有效矩阵,如果存在 J S J − 1 = S T JSJ^{-1} = S^T JSJ−1=ST,则S是辛矩阵。
定义2:H作为有效矩阵,如果存在 J H J − 1 = H T JHJ^{-1} = H^T JHJ−1=HT,则H是哈密顿矩阵。
定理1:对于任何辛矩阵 A n × n A_{n \times n} An×n,构造一个新矩阵 M = [ A 0 0 A T ] M = \begin{bmatrix} A & 0 \\ 0 & A^T \end{bmatrix} M=[A00AT],M也是哈密顿矩阵。
定理2:假设Householder矩阵H可以表示为: H = H ( k , w ) = [ P 0 0 P ] H = H(k, w) = \begin{bmatrix} P & 0 \\ 0 & P \end{bmatrix} H=H(k,w)=[P00P], P = I n − 2 w w T w T w P = I_n - \frac{2ww^T}{w^Tw} P=In−wTw2wwT, w = ( 0 , … , 0 , w k , … , w n ) T ≠ 0 w = (0, \ldots, 0, w_k, \ldots, w_n)^T \neq 0 w=(0,…,0,wk,…,wn)T=0,H是辛酉矩阵。
定理3:假设轨迹矩阵X是m×n(m>n)维实矩阵,且 A = X T X A = X^TX A=XTX是实对称矩阵。然后,可以从对称矩阵A构造哈密顿矩阵M,即 M = [ A 0 0 A T ] M = \begin{bmatrix} A & 0 \\ 0 & A^T \end{bmatrix} M=[A00AT]。
存在一个Householder矩阵H,通过使 H M H T HMH^T HMHT可以构造一个上Hessenberg矩阵B,即:
H M H T = [ P 0 0 P ] [ A 0 0 A T ] [ P 0 0 P ] T = [ P A P T 0 0 P A T P T ] = [ B 0 0 B T ] HMH^T = \begin{bmatrix} P & 0 \\ 0 & P \end{bmatrix} \begin{bmatrix} A & 0 \\ 0 & A^T \end{bmatrix} \begin{bmatrix} P & 0 \\ 0 & P \end{bmatrix}^T = \begin{bmatrix} PAP^T & 0 \\ 0 & PA^TP^T \end{bmatrix} = \begin{bmatrix} B & 0 \\ 0 & B^T \end{bmatrix} HMHT=[P00P][A00AT][P00P]T=[PAPT00PATPT]=[B00BT]
λ ( A ) = λ ( B ) \lambda(A) = \lambda(B) λ(A)=λ(B)
σ = λ 2 ( X ) = λ ( A ) \sigma = \lambda^2(X) = \lambda(A) σ=λ2(X)=λ(A)
上Hessenberg矩阵B是n维空间矩阵。因此,原始2n维空间哈密顿矩阵M可以通过转换为n维空间来解决。
2.1 SGMD方法的实现过程
辛几何模式分解的核心是使用辛几何相似变换求解哈密顿矩阵的特征值,并通过其对应的特征向量重构单个分量信号。因此,首先,我们采用功率谱密度(PSD)方法自适应地确定所研究时间序列的嵌入维数。然后,构造辛几何,并使用辛几何相似变换求解哈密顿矩阵的特征值。最后,使用对角平均和自适应重构获得辛几何分量。从分解处理的角度来看,SGMD是一种可以分解非线性信号、反映非线性结构并适合分析非线性信号的方法。辛几何模式分解方法可以概括为四个步骤:自适应确定时间序列的嵌入维数、辛几何相似变换求解哈密顿矩阵的特征值、对角平均和分量的自适应重构。
2.1.1 自适应确定时间序列的嵌入维数
任何原始信号时间序列可以表示为 x = x 1 , x 2 , … , x n x = x_1, x_2, \ldots, x_n x=x1,x2,…,xn,其中n是数据的长度。根据Takens嵌入定理,可以使用时间序列延迟拓扑等价方法由一维信号重构多维信号。这意味着原始时间序列可以映射到包含时间序列x所有动态信息的轨迹矩阵X:
X = [ x 1 x 1 + τ ⋯ x 1 + ( d − 1 ) τ ⋮ ⋮ ⋱ ⋮ x m x m + τ ⋯ x m + ( d − 1 ) τ ] X = \begin{bmatrix} x_1 & x_{1+\tau} & \cdots & x_{1+(d-1)\tau} \\ \vdots & \vdots & \ddots & \vdots \\ x_m & x_{m+\tau} & \cdots & x_{m+(d-1)\tau} \end{bmatrix} X= x1⋮xmx1+τ⋮xm+τ⋯⋱⋯x1+(d−1)τ⋮xm+(d−1)τ
其中d是嵌入维数,τ是延迟时间, m = n − ( d − 1 ) τ m = n - (d-1)\tau m=n−(d−1)τ,选择适当的嵌入维数d和延迟时间τ以获得相应的重构矩阵X。然而,不同的嵌入维数可能产生不同的效果,文献[34]中确定嵌入维数的思想被用来计算初始时间序列x的PSD。然后在PSD中估计最大峰值的频率 f m a x f_{max} fmax。如果归一化频率小于给定阈值 1 0 − 3 10^{-3} 10−3,则将d设为n/3,其中n是数据的长度。否则,将嵌入维数设为 d = 1.2 × ( F s / f m a x ) d = 1.2 \times (F_s/f_{max}) d=1.2×(Fs/fmax)。
2.1.2 辛几何相似变换求解哈密顿矩阵的特征值
为了构造哈密顿矩阵,对轨迹矩阵进行自相关分析,得到协方差对称矩阵A:
A = X T X A = X^TX A=XTX
然后从对称矩阵A构造哈密顿矩阵M:
M = [ A 0 0 A T ] M = \begin{bmatrix} A & 0 \\ 0 & A^T \end{bmatrix} M=[A00AT]
构造哈密顿矩阵后,M的平方为N,即 N = M 2 N = M^2 N=M2,矩阵M和N都是哈密顿矩阵。因此,可以从方程(7)构造辛正交矩阵Q:
Q T N Q = [ B R 0 B T ] Q^TNQ = \begin{bmatrix} B & R \\ 0 & B^T \end{bmatrix} QTNQ=[B0RBT]
其中矩阵Q是具有辛矩阵性质的正交辛矩阵,可以确保在矩阵变换过程中不破坏哈密顿矩阵的结构,B是上三角矩阵,即 b i j = 0 ( i > j + 1 ) b_{ij} = 0(i > j+1) bij=0(i>j+1)。上三角矩阵B可以通过对矩阵N使用定义的Schmidt正交化进行变换,计算上三角矩阵B的特征值为 λ 1 , λ 2 , … , λ d \lambda_1, \lambda_2, \ldots, \lambda_d λ1,λ2,…,λd。实际上,如果A是实对称的,则A的特征值等于B的特征值。
从哈密顿矩阵的性质计算矩阵A的特征值:
σ i = λ i ( i = 1 , 2 , … , d ) \sigma_i = \sqrt{\lambda_i} \quad (i = 1, 2, \ldots, d) σi=λi(i=1,2,…,d)
X的辛几何由A的特征值按降序排列组成:
σ 1 > σ 2 > ⋯ > σ d \sigma_1 > \sigma_2 > \cdots > \sigma_d σ1>σ2>⋯>σd
σ i \sigma_i σi的分布是A的辛几何谱, σ i \sigma_i σi中较小的值通常被视为噪声分量。 Q i ( i = 1 , 2 , … , d ) Q_i(i = 1, 2, \ldots, d) Qi(i=1,2,…,d)是矩阵A中对应特征值 σ i \sigma_i σi的特征向量。
可以从方程(7)构造矩阵Q为Householder矩阵H,其中辛几何理论是求解嵌入维度时间序列的有效方法。因此,我们选择Householder矩阵H而不是辛正交矩阵Q。很容易证明H是幺正矩阵,且H可以由实矩阵构造。这为研究时间序列提供了便利。设 S = Q T X S = Q^TX S=QTX, Z = Q S Z = QS Z=QS,则Z是重构的轨迹矩阵。
2.1.3 对角平均
每个分量矩阵重构的步骤如下:
首先,通过幺正矩阵特征向量和轨迹矩阵获得变换系数矩阵:
S i = Q i T X T S_i = Q_i^TX^T Si=QiTXT
然后将变换系数矩阵转换以获得重构矩阵Z:
Z i = Q i S i Z_i = Q_iS_i Zi=QiSi
其中 Z i ( i = 1 , 2 , … , d ) Z_i (i = 1, 2, \ldots, d) Zi(i=1,2,…,d)是初始单个分量。
类似地,初始单个分量轨迹矩阵Z可以表示为:
Z = Z 1 + Z 2 + ⋯ + Z d Z = Z_1 + Z_2 + \cdots + Z_d Z=Z1+Z2+⋯+Zd
获得的初始单个分量矩阵Z是m×d矩阵,因此有必要重新排序初始单个分量,并且可以通过对角平均将重构的矩阵Z转换为长度为n的一组新时间序列。可以得到长度为n的d个新时间序列,这d个新时间序列的总和是原始时间序列。
对于任何初始单个分量矩阵 Z i Z_i Zi,定义矩阵的元素为 z i j z_{ij} zij,其中 1 ≤ i ≤ d ; 1 ≤ j ≤ m 1 \leq i \leq d; 1 \leq j \leq m 1≤i≤d;1≤j≤m,并且 d ‾ = min ( m , d ) \underline{d} = \min(m, d) d=min(m,d), m ‾ = max ( m , d ) \overline{m} = \max(m, d) m=max(m,d), n = m + ( d − 1 ) τ n = m + (d-1)\tau n=m+(d−1)τ。令 z i j ∗ = z i j z_{ij}^* = z_{ij} zij∗=zij如果 m < d m < d m<d,否则, z i j ∗ = z j i z_{ij}^* = z_{ji} zij∗=zji。因此,对角平均转移矩阵可以表示为:
y k = { 1 k ∑ p = 1 k z p , k − p + 1 ∗ 1 ≤ k ≤ d ‾ 1 d ‾ ∑ p = 1 d ‾ z p , k − p + 1 ∗ d ‾ ≤ k ≤ m ‾ 1 n − k + 1 ∑ p = k − m ‾ + 1 n − m ‾ + 1 z p , k − p + 1 ∗ m ‾ < k ≤ n y_k = \begin{cases} \frac{1}{k}\sum_{p=1}^{k}z_{p,k-p+1}^* & 1 \leq k \leq \underline{d} \\ \frac{1}{\underline{d}}\sum_{p=1}^{\underline{d}}z_{p,k-p+1}^* & \underline{d} \leq k \leq \overline{m} \\ \frac{1}{n-k+1}\sum_{p=k-\overline{m}+1}^{n-\overline{m}+1}z_{p,k-p+1}^* & \overline{m} < k \leq n \end{cases} yk=⎩ ⎨ ⎧k1∑p=1kzp,k−p+1∗d1∑p=1dzp,k−p+1∗n−k+11∑p=k−m+1n−m+1zp,k−p+1∗1≤k≤dd≤k≤mm<k≤n
矩阵 Z i Z_i Zi可以根据方程(13)转换为一系列 Y i ( y 1 , y 2 , … , y n ) Y_i(y_1, y_2, \ldots, y_n) Yi(y1,y2,…,yn)。因此,重构矩阵Z通过对角平均转换为长度为d×n的新系列矩阵Y。原始时间序列被分解为d个具有不同趋势和频带的独立叠加分量。
2.1.4 分量的自适应重构
通过对角平均得到d个单个分量信号:
Y = Y 1 + Y 2 + ⋯ + Y d Y = Y_1 + Y_2 + \cdots + Y_d Y=Y1+Y2+⋯+Yd
d个单个分量可以通过构造轨迹矩阵和进行对角平均获得。然而,每个分量并不是完全独立的单个分量,不同的分量可能具有相同的周期分量、频率分量和特性等。因此,虽然这些分量彼此不完全独立,但其中一些确实具有相同的周期,需要重构具有相同特性的初始单个分量。本文使用频率相似性和分量相关性来重构分量。如果一个分量被分成几个分量,通过计算它们的频率和相关性来重构这些分量。由于环境因素的干扰,信号通常包含大量没有一定规律性的噪声分量,如频率和相关性,所以我们应该设定重构迭代终止条件。
首先,由于主分量分布在矩阵的前部,将第一个初始单个分量 Y 1 Y_1 Y1与其余分量在某些特性上进行比较。具有高相似度的相似分量进行求和,得到第一个分量 S G C 1 SGC_1 SGC1。然后从矩阵Y中移除 S G C 1 SGC_1 SGC1的重构分量,剩余矩阵可以表示为 G 1 G_1 G1。最后,通过对剩余信号求和得到剩余信号 g 1 g_1 g1,然后计算剩余信号与原始信号之间的归一化均方误差(NMSE):
N M S E h = ∑ e = 1 n g h ( e ) ∑ e = 1 n x ( e ) NMSE_h = \frac{\sum_{e=1}^{n}g_h(e)}{\sum_{e=1}^{n}x(e)} NMSEh=∑e=1nx(e)∑e=1ngh(e)
其中h是迭代次数。当归一化均方误差小于给定阈值th = 1%时,整个分解过程将结束。否则,将剩余矩阵用作迭代原始矩阵重复上述迭代过程,直到满足迭代停止条件,得到最终分解结果:
x ( n ) = ∑ h = 1 N S G C h ( n ) + g ( N + 1 ) ( n ) x(n) = \sum_{h=1}^{N}SGC_h(n) + g_{(N+1)}(n) x(n)=h=1∑NSGCh(n)+g(N+1)(n)
其中N是识别的分量系列数。可以证明,剩余误差的能量在每次迭代中都会减小。
3. SGMD方法的Python实现
下面我们将使用Python实现SGMD方法,并通过模拟信号和实际信号验证其有效性。
3.1 辛几何模式分解的完整Python代码实现
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from scipy import linalg
from scipy.fft import fft, fftfreq
class SGMD:
def __init__(self, threshold=0.01):
"""
Initialize SGMD with threshold for component reconstruction.
Parameters:
-----------
threshold : float
Threshold for normalized mean square error (default: 0.01).
"""
self.threshold = threshold
def _determine_embedding_dimension(self, x):
"""
Adaptively determine the embedding dimension of the time series.
"""
n = len(x)
# Calculate PSD
psd_x = np.abs(fft(x))**2
freqs = fftfreq(n, 1)[:n//2]
psd_x = psd_x[:n//2]
# Find maximum peak frequency
f_max = freqs[np.argmax(psd_x)]
# Normalize frequency
f_norm = f_max / (0.5) # Nyquist frequency is 0.5 in normalized units
if f_norm < 1e-3:
d = n // 3
else:
d = int(1.2 / f_norm)
# Limit the embedding dimension
if d > n // 2:
d = n // 2
if d < 2:
d = 2
return d
def _construct_trajectory_matrix(self, x, d, tau=1):
"""
Construct trajectory matrix from time series.
"""
n = len(x)
m = n - (d - 1) * tau
# Initialize trajectory matrix
X = np.zeros((m, d))
# Fill trajectory matrix
for i in range(m):
for j in range(d):
X[i, j] = x[i + j * tau]
return X
def _symplectic_geometry_transformation(self, X):
"""
Perform symplectic geometry transformation.
"""
# Compute covariance symmetric matrix
A = X.T @ X
# Solve eigenvalue problem
eigenvalues, eigenvectors = linalg.eigh(A)
# Sort eigenvalues and eigenvectors in descending order
idx = np.argsort(eigenvalues)[::-1]
sigma = np.sqrt(eigenvalues[idx])
Q = eigenvectors[:, idx]
return sigma, Q
def _diagonal_averaging(self, Z, n, d, tau=1):
"""
Perform diagonal averaging to transform the reconstructed matrix into a time series.
"""
m = n - (d - 1) * tau
d_min = min(m, d)
m_max = max(m, d)
# Initialize reconstructed time series
y = np.zeros(n)
# Check if the matrix needs to be transposed
if m < d:
Z = Z.T
# Diagonal averaging
for k in range(1, n+1):
if k <= d_min:
# First part
y[k-1] = np.mean([Z[i-1, k-i] for i in range(1, k+1)])
elif d_min < k <= m_max:
# Middle part
y[k-1] = np.mean([Z[i-1, k-i] for i in range(1, d_min+1)])
else:
# Last part
y[k-1] = np.mean([Z[i-1, k-i] for i in range(k-m_max+1, n-m_max+2)])
return y
def _reconstruct_components(self, Y, x):
"""
Adaptively reconstruct components based on frequency similarity and component correlation.
"""
n = len(x)
d = Y.shape[0]
# Initialize components and mask
SGCs = []
mask = np.ones(d, dtype=bool)
while np.any(mask):
# Get first unprocessed component
idx = np.where(mask)[0][0]
group_idx = [idx]
# Find similar components
for i in range(idx+1, d):
if not mask[i]:
continue
# Calculate correlation
corr = np.corrcoef(Y[idx], Y[i])[0, 1]
# Calculate frequency similarity
fft_idx = np.abs(fft(Y[idx]))
fft_i = np.abs(fft(Y[i]))
peak_idx = fftfreq(n)[np.argmax(fft_idx[1:n//2]) + 1]
peak_i = fftfreq(n)[np.argmax(fft_i[1:n//2]) + 1]
freq_sim = 1 - abs(peak_idx - peak_i) / 0.5 # 0.5 is the Nyquist frequency
# Group components with high correlation or frequency similarity
if corr > 0.5 or freq_sim > 0.8:
group_idx.append(i)
# Mark grouped components as processed
mask[group_idx] = False
# Combine grouped components
sgc = np.sum(Y[group_idx], axis=0)
SGCs.append(sgc)
# Calculate residual error ratio
residual = x - np.sum(SGCs, axis=0)
nmse = np.sum(residual**2) / np.sum(x**2)
# Check if error is below threshold
if nmse < self.threshold:
break
return SGCs, residual
def decompose(self, x, tau=1):
"""
Decompose time series into symplectic geometry components.
"""
x = np.asarray(x)
n = len(x)
# Step 1: Determine embedding dimension
d = self._determine_embedding_dimension(x)
print(f"Embedding dimension: {
d}")
# Step 2: Construct trajectory matrix
X = self._construct_trajectory_matrix(x, d, tau)
# Step 3: Symplectic geometry transformation
sigma, Q = self._symplectic_geometry_transformation(X)
# Step 4: Initial single component reconstruction
m = n - (d - 1) * tau
Y = np.zeros((d, n))
for i in range(d):
# Transform coefficient matrix
S_i = Q[:, i].reshape(-1, 1).T @ X.T
# Reconstruction matrix
Z_i = Q[:, i].reshape(-1, 1) @ S_i
# Diagonal averaging to get time series
Y[i] = self._diagonal_averaging(Z_i, n, d, tau)
# Step 5: Adaptive component reconstruction
SGCs, residual = self._reconstruct_components(Y, x)
return SGCs, residual
def plot_decomposition(self, x, SGCs, residual):
"""
Plot original signal, decomposed components, and residual.
"""
n = len(x)
t = np.arange(n)
# Number of components plus original and residual
n_plots = len(SGCs) + 2
plt.figure(figsize=(10, 2*n_plots))
# Plot original signal
plt.subplot(n_plots, 1, 1)
plt.plot(t, x)
plt.title('Original Signal')
plt.grid(True)
# Plot components
for i, sgc in enumerate(SGCs):
plt.subplot(n_plots, 1, i+2)
plt.plot(t, sgc)
plt.title(f'SGC{
i+1}')
plt.grid(True)
# Plot residual
plt.subplot(n_plots, 1, n_plots)
plt.plot(t, residual)
plt.title('Residual')
plt.grid(True)
plt.tight_layout()
plt.show()
def plot_envelope_spectrum(self, SGCs, fs=1.0):
"""
Plot envelope spectrum of each component.
"""
n_comps = len(SGCs)
plt.figure(figsize=(10, 2*n_comps))
for i, sgc in enumerate(SGCs):
# Calculate Hilbert transform to get analytic signal
analytic_signal = signal.hilbert(sgc)
# Calculate amplitude envelope
amplitude_envelope = np.abs(analytic_signal)
# Calculate envelope spectrum
n = len(sgc)
env_spectrum = np.abs(fft(amplitude_envelope)[:n//2])
freqs = fftfreq(n, 1/fs)[:n//2]
# Plot envelope spectrum
plt.subplot(n_comps, 1, i+1)
plt.plot(freqs, env_spectrum)
plt.title(f'SGC{
i+1} Envelope Spectrum')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.tight_layout()
plt.show()
3.2 模拟信号分析示例
下面我们使用模拟信号来验证SGMD方法的有效性,并与其他方法(如EEMD、LCD和小波变换)进行比较。
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from sgmd import SGMD # 导入我们实现的SGMD类
# 设置随机种子以保证结果可复现
np.random.seed(42)
# 生成时间轴
fs = 1000 # 采样频率
t = np.arange(0, 1, 1/fs) # 1秒长的信号
# 构造复杂调幅调频信号
x1 = 2 * np.sin(60 * np.pi * t) * (1 + 0.5 * np.sin(2 * np.pi * t))
x2 = np.sin(120 * np.pi * t)
x3 = 0.5 * np.cos(10 * np.pi * t)
x = x1 + x2 + x3
# 实例化SGMD
sgmd = SGMD(threshold=0.01)
# 分解信号
SGCs, residual = sgmd.decompose(x)
# 输出分量数量
print(f"Number of SGCs: {
len(SGCs)}")
# 绘制分解结果
sgmd.plot_decomposition(x, SGCs, residual)
# 计算分解分量与实际分量的相关系数
for i, sgc in enumerate(SGCs):
corr_x1 = np.corrcoef(x1, sgc)[0, 1]
corr_x2 = np.corrcoef(x2, sgc)[0, 1]
corr_x3 = np.corrcoef(x3, sgc)[0, 1]
print(f"SGC{
i+1} correlation with x1: {
corr_x1:.4f}")
print(f"SGC{
i+1} correlation with x2: {
corr_x2:.4f}")
print(f"SGC{
i+1} correlation with x3: {
corr_x3:.4f}")
print("-" * 40)
# 计算绝对误差
err1 = np.abs(SGCs[0] - x1)
err2 = np.abs(SGCs[1] - x2)
err3 = np.abs(SGCs[2] - x3)
# 绘制绝对误差
plt.figure(figsize=(10, 6))
plt.subplot(3, 1, 1)
plt.plot(t, err1)
plt.title('Absolute Error between SGC1 and x1')
plt.grid(True)
plt.subplot(3, 1, 2)
plt.plot(t, err2)
plt.title('Absolute Error between SGC2 and x2')
plt.grid(True)
plt.subplot(3, 1, 3)
plt.plot(t, err3)
plt.title('Absolute Error between SGC3 and x3')
plt.grid(True)
plt.tight_layout()
plt.show()
3.3 带噪声信号分析示例
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from sgmd import SGMD # 导入我们实现的SGMD类
# 设置随机种子以保证结果可复现
np.random.seed(42)
# 生成时间轴
fs = 1000 # 采样频率
t = np.arange(0, 1, 1/fs) # 1秒长的信号
# 构造带噪声信号
x1 = 2 * (1 + 0.5 * np.sin(2 * np.pi * t)) * np.sin(40 * np.pi * t)
x2 = 1.2 * np.cos(25 * t)
x_clean = x1 + x2
# 添加高斯白噪声
# 信噪比为5dB
snr = 5
x_power = np.sum(x_clean**2) / len(x_clean)
noise_power = x_power / (10**(snr/10))
noise = np.random.normal(0, np.sqrt(noise_power), len(x_clean))
x = x_clean + noise
# 实例化SGMD
sgmd = SGMD(threshold=0.01)
# 分解信号
SGCs, residual = sgmd.decompose(x)
# 输出分量数量
print(f"Number of SGCs: {
len(SGCs)}")
# 绘制分解结果
sgmd.plot_decomposition(x, SGCs, residual)
# 绘制包络谱
sgmd.plot_envelope_spectrum(SGCs, fs=fs)
# 计算分解分量与实际分量的相关系数
for i, sgc in enumerate(SGCs):
corr_x1 = np.corrcoef(x1, sgc)[0, 1]
corr_x2 = np.corrcoef(x2, sgc)[0, 1]
print(f"SGC{
i+1} correlation with x1: {
corr_x1:.4f}")
print(f"SGC{
i+1} correlation with x2: {
corr_x2:.4f}")
print("-" * 40)
# 添加更强噪声的情况
# 信噪比为-5dB
snr = -5
x_power = np.sum(x_clean**2) / len(x_clean)
noise_power = x_power / (10**(snr/10))
strong_noise = np.random.normal(0, np.sqrt(noise_power), len(x_clean))
x_strong_noise = x_clean + strong_noise
# 对强噪声信号进行分解
SGCs_strong, residual_strong = sgmd.decompose(x_strong_noise)
# 输出分量数量
print(f"Number of SGCs (strong noise): {
len(SGCs_strong)}")
# 绘制强噪声信号的分解结果
sgmd.plot_decomposition(x_strong_noise, SGCs_strong, residual_strong)
# 计算分解分量与实际分量的相关系数
for i, sgc in enumerate(SGCs_strong):
corr_x1 = np.corrcoef(x1, sgc)[0, 1]
corr_x2 = np.corrcoef(x2, sgc)[0, 1]
print(f"SGC{
i+1} (strong noise) correlation with x1: {
corr_x1:.4f}")
print(f"SGC{
i+1} (strong noise) correlation with x2: {
corr_x2:.4f}")
print("-" * 40)
3.4 旋转机械复合故障诊断示例
下面我们使用实际旋转机械复合故障振动信号来验证SGMD方法的有效性。
import numpy as np
import matplotlib.pyplot as plt
import scipy.io as sio
from scipy import signal
from sgmd import SGMD # 导入我们实现的SGMD类
mat_data = sio.loadmat('rotating_machinery_fault.mat')
x = mat_data['vibration_signal'].flatten()
fs = 8192 # 采样频率
# 截取一部分数据进行分析
n_samples = 2048
x = x[:n_samples]
# 实例化SGMD
sgmd = SGMD(threshold=0.01)
# 分解信号
让我继续上一部分未完成的代码示例:
```python
# 实例化SGMD
sgmd = SGMD(threshold=0.01)
# 分解信号
SGCs, residual = sgmd.decompose(x)
# 输出分量数量
print(f"Number of SGCs: {
len(SGCs)}")
# 绘制分解结果
sgmd.plot_decomposition(x, SGCs, residual)
# 计算包络谱用于故障诊断
sgmd.plot_envelope_spectrum(SGCs, fs=fs)
# 计算轴承外环故障特征频率和齿轮故障频率
fr = 15 # 旋转频率,单位Hz
fo = 31 # 轴承外环故障频率,单位Hz
# 分析包络谱中的特征频率
for i, sgc in enumerate(SGCs):
# 计算包络
analytic_signal = signal.hilbert(sgc)
amplitude_envelope = np.abs(analytic_signal)
# 计算包络谱
n = len(sgc)
env_spectrum = np.abs(fft(amplitude_envelope)[:n//2])
freqs = fftfreq(n, 1/fs)[:n//2]
# 查找包络谱中特征频率附近的峰值
fo_idx = np.argmin(np.abs(freqs - fo))
fr_idx = np.argmin(np.abs(freqs - fr))
# 计算特征频率峰值与基频峰值的比值作为故障严重程度指标
fo_peak = env_spectrum[fo_idx]
fr_peak = env_spectrum[fr_idx]
print(f"SGC{
i+1}:")
print(f" Bearing outer ring fault frequency peak: {
fo_peak:.2f}")
print(f" Rotating frequency peak: {
fr_peak:.2f}")
# 故障判断
if fo_peak > 0.5 * env_spectrum.max():
print(f" SGC{
i+1} contains bearing outer ring fault features")
if fr_peak > 0.5 * env_spectrum.max():
print(f" SGC{
i+1} contains gear fault features")
print("-" * 40)
# 与其他方法比较
# 这里我们实现一个简单的EEMD方法进行比较
def eemd(x, noise_amp=0.1, ensemble_num=100):
"""
Ensemble Empirical Mode Decomposition (EEMD)
"""
# Here we would normally implement the full EEMD algorithm
# For the sake of example, we'll use a simplified approach
# In a real implementation, you would use PyEMD or similar library
# Simple EMD simulation for comparison
imfs = []
residual = x.copy()
for i in range(5): # Extract 5 IMFs
# In a real implementation, we'd add noise and compute proper IMFs
# Here we're just using band-pass filtering for demonstration
imf = signal.butter(3, [(i+1)*5/fs*2, (i+2)*20/fs*2], 'bandpass', output='sos')
imf = signal.sosfilt(imf, residual)
imfs.append(imf)
residual = residual - imf
imfs.append(residual) # Add the final residual
return np.array(imfs)
# Run EEMD
imfs = eemd(x)
# Plot EEMD results
plt.figure(figsize=(10, 12))
plt.subplot(imfs.shape[0]+1, 1, 1)
plt.plot(x)
plt.title('Original Signal')
plt.grid(True)
for i in range(imfs.shape[0]):
plt.subplot(imfs.shape[0]+1, 1, i+2)
plt.plot(imfs[i])
plt.title(f'IMF{
i+1}')
plt.grid(True)
plt.tight_layout()
plt.show()
# Compare running time
import time
# Measure SGMD time
start_time = time.time()
SGCs, residual = sgmd.decompose(x)
sgmd_time = time.time() - start_time
print(f"SGMD running time: {
sgmd_time:.6f} seconds")
# Measure EEMD time
start_time = time.time()
imfs = eemd(x)
eemd_time = time.time() - start_time
print(f"EEMD running time: {
eemd_time:.6f} seconds")
# Calculate and plot envelope spectrums for IMFs
plt.figure(figsize=(10, 12))
for i in range(min(4, imfs.shape[0])):
# Calculate Hilbert transform
analytic_signal = signal.hilbert(imfs[i])
amplitude_envelope = np.abs(analytic_signal)
# Calculate envelope spectrum
n = len(imfs[i])
env_spectrum = np.abs(fft(amplitude_envelope)[:n//2])
freqs = fftfreq(n, 1/fs)[:n//2]
plt.subplot(4, 1, i+1)
plt.plot(freqs, env_spectrum)
plt.title(f'IMF{
i+1} Envelope Spectrum')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.grid(True)
# Highlight key frequencies
plt.axvline(x=fr, color='r', linestyle='--', label=f'Rotating Frequency ({
fr} Hz)')
plt.axvline(x=fo, color='g', linestyle='--', label=f'Bearing Fault Frequency ({
fo} Hz)')
plt.legend()
plt.tight_layout()
plt.show()
4. 参数分析与对比研究
为了更全面地评估SGMD方法的性能,下面我们进行参数分析与与其他方法的对比研究。
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
import time
from sgmd import SGMD
# 设置随机种子以保证结果可复现
np.random.seed(42)
# 生成模拟信号
fs = 1000 # 采样频率
t = np.arange(0, 1, 1/fs) # 1秒长的信号
# 构造带噪声信号
x1 = 2 * (1 + 0.5 * np.sin(2 * np.pi * t)) * np.sin(40 * np.pi * t)
x2 = 1.2 * np.cos(25 * t)
x_clean = x1 + x2
# 创建不同信噪比的信号
snr_levels = [-10, -5, 0, 5, 10, 15, 20]
signals = []
for snr in snr_levels:
x_power = np.sum(x_clean**2) / len(x_clean)
noise_power = x_power / (10**(snr/10))
noise = np.random.normal(0, np.sqrt(noise_power), len(x_clean))
signals.append(x_clean + noise)
# 性能指标
corr_sgmd_x1 = []
corr_sgmd_x2 = []
time_sgmd = []
# 分析不同信噪比的性能
for i, snr in enumerate(snr_levels):
print(f"Processing SNR = {
snr} dB")
# 实例化SGMD
sgmd = SGMD(threshold=0.01)
# 测量运行时间
start_time = time.time()
SGCs, residual = sgmd.decompose(signals[i])
end_time = time.time()
# 记录运行时间
time_sgmd.append(end_time - start_time)
# 计算相关系数
if len(SGCs) >= 1:
# 找出与x1和x2相关性最高的分量
corr_with_x1 = [np.abs(np.corrcoef(x1, sgc)[0, 1]) for sgc in SGCs]
corr_with_x2 = [np.abs(np.corrcoef(x2, sgc)[0, 1]) for sgc in SGCs]
corr_sgmd_x1.append(max(corr_with_x1))
corr_sgmd_x2.append(max(corr_with_x2))
else:
corr_sgmd_x1.append(0)
corr_sgmd_x2.append(0)
# 绘制相关系数随信噪比的变化
plt.figure(figsize=(10, 6))
plt.plot(snr_levels, corr_sgmd_x1, 'o-', label='Component 1')
plt.plot(snr_levels, corr_sgmd_x2, 's-', label='Component 2')
plt.xlabel('SNR (dB)')
plt.ylabel('Correlation Coefficient')
plt.title('SGMD Performance vs. SNR')
plt.grid(True)
plt.legend()
plt.show()
# 绘制运行时间
plt.figure(figsize=(8, 4))
plt.plot(snr_levels, time_sgmd, 'o-')
plt.xlabel('SNR (dB)')
plt.ylabel('Running Time (s)')
plt.title('SGMD Running Time vs. SNR')
plt.grid(True)
plt.show()
# 不同嵌入维数的影响分析
d_values = [5, 10, 20, 50, 100]
x = signals[3] # 使用SNR=5dB的信号
corr_vs_d_x1 = []
corr_vs_d_x2 = []
time_vs_d = []
for d in d_values:
print(f"Testing embedding dimension d = {
d}")
# 创建一个自定义SGMD实例,不使用自适应嵌入维数
class CustomSGMD(SGMD):
def _determine_embedding_dimension(self, x):
return d
sgmd = CustomSGMD(threshold=0.01)
# 测量运行时间
start_time = time.time()
SGCs, residual = sgmd.decompose(x)
end_time = time.time()
# 记录运行时间
time_vs_d.append(end_time - start_time)
# 计算相关系数
if len(SGCs) >= 1:
# 找出与x1和x2相关性最高的分量
corr_with_x1 = [np.abs(np.corrcoef(x1, sgc)[0, 1]) for sgc in SGCs]
corr_with_x2 = [np.abs(np.corrcoef(x2, sgc)[0, 1]) for sgc in SGCs]
corr_vs_d_x1.append(max(corr_with_x1))
corr_vs_d_x2.append(max(corr_with_x2))
else:
corr_vs_d_x1.append(0)
corr_vs_d_x2.append(0)
# 绘制嵌入维数的影响
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(d_values, corr_vs_d_x1, 'o-', label='Component 1')
plt.plot(d_values, corr_vs_d_x2, 's-', label='Component 2')
plt.xlabel('Embedding Dimension')
plt.ylabel('Correlation Coefficient')
plt.title('SGMD Performance vs. Embedding Dimension')
plt.grid(True)
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(d_values, time_vs_d, 'o-')
plt.xlabel('Embedding Dimension')
plt.ylabel('Running Time (s)')
plt.title('SGMD Running Time vs. Embedding Dimension')
plt.grid(True)
plt.tight_layout()
plt.show()
5. 旋转机械复合故障诊断的完整实现
下面展示一个完整的旋转机械复合故障诊断案例,包括读取数据、信号预处理、特征提取和故障诊断。
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from scipy.fft import fft, fftfreq
import pandas as pd
from sgmd import SGMD
def load_fault_data(filename):
"""
加载旋转机械故障数据
"""
# 在实际应用中,根据数据格式选择合适的加载方法
# 这里假设数据是CSV格式
data = pd.read_csv(filename)
x = data['acceleration'].values
fs = 8192 # 采样频率,单位Hz
return x, fs
def preprocess_signal(x, fs):
"""
信号预处理
"""
# 去除直流分量
x_processed = x - np.mean(x)
# 应用带通滤波器 (10Hz - 2000Hz)
b, a = signal.butter(4, [10/(fs/2), 2000/(fs/2)], 'bandpass')
x_processed = signal.filtfilt(b, a, x_processed)
# 截取合适的数据长度
n_samples = min(len(x_processed), 8192) # 使用1秒钟的数据
x_processed = x_processed[:n_samples]
return x_processed
def extract_fault_features(sgcs, fs):
"""
从SGMD分量中提取故障特征
"""
features = {
}
# 旋转机械参数
rpm = 900 # 转速,单位r/min
fr = rpm / 60 # 旋转频率,单位Hz
z = 37 # 齿轮齿数
fg = fr # 齿轮故障特征频率 (cracked tooth)
fo = 31 # 轴承外环故障频率,单位Hz
for i, sgc in enumerate(sgcs):
# 计算包络
analytic_signal = signal.hilbert(sgc)
amplitude_envelope = np.abs(analytic_signal)
# 计算包络谱
n = len(sgc)
env_spectrum = np.abs(fft(amplitude_envelope)[:n//2])
freqs = fftfreq(n, 1/fs)[:n//2]
# 查找特征频率附近的峰值
fr_idx = np.argmin(np.abs(freqs - fr))
fo_idx = np.argmin(np.abs(freqs - fo))
# 考虑谐波和边频带
fr_harmonics = [np.argmin(np.abs(freqs - fr*j)) for j in range(1, 5)]
fo_harmonics = [np.argmin(np.abs(freqs - fo*j)) for j in range(1, 5)]
# 计算各频率处的幅值
fr_amps = [env_spectrum[idx] for idx in fr_harmonics]
fo_amps = [env_spectrum[idx] for idx in fo_harmonics]
# 保存特征
features[f'SGC{
i+1}_fr_amps'] = fr_amps
features[f'SGC{
i+1}_fo_amps'] = fo_amps
# 计算指标
features[f'SGC{
i+1}_fr_ratio'] = sum(fr_amps) / env_spectrum.sum()
features[f'SGC{
i+1}_fo_ratio'] = sum(fo_amps) / env_spectrum.sum()
# 计算峭度和偏度作为时域特征
features[f'SGC{
i+1}_kurtosis'] = np.mean((sgc - np.mean(sgc))**4) / (np.std(sgc)**4)
features[f'SGC{
i+1}_skewness'] = np.mean((sgc - np.mean(sgc))**3) / (np.std(sgc)**3)
return features
def diagnose_fault(features):
"""
基于提取的特征进行故障诊断
"""
diagnosis = {
'bearing_outer_fault': False,
'gear_tooth_fault': False,
'bearing_fault_severity': 0,
'gear_fault_severity': 0
}
# 设置故障判断阈值
bearing_threshold = 0.05
gear_threshold = 0.02
# 检查每个分量的特征
for key in features:
if '_fo_ratio' in key and features[key] > bearing_threshold:
diagnosis['bearing_outer_fault'] = True
diagnosis['bearing_fault_severity'] = max(diagnosis['bearing_fault_severity'], features[key])
if '_fr_ratio' in key and features[key] > gear_threshold:
diagnosis['gear_tooth_fault'] = True
diagnosis['gear_fault_severity'] = max(diagnosis['gear_fault_severity'], features[key])
return diagnosis
def main():
# 加载数据
filename = 'rotating_machinery_fault.csv'
x, fs = load_fault_data(filename)
# 预处理信号
x_processed = preprocess_signal(x, fs)
# 实例化SGMD
sgmd = SGMD(threshold=0.01)
# 分解信号
SGCs, residual = sgmd.decompose(x_processed)
# 绘制分解结果
sgmd.plot_decomposition(x_processed, SGCs, residual)
# 计算包络谱
sgmd.plot_envelope_spectrum(SGCs, fs=fs)
# 提取故障特征
features = extract_fault_features(SGCs, fs)
# 故障诊断
diagnosis = diagnose_fault(features)
# 打印诊断结果
print("Fault Diagnosis Results:")
print("-" * 30)
if diagnosis['bearing_outer_fault']:
print(f"Bearing outer ring fault detected (severity: {
diagnosis['bearing_fault_severity']:.4f})")
else:
print("No bearing outer ring fault detected")
if diagnosis['gear_tooth_fault']:
print(f"Gear tooth fault detected (severity: {
diagnosis['gear_fault_severity']:.4f})")
else:
print("No gear tooth fault detected")
# 打印详细特征
print("\nDetailed Features:")
print("-" * 30)
for key, value in features.items():
if isinstance(value, list):
print(f"{
key}: {
[f'{
v:.4f}' for v in value]}")
else:
print(f"{
key}: {
value:.4f}")
if __name__ == "__main__":
main()
6. SGMD方法的优化与扩展
SGMD方法虽然具有诸多优势,但仍然存在一些可以优化的地方。下面提供一些优化和扩展的思路及示例代码。
6.1 优化嵌入维数自适应选择策略
def improved_embedding_dimension(x, fs=1.0):
"""
改进的嵌入维数自适应选择策略
"""
n = len(x)
# 使用多个方法估计嵌入维数
# 1. 基于PSD的方法
psd_x = np.abs(fft(x))**2
freqs = fftfreq(n, 1/fs)[:n//2]
psd_x = psd_x[:n//2]
f_max = freqs[np.argmax(psd_x[1:]) + 1] # 避免直流分量
d_psd = int(1.2 * fs / f_max)
# 2. 基于自相关函数的方法
acf = np.correlate(x, x, mode='full')
acf = acf[n-1:] / acf[n-1] # 标准化
# 找到第一个过零点
zero_crossings = np.where(np.diff(np.signbit(acf)))[0]
if len(zero_crossings) > 0:
d_acf = zero_crossings[0]
else:
d_acf = n // 10
# 3. 基于互信息的方法 (简化版)
# 在实际实现中,应使用更复杂的互信息计算
d_mi = n // 8
# 综合考虑多个方法的结果
d = min(int(np.mean([d_psd, d_acf, d_mi])), n // 2)
# 限制嵌入维数范围
d = max(min(d, n // 2), 2)
return d
6.2 改进的分量重构策略
def improved_component_reconstruction(Y, x):
"""
改进的分量重构策略
"""
n = len(x)
d = Y.shape[0]
# 步骤1: 使用频谱特性聚类分量
# 计算每个分量的归一化功率谱
spectra = []
for i in range(d):
spec = np.abs(fft(Y[i])[:n//2])**2
spec /= np.sum(spec)
spectra.append(spec)
# 计算分量之间的频谱相似度
similarity_matrix = np.zeros((d, d))
for i in range(d):
for j in range(i+1, d):
# 使用Kullback-Leibler散度衡量相似度
kl_div = np.sum(spectra[i] * np.log(spectra[i] / (spectra[j] + 1e-10) + 1e-10))
similarity_matrix[i, j] = similarity_matrix[j, i] = np.exp(-kl_div)
# 使用谱聚类进行分组
from sklearn.cluster import SpectralClustering
# 估计最佳聚类数
eigenvalues = np.sort(np.linalg.eigvals(similarity_matrix))[::-1]
eigenvalue_diffs = np.diff(eigenvalues)
n_clusters = np.argmax(eigenvalue_diffs[:min(10, len(eigenvalue_diffs))]) + 2
# 限制聚类数
n_clusters = min(max(n_clusters, 2), d // 2)
# 执行谱聚类
clustering = SpectralClustering(n_clusters=n_clusters, affinity='precomputed', random_state=42)
cluster_labels = clustering.fit_predict(similarity_matrix)
# 步骤2: 基于聚类结果重构分量
SGCs = []
for cluster in range(n_clusters):
# 获取当前聚类的所有分量
cluster_indices = np.where(cluster_labels == cluster)[0]
if len(cluster_indices) > 0:
# 合并同一聚类的分量
sgc = np.sum(Y[cluster_indices], axis=0)
SGCs.append(sgc)
# 计算残差
residual = x - np.sum(SGCs, axis=0)
return SGCs, residual
6.3 端点效应处理优化
def mirror_extension(x, extend_length):
"""
镜像扩展方法处理端点效应
"""
n = len(x)
# 左端点扩展
left_extension = 2*x[0] - x[extend_length:0:-1]
# 右端点扩展
right_extension = 2*x[-1] - x[-2:-extend_length-2:-1]
# 合并扩展信号
x_extended = np.concatenate((left_extension, x, right_extension))
return x_extended, extend_length
4. 结论与展望
本文基于辛几何相似变换提出了一种新的非线性动态分解方法SGMD,用于分解动态时间序列信号。该方法的核心是利用辛几何相似变换求解哈密顿矩阵的特征值,并保持原始信号的本质特性不变。SGMD与三种方法(EEMD、LCD和小波变换)通过分析复杂合成信号和带噪声信号进行了比较,结果表明所提出的SGMD方法可以获得更好的分解性能和鲁棒性。最后,将SGMD引入分析旋转机械复合故障的振动信号,并与相同的三种方法进行比较,分析结果表明所提出的SGMD方法可以获得更好的旋转机械复合故障诊断效果。
SGMD方法的主要优势
-
无需用户定义参数:SGMD不需要像EEMD和小波变换那样选择参数,避免了参数对结果的敏感性影响。
-
优异的噪声鲁棒性:通过辛几何相似变换保持原始信号的本质特性,SGMD能够有效处理强噪声信号,并准确提取有用分量。
-
保持信号本质特性:辛几何相似变换可以保持测度并保持原始时间序列的本质特性不变,避免了模式混叠和分量失真问题。
-
物理解释明确:SGMD将信号分解转换为辛几何变换问题,具有明确的数学和物理解释,避免了经验选择参数的不确定性。
-
高效计算:与LCD方法相比,SGMD具有更快的计算速度,提高了故障诊断的效率。