
1. 项目背景与核心问题拆解1.1 重大装备健康管理到底在管什么重大装备健康管理英文叫PHMPrognostics and Health Management说白了就是给大型设备装一套“体检加预判”的系统。这套系统要干三件事第一实时感知设备当前状态第二判断它是不是已经出了问题、问题在哪第三预测它还能撑多久、什么时候该修。风电齿轮箱、航空发动机、船舶动力系统、轨道交通牵引系统这些动辄几百万上千万的装备一旦非计划停机损失是按小时甚至按分钟算的。我最早接触PHM是在一个风电传动链监测项目上。当时团队拿到了一堆振动加速度传感器数据采样频率20kHz每台机组每天产生几十GB的原始信号。问题很快就来了正常运行的样本多如牛毛故障样本少得可怜。一台齿轮箱从健康到失效可能跑了大半年真正处于“早期故障”状态的数据窗口可能只有几天甚至几小时。这就是PHM领域最经典的痛点——极端类别不平衡。1.2 为什么故障样本总是那么少这个问题的根源在于工业场景的物理约束。你不可能为了让模型多学点故障样本就故意把一台几千万的设备搞坏。故障是“稀有事件”而且从经济性和安全性角度我们恰恰希望它越少越好。但机器学习模型尤其是分类模型天生对不平衡数据敏感。举个直观的例子如果10000个样本里只有50个故障样本模型只要把所有样本都判为“正常”准确率就能到99.5%。这个数字看起来很漂亮但故障一个都没抓到实际部署就是灾难。更麻烦的是PHM不只是做“故障/正常”的二分类。很多时候我们要做多级故障诊断比如轴承外圈故障、内圈故障、滚动体故障、保持架故障每一类的样本量还不一样。有些故障模式在历史上只出现过一两次样本量个位数。这种情况下常规的过采样、欠采样、代价敏感学习都显得力不从心。1.3 Feature-level SMOTE的切入点SMOTESynthetic Minority Over-sampling Technique本身不是新东西1998年就提出来了。它的核心思想是在少数类样本之间做线性插值生成新的合成样本。但传统SMOTE是在原始特征空间或者经过简单归一化后的空间里操作的。对于PHM场景尤其是振动信号、电流信号、温度信号这类高维时序数据直接在原始空间做插值会带来两个严重问题。第一原始信号维度极高。一个振动加速度信号做FFT之后可能有好几千个频点直接在这个空间里找最近邻距离度量会被大量噪声维度主导生成的合成样本物理意义不明。第二PHM的特征往往有明确的物理含义比如啮合频率幅值、边频带能量、峭度、裕度因子等。在原始信号上插值可能生成一个“既不像正常也不像故障”的怪东西反而污染训练集。Feature-level SMOTE的思路就是先做特征工程把原始信号映射到一个低维、有物理意义的特征空间然后在这个特征空间里做SMOTE。这样做的好处是插值操作发生在有明确工程含义的维度上生成的合成样本更符合故障机理模型学到的决策边界也更稳健。2. 特征工程Feature-level SMOTE的地基2.1 时域特征最直接但最容易被低估时域特征是从原始时序信号直接算出来的统计量。别小看这些简单指标在PHM里它们往往是最先报警的那一批。我常用的时域特征包括均方根值RMS反映信号能量对磨损类故障敏感。峭度Kurtosis对冲击成分极其敏感早期轴承点蚀、齿轮断齿都会让峭度飙升。峰值因子Crest Factor峰值与RMS之比适合检测早期冲击。裕度因子Clearance Factor峰值与方根幅值之比对摩擦类故障有奇效。波形因子Shape FactorRMS与绝对均值之比反映波形变化。这些特征的计算复杂度低实时性好适合在线监测。但单独使用时域特征有个问题它们对负载和转速变化比较敏感。同一台设备负载从50%拉到100%RMS可能翻倍但设备其实是健康的。所以时域特征通常需要做工况归一化或者和转速信号一起作为条件变量。2.2 频域特征故障机理的指纹频域特征是PHM故障诊断的核心。旋转机械的故障特征频率是可以从运动学关系精确算出来的。比如一个滚动轴承外圈故障特征频率BPFO、内圈故障特征频率BPFI、滚动体故障特征频率BSF、保持架故障特征频率FTF都有明确的公式。齿轮箱的啮合频率、边频带间隔也都和齿数、转速直接相关。我通常会把频域特征分成两类。一类是特征频率幅值直接在频谱上取故障特征频率及其谐波处的幅值。另一类是频带能量把频谱划分成若干频带计算每个频带的能量占比。频带划分可以等宽也可以按倍频程或者根据具体设备的故障机理来定制。这里有个实操细节做FFT之前加窗函数的选择很关键。汉宁窗适合大多数稳态信号但如果信号里有明显的冲击成分矩形窗或者平顶窗可能更合适。另外频谱分辨率取决于采样时长对于低速重载设备特征频率间隔可能只有零点几赫兹需要足够长的采样窗口才能分辨。2.3 时频域特征非平稳工况的杀手锏重大装备经常在变转速、变负载工况下运行这时候单纯的时域或频域特征就不够用了。时频分析能把信号在时间和频率两个维度上同时展开捕捉非平稳特征。常用的方法包括短时傅里叶变换STFT、小波变换WT、希尔伯特-黄变换HHT、Wigner-Ville分布等。我在船舶动力系统监测项目里用过小波包分解。把振动信号做三层小波包分解得到8个频带的能量特征。船舶在加速、减速、转向时这些频带能量的变化模式能很好地区分正常工况和故障工况。小波基的选择上Daubechies系列db4、db6在机械故障诊断里用得最多因为它们的波形和冲击衰减比较像。时频域特征的问题是维度容易爆炸。STFT如果窗长选得小时间分辨率高但频率分辨率低窗长选得大反过来。小波包分解的层数越多频带越细特征维度越高。所以做Feature-level SMOTE之前通常需要先做一轮特征选择或降维。2.4 特征选择少而精比多而杂好特征不是越多越好。我见过太多项目上来就提取几百个特征然后一股脑扔给模型。结果模型训练慢、过拟合严重、可解释性差。Feature-level SMOTE尤其怕高维因为SMOTE的最近邻搜索在高维空间里会失效——这就是所谓的“维度灾难”。我的做法是分两步走。第一步用过滤法快速筛掉明显无关的特征比如方差接近零的、和标签相关性极低的。常用的指标有互信息、Fisher判别比、ReliefF。第二步用包裹法或嵌入法做精细选择。随机森林的特征重要性、LASSO回归的稀疏系数、递归特征消除RFE都是实战中好用的工具。对于Feature-level SMOTE我建议最终保留的特征维度控制在10到30之间。这个区间既能保留足够的判别信息又不至于让最近邻搜索失效。如果原始特征维度太高可以先做PCA或者自编码器降维但要注意降维后的特征物理意义会丢失SMOTE生成的样本解释性会变差。3. Feature-level SMOTE的实现细节3.1 标准SMOTE的数学原理回顾SMOTE的核心公式很简单。对于少数类中的每一个样本 ( x_i )找到它的 ( k ) 个最近邻也是少数类随机选一个邻居 ( x_{i,nn} )然后在两者之间随机插值[ x_{new} x_i \lambda \cdot (x_{i,nn} - x_i) ]其中 ( \lambda ) 是0到1之间的随机数。这个过程重复若干次直到少数类样本数量达到预期。标准SMOTE有几个明显缺陷。第一它对所有少数类样本一视同仁如果少数类内部有噪声或者离群点SMOTE会在这些坏样本周围生成更多坏样本。第二它不考虑多数类的分布生成的样本可能侵入多数类区域造成类别重叠。第三( k ) 值的选择很敏感( k ) 太小容易过拟合( k ) 太大可能跨越类别边界。3.2 在特征空间做SMOTE的注意事项Feature-level SMOTE不是简单地把原始信号换成特征向量就完事了。有几个坑我踩过这里直接说结论。第一特征尺度必须统一。时域特征里RMS可能是几十上百峭度可能是几到几十频域幅值可能是指数级变化。如果不做标准化SMOTE的欧氏距离会被大量纲特征主导。我通常用Z-score标准化或者RobustScaler对离群点更稳健。注意标准化参数只能从训练集算然后应用到验证集和测试集否则会数据泄露。第二类别边界要保护。如果少数类样本和多数类样本在特征空间里挨得很近SMOTE生成的样本很容易越界。这时候可以用Borderline-SMOTE或者ADASYN它们会根据样本周围的类别分布调整生成策略。Borderline-SMOTE只对“边界上的”少数类样本做过采样ADASYN则根据分类难度自适应地生成样本。第三合成样本要验证物理合理性。这是Feature-level SMOTE相比原始空间SMOTE的最大优势也是必须做的步骤。生成一个合成样本后检查它的特征值是否在物理可能范围内。比如峭度不能是负数频带能量占比不能超过1特征频率幅值不能超过总能量。如果越界这个样本就应该丢弃或者修正。3.3 代码实现从特征矩阵到合成样本下面是我在项目里常用的一个Feature-level SMOTE实现框架。用的是Python的imbalanced-learn库但加了自己的物理约束检查。import numpy as np from imblearn.over_sampling import SMOTE from sklearn.preprocessing import RobustScaler from sklearn.neighbors import NearestNeighbors def feature_level_smote(X_minority, X_majority, k_neighbors5, target_ratio0.5, physical_boundsNone): X_minority: 少数类特征矩阵 (n_minority, n_features) X_majority: 多数类特征矩阵 (n_majority, n_features) k_neighbors: SMOTE最近邻数 target_ratio: 目标少数类/多数类比例 physical_bounds: 每个特征的(下限, 上限)列表 n_minority X_minority.shape[0] n_majority X_majority.shape[0] n_synthetic int(target_ratio * n_majority) - n_minority if n_synthetic 0: return X_minority # 标准化 scaler RobustScaler() X_all np.vstack([X_minority, X_majority]) X_all_scaled scaler.fit_transform(X_all) X_min_scaled X_all_scaled[:n_minority] # 找最近邻 nn NearestNeighbors(n_neighborsk_neighbors1) nn.fit(X_min_scaled) synthetic_samples [] attempts 0 max_attempts n_synthetic * 10 while len(synthetic_samples) n_synthetic and attempts max_attempts: attempts 1 idx np.random.randint(0, n_minority) x_i X_min_scaled[idx] neighbors nn.kneighbors([x_i], return_distanceFalse)[0][1:] nn_idx np.random.choice(neighbors) x_nn X_min_scaled[nn_idx] lam np.random.random() x_new x_i lam * (x_nn - x_i) # 反标准化 x_new_original scaler.inverse_transform([x_new])[0] # 物理约束检查 if physical_bounds is not None: valid True for j, (low, high) in enumerate(physical_bounds): if x_new_original[j] low or x_new_original[j] high: valid False break if not valid: continue synthetic_samples.append(x_new_original) if len(synthetic_samples) 0: return X_minority X_synthetic np.array(synthetic_samples) return np.vstack([X_minority, X_synthetic])这段代码有几个关键点。RobustScaler用中位数和四分位距做标准化比Z-score更抗离群点。物理约束检查放在反标准化之后因为约束条件是针对原始特征值的。max_attempts防止在极端情况下死循环。如果生成的样本数不够至少返回原始少数类不会让程序崩掉。3.4 参数调优k值和采样比例怎么定k_neighbors的选择没有万能公式但有几个经验规则。如果少数类样本数少于50k取3到5比较安全。如果样本数在50到200之间k可以取5到10。样本数超过200k可以到10到15。k太大时最近邻可能跨越不同的故障子模式生成的样本会“四不像”。采样比例方面我不建议把少数类过采样到和多数类完全1:1。在PHM场景里完全平衡反而可能让模型对多数类的正常工况欠拟合。我通常把目标比例设在0.3到0.5之间也就是少数类补到多数类的30%到50%。具体数值可以用验证集上的F1分数或者G-mean来调。还有一个技巧是分层SMOTE。如果少数类内部还有子类别比如不同故障等级可以按子类别分别做SMOTE保持子类别之间的相对比例。这样生成的样本不会让某个子类别被过度代表。4. 与PHM诊断模型的集成实战4.1 模型选型从传统机器学习到深度学习Feature-level SMOTE生成的是特征向量所以下游模型可以是任何接受特征输入的分类器。我在不同项目里用过以下几类随机森林和梯度提升树XGBoost、LightGBM对特征尺度不敏感能输出特征重要性训练速度快适合中小规模特征集。在风电齿轮箱故障诊断里XGBoost加Feature-level SMOTE的F1分数比不加SMOTE提升了将近20个百分点。支持向量机SVM在小样本、高维特征下表现好但核函数选择和参数调优比较费时。RBF核配合SMOTE在轴承故障诊断里是经典组合。一维卷积神经网络1D-CNN如果坚持用原始信号做端到端学习1D-CNN可以直接处理时序数据。但这时候SMOTE就要在卷积特征层之后做而不是原始信号层。我通常把CNN当作特征提取器取全连接层之前的特征向量再做Feature-level SMOTE最后接一个分类头。自编码器分类器先用自编码器做无监督特征学习取编码器的低维表示作为特征再做SMOTE。这种方法在无标签数据多、有标签数据少的场景下特别有用。4.2 训练流程数据划分的陷阱PHM数据有个特点时间相关性很强。同一台设备连续运行的数据相邻时间窗口的样本高度相似。如果随机划分训练集和测试集测试集里的样本可能在训练集里有“近亲”导致评估结果虚高。正确的做法是按时间划分或者按设备划分。比如用前80%时间的数据做训练后20%做测试或者用A设备的全部数据做训练B设备的数据做测试。Feature-level SMOTE只能在训练集上做绝对不能对测试集做任何过采样。测试集必须保持原始分布否则评估结果没有意义。我见过有人把整个数据集做SMOTE之后再划分这是严重的数据泄露模型在真实场景里会崩得很惨。验证集的处理也有讲究。如果验证集也做SMOTE早停和超参数选择会偏向过采样后的分布。我的做法是训练集做SMOTE验证集保持原始不平衡分布用验证集上的召回率或者F1分数来做模型选择。虽然验证集指标看起来会低一些但更接近真实部署情况。4.3 评估指标准确率是最大的谎言在极端不平衡的PHM数据上准确率基本没有参考价值。我主要看以下几个指标指标含义PHM场景下的意义召回率Recall故障样本中被正确识别的比例漏报率越低越好直接关系安全精确率Precision预测为故障的样本中真正故障的比例误报率太低会导致频繁停机检修F1分数召回率和精确率的调和平均综合衡量适合不平衡数据G-mean各类召回率的几何平均衡量模型在所有类别上的均衡表现AUC-ROCROC曲线下面积对类别不平衡不敏感适合模型对比混淆矩阵各类别误判分布看具体哪些故障模式容易被混淆在安全关键的PHM场景里召回率通常优先于精确率。漏报一个早期故障可能导致设备彻底损坏甚至安全事故误报一次最多是多做一次检查。但误报太多也会导致“狼来了”效应运维人员会逐渐忽视报警。所以实际部署时我会根据设备的重要程度和检修成本来调整分类阈值。4.4 一个完整的实战案例船舶动力系统故障诊断我拿一个船舶动力系统的项目来串一遍完整流程。数据来自一台柴油机驱动的推进系统监测信号包括振动、缸压、排温、转速。故障类型有喷油器堵塞、气阀间隙异常、涡轮增压器效率下降、轴承磨损四类。正常样本约8000个四类故障样本分别只有120、85、60、35个。第一步特征提取。对振动信号提取时域特征12个、频域特征18个、时频域特征16个共46个初始特征。对缸压和排温信号提取统计特征和趋势特征共14个。总特征维度60。第二步特征选择。用随机森林做初步筛选保留重要性排名前25的特征。再用递归特征消除最终保留18个特征。这18个特征涵盖了主要故障机理缸压峰值、排温偏差、振动峭度、特征频率幅值等。第三步Feature-level SMOTE。对四类故障分别做SMOTE目标比例设为0.4。喷油器堵塞从120补到约3200气阀间隙异常从85补到约3200涡轮增压器效率下降从60补到约3200轴承磨损从35补到约3200。物理约束检查丢弃了约8%的合成样本。第四步模型训练。用XGBoost做五分类。训练集做SMOTE验证集和测试集保持原始分布。超参数用贝叶斯优化搜索主要调树的深度、学习率、子采样比例。第五步评估。测试集上不加SMOTE的XGBoost对轴承磨损的召回率只有0.42加Feature-level SMOTE之后提升到0.87。整体F1分数从0.61提升到0.83。误报率从12%降到7%。这个提升在船舶动力系统这种安全关键场景里是非常显著的。5. 常见问题与排查技巧实录5.1 合成样本质量差怎么办症状SMOTE生成的样本在特征空间里分布很怪模型训练后验证集表现反而下降。排查思路先可视化。用t-SNE或者UMAP把原始少数类样本和合成样本降到二维看合成样本是不是散得太开或者聚得太紧。如果合成样本明显偏离原始少数类的分布通常是k值太大或者特征尺度没统一。解决方法减小k值检查标准化步骤增加物理约束的严格程度。如果少数类内部本身就有多个子模式考虑分层SMOTE。5.2 模型过拟合合成样本症状训练集指标极高验证集和测试集指标明显低一截。排查思路检查合成样本是不是和原始少数类样本太像了。如果k值太小SMOTE生成的样本基本就是原始样本的轻微扰动模型会记住这些样本而不是学到泛化模式。解决方法增大k值增加合成样本的多样性。或者在SMOTE之后加一点高斯噪声让样本分布更平滑。另外正则化L1、L2、Dropout和早停也能缓解过拟合。5.3 类别重叠严重时的处理症状少数类和多数类在特征空间里混在一起SMOTE生成的样本大量落入多数类区域。排查思路计算少数类样本到最近多数类样本的距离分布。如果很多少数类样本的最近邻是多数类说明类别边界模糊。解决方法用Borderline-SMOTE或者ADASYN它们会优先在边界区域生成样本。或者先用Tomek Links、Edited Nearest Neighbors做数据清洗去掉边界上的噪声样本。如果重叠太严重可能需要重新审视特征工程看看是不是漏掉了关键的判别特征。5.4 多分类场景下的SMOTE策略症状多类故障诊断时有些类样本多有些类样本少SMOTE之后各类比例还是不平衡。排查思路SMOTE默认是对二分类设计的多分类时需要逐类处理。如果简单地一对多可能会让某些类被过度采样。解决方法用多类SMOTE变体比如SMOTE-ENC处理类别特征、或者对每个少数类分别做SMOTE目标比例统一设为多数类的某个百分比。我通常用“逐类SMOTE全局比例控制”的策略先对每个少数类单独过采样到多数类的40%如果总样本量太大再对多数类做欠采样。5.5 实时部署时的计算开销症状训练时SMOTE没问题但实时诊断时每次新数据来了都要重新做SMOTE计算太慢。排查思路SMOTE是训练阶段的数据增强技术不应该在推理阶段使用。推理阶段直接用训练好的模型对新样本做预测。解决方法把SMOTE完全放在离线训练流程里。在线推理时新样本经过同样的特征提取和标准化流程直接输入模型。如果模型需要定期更新SMOTE也在更新时离线做。另外特征提取的计算复杂度要控制时频域特征可以用滑动窗口增量计算避免每次从头算。5.6 常见问题速查表问题可能原因排查方法解决措施合成样本越界特征尺度不统一检查标准化前后特征范围用RobustScaler加物理约束验证集指标下降过拟合合成样本对比训练集和验证集指标增大k值加正则化早停类别重叠严重特征判别力不足可视化t-SNE算类间距离Borderline-SMOTE特征再选择多分类不平衡逐类SMOTE比例失控统计各类采样后数量全局比例控制分层采样推理速度慢在线做SMOTE检查推理流程SMOTE只在离线训练用召回率上不去分类阈值太高画PR曲线降低阈值代价敏感学习6. 进阶方向与个人经验6.1 从SMOTE到生成模型SMOTE本质上是线性插值生成能力有限。如果数据量足够可以尝试用生成对抗网络GAN或者变分自编码器VAE来生成故障样本。GAN能学到更复杂的分布生成的样本多样性更好。但GAN训练不稳定在工业小样本场景下容易模式崩溃。我的经验是样本量少于500时SMOTE系列方法更稳样本量超过1000时可以试试条件GANCGAN把故障类别作为条件输入。6.2 迁移学习与少样本故障诊断如果目标设备的故障样本极少但同类设备有较多历史数据可以用迁移学习。先在源设备上预训练特征提取器然后在目标设备上微调分类器。Feature-level SMOTE可以在微调阶段使用对目标设备的少数类样本做增强。这种方法在风电、轨道交通等设备型号多、单台故障少的场景下很有前景。6.3 我踩过的最大的坑早期做Feature-level SMOTE时我犯过一个错误把标准化参数从整个数据集上算包括测试集。结果模型在测试集上表现好得离谱实际部署时一塌糊涂。后来才明白标准化参数必须只从训练集算这是数据泄露的经典案例。另一个坑是物理约束检查太宽松生成了一批“看起来合理但物理上不可能”的样本比如频带能量占比超过1。这些样本让模型学到了错误的模式。现在我的做法是每个特征都定义严格的上下限越界的样本直接丢弃宁可少生成也不污染数据。6.4 一个实用的小技巧如果特征维度比较高但又不想做PCA丢失物理意义可以试试特征分组SMOTE。把特征按物理含义分成几组比如时域组、频域组、温度组然后在每组内部单独做SMOTE最后拼接。这样生成的样本在每组特征内部都符合物理规律组间的相关性可能弱一些但整体质量比全局SMOTE好。我在一个多传感器融合项目里用这个方法模型F1分数比全局SMOTE高了5个百分点。6.5 关于燃料电池混合动力船舶健康感知能量管理最近看到燃料电池混合动力船舶的健康感知能量管理是个热点。这类系统里燃料电池、锂电池、超级电容的退化状态直接影响能量分配策略。故障样本少、工况变化大、多能源耦合这些特点让Feature-level SMOTE特别适用。我设想的方案是对每个能源子系统的电压、电流、温度、阻抗谱提取特征分别做SMOTE增强然后训练一个多任务学习模型同时做故障诊断和剩余寿命预测。能量管理策略再根据诊断结果动态调整功率分配。这个方向值得深入做。6.6 故障诊断代码的工程化建议最后说几句代码工程化的事。Feature-level SMOTE的代码不要写成一坨脚本要模块化。特征提取、特征选择、SMOTE、模型训练、评估每个环节独立成函数或类。配置文件用YAML或者JSON把k值、采样比例、物理约束这些参数外置。这样换一个项目改配置文件就行不用改代码。另外每次实验都要记录随机种子、数据版本、参数配置不然结果没法复现。我吃过这个亏三个月后想复现一个实验发现随机种子没记结果怎么都调不回去。Feature-level SMOTE在PHM里不是万能药它解决的是数据层面的问题。如果特征本身没有判别力SMOTE生成再多样本也没用。如果故障机理不清楚物理约束就定不准。所以我的建议是先把特征工程和故障机理研究做扎实再用SMOTE做增强。顺序反了事倍功半。