齿轮故障诊断端到端实践:从振动信号到可解释模型
发布时间:2026/10/1 11:25:27来源:尧图网络
简介本资源是一套完整的齿轮故障诊断课程设计与毕业设计实践方案面向自动化、机械工程及人工智能方向的本科生与研究生聚焦工业设备状态监测中的典型故障识别问题。项目基于Python实现整合数据预处理、特征提取、Adaboost与Logistic回归两种主流分类模型训练与测试全流程配套真实齿轮故障测试数据CSV格式及特征说明文档TXT源码结构清晰、注释完整便于理解算法原理与工程落地逻辑。压缩包共7个文件含3个核心Python脚本数据处理、双模型训练与预测、2个CSV测试/训练数据集、2个TXT特征说明文档整体仅38KB轻量易部署。目前已有174人学习下载读者可直接运行复现诊断流程获取可扩展的故障分类基线代码、标准化数据处理范式及模型对比分析思路为后续引入深度学习或嵌入式部署提供扎实基础。1. 齿轮故障诊断不是调包跑个准确率它是一套从振动信号到可解释决策的完整闭环专为课程设计和毕业答辩卡点而生你手头那份“齿轮故障诊断.zip”不是网上随手搜到的 demo 代码合集——它是用真实齿轮箱振动数据含正常、断齿、磨损、点蚀四类工况驱动的端到端诊断流程核心逻辑藏在数据处理.py里先对原始时域信号做包络谱分析提取幅值谱特征再用滑动窗FFT生成频域能量矩阵最后用统计量峭度、裕度、波形因子等压缩成 24 维特征向量。整个 pipeline 不依赖 librosa 或 pyts 这类黑匣子库所有信号处理步骤都手动实现连 FFT 的窗函数选 Hanning 还是 Hamming 都有注释说明。Adaboost 和 Logistic 两个模型脚本不是并列选项而是刻意设计的对比实验前者用弱分类器集成提升小样本泛化能力适合你只有 300 条测试数据的现实后者用 sigmoid 输出概率值方便画 ROC 曲线——这正是答辩老师最爱问“为什么选这个模型”的底层答案。如果你正被毕设 deadline 追着跑或者课程设计只剩两周要交完整报告可运行代码答辩 PPT这份资源能直接填满“数据采集→特征工程→模型训练→结果可视化”四大模块且每个环节都有可修改的参数入口不是那种改个路径就报错的“伪开源”。2. 数据处理从 raw_vib.csv 到 24 维特征向量每一步都得亲手过一遍2.1 振动信号预处理为什么必须做去趋势高通滤波齿轮故障的早期征兆往往淹没在低频机械振动和传感器直流偏置中。数据处理.py开头的remove_trend()函数用的是最小二乘拟合直线再减去而非简单 detrend——因为齿轮箱底座振动常呈缓慢上升趋势线性拟合比 Savitzky-Golay 更稳high_pass_filter()用的是二阶巴特沃斯滤波器截止频率设为 500Hz对应齿轮啮合频率的 1/3这个值来自测试数据特征.txt里标注的轴承转速与齿数计算出的理论啮合频率1720rpm × 24齿 ÷ 60 ≈ 688Hz。代码里没写死而是通过fs10000采样率和f_nyq fs/2动态算出归一化截止频率from scipy.signal import butter, filtfilt def high_pass_filter(data, fs10000, cutoff500): nyq 0.5 * fs normal_cutoff cutoff / nyq b, a butter(2, normal_cutoff, btypehigh, analogFalse) return filtfilt(b, a, data)提示filtfilt是关键——它做零相位滤波避免传统lfilter引起的相位失真这对后续包络谱分析至关重要。如果跳过这步你的峭度指标会因相位混叠而虚高导致误判。2.2 包络谱提取不是调用 hilbert() 就完事得懂 Hilbert 变换的边界条件数据处理.py中get_envelope_spectrum()函数先对滤波后信号做 Hilbert 变换但重点在后续处理它把解析信号取模得到包络再对包络做 FFT最后只取前 2048 点对应 0~5000Hz 频段并归一化。这里有个血泪经验原始信号长度若非 2 的整数次幂Hilbert 变换会因补零引入虚假谐波。所以代码里强制data np.pad(data, (0, 2**14 - len(data)), constant)补到 16384 点2^14再截取中间 8192 点做变换——这个细节决定了你能否在包络谱上清晰看到故障特征频率如断齿对应的 688Hz 及其倍频。2.3 特征工程24 维不是随便凑的每维都对应一个物理意义最终特征向量包含三类指标时域统计量8维均值、方差、标准差、峭度、偏度、峰值因子、脉冲因子、裕度因子频域能量比12维将包络谱划分为 12 个频带0-500Hz, 500-1000Hz, ..., 5500-6000Hz计算各频带能量占总能量比例故障敏感频带4维单独提取啮合频率688Hz±5%、2倍频±5%、3倍频±5%、边频带688±30Hz的能量占比。这些维度设计直指齿轮故障机理断齿主要激发啮合频率及其谐波点蚀则在边频带产生能量突增。数据特征.txt文件里明确标注了各频带中心频率和宽度不是凭空划分。2.4 特征保存与加载CSV 格式里的隐藏陷阱Adaboost_Train.csv和Adaboost_Test.csv的第一列是label0正常1断齿2磨损3点蚀但注意所有特征列名都带单位如kurtosis_g、energy_0_500Hz_%。这是为了防止你在后续建模时误把标签列当特征——基于Adaboost的齿轮故障.py里用pd.read_csv(..., index_col0)直接跳过第一行索引再用X df.iloc[:, 1:]取特征y df.iloc[:, 0]取标签。如果自己重生成 CSV务必保持列顺序一致否则模型会把“磨损”标签当成“能量比”特征喂进去准确率直接崩到 25%纯随机。3. 模型训练Adaboost 与 Logistic 的参数博弈不是调参而是理解误差来源3.1 Adaboost弱分类器选 DecisionTreeClassifier(max_depth1) 的物理依据基于Adaboost的齿轮故障.py中AdaBoostClassifier(base_estimatorDecisionTreeClassifier(max_depth1), n_estimators50)的设定不是拍脑袋max_depth1对应决策树桩stump它只能做单特征阈值分割正好匹配齿轮故障特征中“某频带能量是否超阈值”这种简单判据。而n_estimators50是通过Adaboost_Train.csv的 1200 条训练样本交叉验证确定的——少于 30 个基学习器时对点蚀类别的召回率低于 70%多于 60 个则在Adaboost_Test.csv上出现过拟合测试准确率下降 3.2%。代码里留了learning_rate1.0的注释“若样本噪声大可降至 0.75 以抑制过拟合”这是针对你实际采集数据可能含电机干扰的后悔药。3.2 Logistic 回归为什么用 OneVsRest 而不用 Softmax基于Logistic的齿轮故障.py用OneVsRestClassifier(LogisticRegression(C1.0, solverliblinear))而非multinomial原因很实在liblinear求解器在小样本2000下收敛更快且C1.0是通过网格搜索在Adaboost_Train.csv上找到的最优正则强度——C太小如 0.1会导致权重衰减过度漏检微弱故障C太大如 10则让模型对噪声敏感把正常振动误判为点蚀。更关键的是OneVsRest结构它为每个故障类型训练独立二分类器输出概率可直接解释为“该故障发生的置信度”答辩时你能指着predict_proba()结果说“系统判断点蚀概率 87%远高于其他类别符合振动频谱中边频带能量突增的物理证据”。3.3 训练流程五折交叉验证的实操细节两个脚本都内置StratifiedKFold(n_splits5, shuffleTrue, random_state42)但注意random_state42不是玄学——它确保每次运行划分一致方便你复现论文结果。Adaboost_Train.csv的标签分布是 [300,300,300,300]四类均衡所以分层抽样能保证每折都有各类样本。代码里cross_val_score()返回的是每折的准确率数组而classification_report()输出的宏平均 F1 值才是你写进毕设报告的关键指标答辩老师必问“F1 值多少”。3.4 模型持久化joblib 保存的不只是权重还有特征缩放器基于Adaboost的齿轮故障.py在训练前用StandardScaler()对特征做标准化并把 scaler 实例和训练好的模型一起用joblib.dump()保存为adaboost_model.pkl。这意味着你后续预测时必须先用同一个 scaler 对新数据做 transform再喂给模型——基于Logistic的齿轮故障.py同理。很多同学直接load_model()后就 predict结果准确率暴跌就是因为忘了这步。代码里scaler joblib.load(scaler.pkl)和model joblib.load(adaboost_model.pkl)是绑定关系拆开就失效。4. 测试与验证别只看 test_accuracy故障诊断要看混淆矩阵和 ROC 曲线4.1 测试数据结构Adaboost_Test.csv里的样本分布暗藏玄机Adaboost_Test.csv共 400 条样本但四类并非均匀分布正常 120 条、断齿 100 条、磨损 90 条、点蚀 90 条。这种设计模拟真实产线——正常状态最多故障样本稀缺。因此单纯看整体准确率如 92%会掩盖问题可能模型把所有样本都判为“正常”准确率仍有 30%。必须用confusion_matrix(y_true, y_pred)查看每类识别情况。测试数据特征.txt明确标注了各类样本编号范围如“点蚀310-400”方便你人工核对误判案例。4.2 ROC 曲线绘制Logistic 模型的专属验证武器基于Logistic的齿轮故障.py末尾有plot_roc_curve()函数它调用OneVsRestClassifier的decision_function()获取每个类别的决策分数再用roc_curve()计算 TPR/FPR。关键参数fpr, tpr, _ roc_curve(y_test i, y_score[:, i])中的y_test i生成布尔数组这才是多分类 ROC 的正确打开方式。生成的roc_auc_score(y_test, y_score, multi_classovr)宏平均 AUC 值通常 0.93~0.96比准确率更有说服力——它证明模型在不同分类阈值下都稳定优于随机猜测。4.3 特征重要性可视化Adaboost 的可解释性落地基于Adaboost的齿轮故障.py用model.estimators_[0].feature_importances_提取第一个决策树桩的重要性再对 50 个基学习器求平均。结果保存为feature_importance.png横轴是特征名如energy_688_720Hz_%纵轴是平均权重。你会发现啮合频率±5% 频带的能量占比永远排前三这直接印证了齿轮故障诊断的物理基础——特征重要性排序就是你的答辩 PPT 第三页“模型可信度论证”。4.4 预测接口封装三行代码搞定新数据诊断predict_new_data.py需自行创建示范如何调用已训练模型import numpy as np import pandas as pd from sklearn.preprocessing import StandardScaler import joblib # 1. 加载 scaler 和模型 scaler joblib.load(scaler.pkl) model joblib.load(adaboost_model.pkl) # 2. 读取新振动数据假设为 10000 点时域信号 new_signal np.loadtxt(new_vib.txt) # 你的新采集数据 # 3. 复用数据处理流程生成 24 维特征 features extract_features(new_signal) # 此函数需从数据处理.py 复制 X_new scaler.transform([features]) # 注意必须是二维数组 pred model.predict(X_new)[0] print(f预测故障类型{[正常,断齿,磨损,点蚀][pred]})注意extract_features()必须完全复用数据处理.py中的函数包括滤波参数、FFT 点数、频带划分——任何改动都会导致特征失配。5. 避坑指南那些让你在答辩前夜崩溃的 5 个真实翻车现场5.1 现象Adaboost_Test.csv加载后 shape 显示 (400, 25)但训练时报错ValueError: Found array with 0 sample(s)原因CSV 文件用 Excel 打开并另存为时Excel 会把第一列label自动转成文本格式如 “0” 变成 “0.00”导致pd.read_csv()读入后y列是 object 类型而非 int。解决用记事本或 VS Code 打开 CSV确认第一列无小数点或在代码中强制转换df[label] df[label].astype(int)。5.2 现象基于Logistic的齿轮故障.py运行到fit()时卡住超过 10 分钟CPU 占用 100%原因solverliblinear在特征维度高24维且样本少1200条时迭代收敛慢更可能是C参数过大如设为 100导致优化器在权重空间反复震荡。解决将C改为 0.5~2.0 之间或换用solversaga支持 L1/L2 混合正则小样本更快。5.3 现象包络谱图上看不到 688Hz 峰值反而在 100Hz 附近出现强峰原因high_pass_filter()的cutoff参数设错了——如果误设为 100Hz会滤掉故障特征频段或fs采样率与实际硬件不符如代码写 10000Hz但你的采集卡实际是 5000Hz。解决用scipy.signal.freqz()绘制滤波器响应曲线确认 688Hz 处增益 -1dB检查测试数据特征.txt中的sampling_rate字段严格匹配代码。5.4 现象confusion_matrix显示“点蚀”类召回率仅 45%但人工看频谱明显有边频带原因特征工程中边频带688±30Hz的频带划分错误——数据处理.py里freq_bands列表若写成(658, 718)宽 60Hz但实际应按np.arange(658, 719, 1)生成离散频率点再 sum 能量若用np.sum(spectrum[658:718])会因索引偏移漏掉部分频点。解决用np.where((freq 658) (freq 718))获取精确索引再spectrum[idx].sum()。5.5 现象joblib.load(adaboost_model.pkl)报错ModuleNotFoundError: No module named sklearn.ensemble._weight_boosting原因模型保存时用的 scikit-learn 版本如 1.2.2与当前环境版本如 1.4.0不兼容内部模块路径变更。解决统一环境版本——pip install scikit-learn1.2.2或改用pickle序列化但需确保 Python 版本一致最稳妥是重新训练并保存。6. 进阶技巧用 SHAP 解释单次预测让答辩老师当场追问“这怎么做到的”6.1 为什么 SHAP 比 feature_importance 更适合答辩场景Adaboost 的feature_importances_只告诉“全局哪个特征重要”但答辩时老师会问“这次具体预测为‘断齿’是哪几个特征起决定作用” SHAPSHapley Additive exPlanations能给出每个样本的逐特征贡献值比如energy_688_720Hz_%贡献 0.42强力支持断齿kurtosis_g贡献 0.18辅助证据energy_0_500Hz_%贡献 -0.31削弱判断这种细粒度解释配上shap.plots.waterfall()生成的瀑布图比单纯说“准确率 95%” 有力十倍。6.2 三步接入 SHAP无需改模型只要加 10 行代码在基于Adaboost的齿轮故障.py训练完成后插入import shap # 1. 创建解释器用训练集前 100 条样本作为背景数据 explainer shap.TreeExplainer(model, X_train[:100]) # 2. 计算单样本 SHAP 值以第一条测试样本为例 shap_values explainer.shap_values(X_test[0:1]) # 3. 绘制瀑布图需安装 matplotlib shap.plots.waterfall(explainer.expected_value[0], shap_values[0][0], feature_names[kurtosis_g, energy_0_500Hz_%, ...]) # 填入全部24个特征名注意shap_values[0][0]中第一个[0]是类别索引断齿类第二个[0]是样本索引。特征名列表必须与X_test列顺序严格一致。6.3 SHAP 值的物理映射把数学结果翻译成工程师语言SHAP 值不是抽象数字——它直接对应物理量级。例如energy_688_720Hz_%的 SHAP 值 0.42意味着该频带能量比正常状态高 42%这与齿轮断齿时啮合冲击加剧的机理完全吻合。我在去年指导学生答辩时把 SHAP 瀑布图和实测振动频谱图并排展示老师立刻追问“这个 -0.31 的负贡献对应频谱里哪个区域” 我指了指 0-500Hz 频段的平稳基线说“这里能量偏低说明没有其他机械松动干扰让断齿特征更纯粹。” ——这种把算法输出和物理现象挂钩的能力才是课程设计该体现的工程素养。从那以后我每次教学生做故障诊断项目都强制他们在predict_new_data.py里加 SHAP 解释模块哪怕只跑一次样本。因为答辩不是考你会不会调包而是考你敢不敢说清楚“为什么是这个结论”。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网