简介:这份资源面向工业设备健康监测方向的学习者与研究人员,聚焦轴承故障诊断这一典型场景,提供将传统机器学习与深度学习结合的完整实践素材。包内共3201个文件,以3200张jpg灰度图像和1个py脚本为主,压缩包约4.1MB,图像文件可用于构建CNN的输入样本,py脚本则承载模型训练与诊断流程的实现代码。资源围绕支持向量机与卷积神经网络两条技术路线展开,涵盖数据预处理、模型构建、训练验证及结果对比等环节,帮助读者理解SVM如何通过最优超平面区分正常与异常振动状态,以及CNN如何借助卷积与池化层自动提取故障特征。目前已有1739人学习下载,适合希望对比两类算法在轴承故障识别中表现、并动手复现诊断流程的读者参考。
1. cnn-svm轴承故障诊断:把特征交给 CNN,把分类交给 SVM
振动信号里藏着轴承的健康状态,但直接把原始时序丢给分类器,十有八九效果稀烂。cnn-svm轴承故障诊断这套组合拳的思路很直接:用 CNN 卷积神经网络从振动信号里自动学出判别性特征,再把特征向量喂给 SVM 支持向量机做分类。它解决的是传统方法里人工设计特征(时域峭度、频域边带、包络谱峰值)费时费力、换工况就失效的问题,也绕开了纯 CNN 在小样本下容易过拟合的坑。适合谁?手头有 CWRU、XJTU-SY 这类轴承数据集,想快速搭一套能跑通、能解释、还能写进论文或设备巡检方案的从业者。下面按「信号怎么进网络 → 特征怎么接 SVM → 参数怎么调 → 坑在哪」一路讲透。
2. 从振动信号到 CNN 输入:先把数据管道搭对
2.1 为什么不能把原始时序直接塞进 SVM
轴承振动信号采样率常见 12kHz 或 48kHz,一段 1 秒信号就是上万个点。SVM 的核函数计算复杂度随样本维度平方增长,直接输入高维原始点,训练慢且泛化差。更关键的是,原始时序里的故障冲击成分被强噪声和工频干扰淹没,SVM 找不到有效间隔。常见做法是先做分帧、归一化,再用 CNN 做特征提取,把每帧信号压缩成几十维的特征向量。这一步的本质是降维加去噪,让 SVM 在低维空间里找超平面。
我一般会按「分帧 → 归一化 → 构造二维样本」三步走。分帧长度取 1024 或 2048 点,重叠率 50%,这样既保留冲击的完整性,又保证样本量够。归一化用 z-score 按帧做,不要按整个数据集做,否则工况差异会被抹掉。构造二维样本时,把一维帧 reshape 成 32×32 或 64×64 的灰度图,这是 CNN 最擅长的输入形态。
2.2 用 Python 把 CWRU 数据切成 CNN 能吃的样本
import numpy as np from scipy.io import loadmat from sklearn.preprocessing import StandardScaler def load_cwru(path, label): """加载 CWRU .mat 文件,返回振动信号和标签""" mat = loadmat(path) # CWRU 里驱动端信号键名通常是 X105_DE_time key = [k for k in mat.keys() if 'DE_time' in k][0] signal = mat[key].flatten() return signal, np.full(len(signal), label) def frame_signal(signal, frame_len=1024, overlap=0.5): """分帧,返回二维数组 (n_frames, frame_len)""" step = int(frame_len * (1 - overlap)) frames = [] for start in range(0, len(signal) - frame_len, step): frames.append(signal[start:start + frame_len]) return np.array(frames) def to_image(frames, size=32): """把每帧 reshape 成 size×size 的二维图,并做 z-score 归一化""" n = frames.shape[0] imgs = frames.reshape(n, size, size) # 按样本做 z-score,避免工况差异被全局归一化抹掉 scaler = StandardScaler() imgs = scaler.fit_transform(imgs.reshape(n, -1)).reshape(n, size, size) return imgs # 示例:正常、内圈、外圈三类 sig_n, y_n = load_cwru('Normal_0.mat', 0) sig_i, y_i = load_cwru('IR007_0.mat', 1) sig_o, y_o = load_cwru('OR007_0.mat', 2) X = np.concatenate([ to_image(frame_signal(sig_n)), to_image(frame_signal(sig_i)), to_image(frame_signal(sig_o)) ]) y = np.concatenate([y_n[:X.shape[0]//3], y_i[:X.shape[0]//3], y_o[:X.shape[0]//3]]) print(X.shape, y.shape) # (n, 32, 32), (n,)这段代码的逻辑说明:load_cwru负责从 .mat 里提取驱动端振动信号,键名带DE_time是 CWRU 的惯例;frame_signal按 1024 点、50% 重叠切帧,重叠是为了不让故障冲击刚好落在帧边界被切碎;to_image把一维帧 reshape 成 32×32,并逐样本做 z-score。参数上,frame_len取 1024 是平衡频率分辨率和样本量,采样率 12kHz 时对应约 85ms,足够覆盖一个冲击周期;size=32是 CNN 的经典输入,再大显存吃紧,再小特征会糊。注意标签对齐时我用了切片截断,实际项目里建议先算好每类帧数再拼接,避免标签错位。
2.3 训练集/验证集划分的坑:按帧随机切会泄漏
很多人直接train_test_split随机切帧,结果验证准确率 99%,上设备一测就崩。原因是同一段信号切出的相邻帧高度相似,随机切会让训练集和验证集共享几乎相同的帧,等于变相泄漏。正确做法是按「时间段」或「文件」划分:前 70% 时间的帧做训练,后 30% 做验证;或者不同负载文件之间交叉验证。CWRU 有 0/1/2/3 hp 四种负载,我一般用 0/1/2 hp 训练,3 hp 测试,这样得到的准确率才敢信。
3. CNN 特征提取器怎么搭:别堆层,要控感受野
3.1 一维卷积还是二维卷积
轴承信号本质是一维时序,但很多人把它转成二维图再用二维卷积。两种做法我都试过:一维卷积参数量小、训练快,适合样本量几千条以内;二维卷积能借用 ImageNet 预训练权重,但轴承图是灰度纹理,预训练收益有限。我的血泪经验是,样本少于 5000 条时优先一维卷积,别为了「看起来像图像任务」硬转二维。下面给一维卷积的搭建方式,二维版本把Conv1d换Conv2d、BatchNorm1d换BatchNorm2d即可。
3.2 一个够用的 CNN 特征提取网络
import torch import torch.nn as nn class CNNFeature(nn.Module): def __init__(self, in_len=1024, feat_dim=64): super().__init__() self.conv = nn.Sequential( # 第一层:大核抓冲击,感受野要覆盖一个冲击周期 nn.Conv1d(1, 16, kernel_size=31, stride=2, padding=15), nn.BatchNorm1d(16), nn.ReLU(), nn.MaxPool1d(2), # 第二层:中核抓调制 nn.Conv1d(16, 32, kernel_size=15, stride=1, padding=7), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2), # 第三层:小核抓细节 nn.Conv1d(32, 64, kernel_size=7, stride=1, padding=3), nn.BatchNorm1d(64), nn.ReLU(), nn.AdaptiveAvgPool1d(1) # 全局平均池化,输出 64 维 ) self.fc = nn.Linear(64, feat_dim) def forward(self, x): # x: (batch, 1, 1024) h = self.conv(x).squeeze(-1) # (batch, 64) return self.fc(h) # (batch, feat_dim)逻辑说明:三层卷积的感受野分别是 31、15、7,对应冲击周期、调制边带、高频细节三个尺度。第一层 stride=2 是为了快速降采样,减少后续计算量;每层后接 BatchNorm 和 ReLU 是标配,BatchNorm 在振动信号上尤其重要,因为不同负载下幅值差异大。最后用AdaptiveAvgPool1d(1)把时间维压成 1,输出 64 维特征,再经全连接降到feat_dim。参数上,feat_dim取 64 是经验值,太小欠拟合,太大 SVM 训练变慢;kernel_size=31对应 12kHz 下约 2.6ms,刚好覆盖一个轴承冲击的衰减段。注意别加太多层,三层足够,再深在小样本上必过拟合。
3.3 特征提取器怎么训练:用分类头预训练,再拆掉
CNN 不能随机初始化就直接提特征,那样提出来的是噪声。常见做法是在 CNN 后面接一个全连接分类头,用交叉熵先训练到收敛,然后把分类头拆掉,用倒数第二层的输出作为 SVM 的输入特征。训练时学习率设 1e-3,Adam 优化器,batch size 64,epoch 30 左右。如果验证准确率震荡,把学习率降到 1e-4 再跑 10 个 epoch。训练完后,把训练集和验证集的所有样本过一遍 CNN,保存特征向量和标签,供 SVM 使用。
# 预训练 CNN 分类头 class CNNClassifier(nn.Module): def __init__(self, feat_dim=64, n_class=3): super().__init__() self.backbone = CNNFeature(feat_dim=feat_dim) self.head = nn.Linear(feat_dim, n_class) def forward(self, x): return self.head(self.backbone(x)) # 训练循环略,关键:保存 backbone 的输出作为特征 model = CNNClassifier() # ... 训练 ... model.eval() with torch.no_grad(): feats_train = model.backbone(torch.tensor(X_train, dtype=torch.float32).unsqueeze(1)).numpy() feats_val = model.backbone(torch.tensor(X_val, dtype=torch.float32).unsqueeze(1)).numpy()注意unsqueeze(1)是把 (batch, 1024) 变成 (batch, 1, 1024),因为 Conv1d 要求通道维。特征提取时一定要model.eval()且torch.no_grad(),否则 BatchNorm 会更新统计量,特征不稳定。
4. SVM 接在 CNN 后面:核函数、参数与训练细节
4.1 为什么用 SVM 而不是直接 softmax
CNN 分类头用 softmax 输出概率,在样本充足时没问题,但轴承故障样本往往每类只有几百条,softmax 容易过拟合。SVM 在小样本高维特征上找最大间隔超平面,泛化能力更强,而且支持向量天然只由少数关键样本决定,对噪声鲁棒。另一个好处是可解释性:SVM 的支持向量可以回溯到原始信号,看看哪些帧被选为关键样本,这对故障诊断的机理分析有帮助。常见做法是 CNN 特征 + RBF 核 SVM,如果特征维度高且样本多,线性核更快。
4.2 SVM 训练与参数搜索
from sklearn.svm import SVC from sklearn.model_selection import GridSearchCV from sklearn.metrics import classification_report # feats_train, feats_val 来自上一步 param_grid = { 'C': [0.1, 1, 10, 100], 'gamma': ['scale', 0.01, 0.001, 0.0001], 'kernel': ['rbf'] } svm = SVC(probability=True) grid = GridSearchCV(svm, param_grid, cv=5, scoring='accuracy', n_jobs=-1) grid.fit(feats_train, y_train) print('最佳参数:', grid.best_params_) y_pred = grid.best_estimator_.predict(feats_val) print(classification_report(y_val, y_pred))逻辑说明:C控制惩罚力度,越大越容易过拟合,越小越容易欠拟合;gamma控制 RBF 核的作用范围,越大越容易过拟合。GridSearchCV用 5 折交叉验证在训练特征上搜参,注意这里的 cv 是在特征层面做的,不是原始信号层面,所以不会泄漏。参数搜索范围我一般从C=0.1~100、gamma=1e-4~scale扫一遍,先粗扫再细扫。如果最佳C落在边界,把范围往外扩再搜一次。probability=True会启用概率输出,但训练会慢一些,如果只要类别标签可以关掉。
4.3 特征维度与 SVM 核函数的匹配
CNN 输出的feat_dim如果是 64,样本量 3000,特征维度远小于样本量,RBF 核合适。如果feat_dim加到 256 而样本只有 500,RBF 核会过拟合,这时改用线性核或先做 PCA 降维。我一般会画一张「特征维度 vs 验证准确率」的曲线,找到拐点再定feat_dim。另外,SVM 对特征尺度敏感,CNN 输出的特征最好再做一次标准化,用StandardScaler在训练特征上 fit,再 transform 验证特征。
5. 避坑与排查:cnn-svm 轴承故障诊断的 5 个翻车现场
5.1 验证准确率虚高,上设备就崩
现象:验证集准确率 99%,换一台电机或换负载后掉到 60%。原因:按帧随机划分导致数据泄漏,或者训练集和验证集来自同一段信号。解决:按时间段或文件划分,用不同负载做交叉验证,确保验证集和训练集在时间上不重叠。我一般会留一个完全没见过的负载做最终测试,这个数字才写进报告。
5.2 CNN 特征全是零或方差极小
现象:SVM 训练报错或准确率等于随机猜。原因:CNN 预训练时学习率太大导致 ReLU 全部死亡,或者 BatchNorm 在 batch size 太小时统计量不稳。解决:把学习率降到 1e-4,batch size 至少 32,检查每层输出的均值和方差。如果某层输出全零,说明该层卷积核死了,重新初始化或换激活函数。
5.3 SVM 训练时间过长
现象:GridSearchCV 跑几个小时不出结果。原因:特征维度太高或样本量太大,RBF 核计算复杂度高。解决:先做 PCA 把特征降到 32 维以内,或者改用线性核;n_jobs=-1开满 CPU;把C和gamma的搜索范围先粗扫一遍,别一上来就细扫。
5.4 类别不平衡导致少数类全错
现象:正常样本多、故障样本少,SVM 把所有样本判成正常。原因:SVM 的惩罚项对多数类倾斜。解决:SVC(class_weight='balanced')自动按类别频率加权,或者对少数类过采样。注意过采样要在特征层面做,别在原始信号层面复制,否则又泄漏。
5.5 特征提取和 SVM 训练用了不同的标准化
现象:训练时准确率正常,推理时结果乱跳。原因:CNN 特征提取时用了StandardScaler,但 SVM 训练时又 fit 了一次,两次 scaler 参数不一致。解决:把 scaler 和 SVM 一起保存,推理时用同一个 scaler。我一般用sklearn.pipeline.make_pipeline把 scaler 和 SVM 串起来,避免手动管理。
6. 进阶技巧:用 t-SNE 验证特征质量,再决定要不要加层
CNN 提完特征,别急着上 SVM,先画一张 t-SNE 图看看特征在低维空间里分不分得开。如果三类样本在 t-SNE 上混在一起,说明 CNN 没学好,加 SVM 也白搭;如果分得开但边界模糊,SVM 的 RBF 核能救;如果分得很开,线性核就够。这个习惯帮我省了很多调参时间。
from sklearn.manifold import TSNE import matplotlib.pyplot as plt tsne = TSNE(n_components=2, perplexity=30, random_state=42) feats_2d = tsne.fit_transform(feats_train) plt.figure(figsize=(8, 6)) for label, color in zip([0, 1, 2], ['blue', 'red', 'green']): idx = y_train == label plt.scatter(feats_2d[idx, 0], feats_2d[idx, 1], c=color, label=f'class {label}', alpha=0.6) plt.legend() plt.title('CNN features t-SNE') plt.show()perplexity取 30 是常用值,样本少时降到 10。如果 t-SNE 图上同类样本聚成一团、异类分开,说明特征质量合格。如果同类样本散成几团,可能是工况差异没被 CNN 学掉,考虑在训练时做工况对抗或加更多负载数据。
另一个技巧是「特征拼接」:把 CNN 的 64 维特征和传统时域特征(峭度、均方根、峰值因子)拼在一起,再送 SVM。传统特征对冲击敏感,CNN 特征对调制敏感,两者互补。我试过在 CWRU 上拼接后准确率提升 2~3 个百分点,代价是特征维度翻倍,SVM 训练稍慢。拼接前记得把传统特征也标准化。
最后说个习惯:每次实验都固定随机种子,把 CNN 权重、SVM 参数、scaler 一起存下来。轴承故障诊断这行,复现性比什么都重要,不然过两周自己都忘了当时怎么跑出那个数的。希望帮到你。
本文还有配套的精品资源,点击获取