2026/10/3 18:07:00

Python多模型对比:盾构滚刀状态识别实战

Python多模型对比:盾构滚刀状态识别实战 简介这份资源面向机械加工与智能制造方向的本科生、研究生及算法入门者提供一套基于机器学习的滚刀状态识别完整项目可用于毕业设计、课程设计或期末大作业。项目以Python实现覆盖CNN、LSTM、GRU、SVM、随机森林等多种模型帮助读者对比深度学习与经典算法在刀具状态识别任务上的表现差异。压缩包共15个文件约2.63MB包含8个py源码文件、4个csv数据集、1个png结果图、1个md说明文档及gitignore配置源码按数据合并、特征生成、模型训练与测试等环节拆分结构清晰便于逐模块阅读与二次修改。目前已有233人学习下载。读者可直接获得可运行的项目代码与配套数据快速完成数据预处理、特征提取、模型搭建与评估全流程并参考README说明完成环境部署适合作为入门机器学习与工业信号分析的实践案例。1. 从振动信号到刀具健康度滚刀状态识别到底在识别什么盾构机在复合地层里掘进时滚刀是直接接触岩面的那批零件它一旦偏磨、崩刃或者卡死整条掘进循环的效率会立刻掉下来。现场最常见的诉求不是预测还剩多少寿命而是现在这一刀盘上的滚刀到底处于正常、磨损还是异常状态。这个标题讲的就是用 Python 把这件事做成一个可复现的机器学习分类任务采集滚刀工作时的振动、电流、转速等信号做特征工程再分别用 CNN、LSTM、GRU、SVM、随机森林去建模比较谁在滚刀状态识别上更稳。它适合两类人一类是手里已经有台车或试验台数据、想快速跑通一套基线的人另一类是想拿一个真实工况的多模型对比项目练手的人。滚刀状态识别本质上是一个多传感器时间序列分类问题难点不在模型多花哨而在标签怎么定、窗口怎么切、特征怎么对齐。下面我按自己搭这套流程的顺序把选型理由、代码、参数和踩过的坑一次讲清。2. 数据准备与标签体系滚刀状态识别的地基怎么打2.1 先想清楚标签从哪来滚刀状态识别最容易翻车的地方不是模型是标签。现场能拿到的原始记录通常是某段时间内某把刀被换下但换刀时刻和真实失效时刻之间往往差几十分钟甚至几个班。我一般用三种方式交叉定标签一是换刀记录里的刀具编号和磨损量二是掘进参数推力、扭矩、贯入度的突变点三是停机检修时的照片或测量值。三者对齐后把每把刀的状态归成三类正常、磨损、异常崩刃/卡死/偏磨。如果只有试验台数据标签会干净很多直接按加载工况分。但要注意试验台的转速和载荷分布跟现场差得远模型迁移过去会掉点这点后面避坑章会细说。2.2 采样、切窗与对齐振动信号采样率常见 5kHz 到 20kHz电流和转速一般 1kHz 以下。多源信号频率不一致必须先重采样到统一时间轴再切窗。窗口长度我一般取 1024 或 2048 点重叠 50%这样既能覆盖一个完整的刀具啮合周期又不至于样本太少。import numpy as np import pandas as pd from scipy.signal import resample def align_and_window(vib, cur, rpm, fs_vib10000, fs_low1000, win2048, overlap0.5): # 把低频信号重采样到振动同一时间轴 n len(vib) cur_up resample(cur, n) rpm_up resample(rpm, n) step int(win * (1 - overlap)) windows [] for start in range(0, n - win 1, step): seg_v vib[start:start win] seg_c cur_up[start:start win] seg_r rpm_up[start:start win] # 三通道堆叠成 (3, win) windows.append(np.vstack([seg_v, seg_c, seg_r])) return np.array(windows, dtypenp.float32)这段代码的关键点是resample把电流和转速拉到振动的时间分辨率保证同一窗口内三路信号是同一时刻的。win2048对应 10kHz 采样约 0.2 秒overlap0.5让相邻窗口共享一半数据样本量翻倍但要注意后续划分数据集时按时间段切不能随机打乱否则同一段信号会同时进训练和测试指标虚高。2.3 特征工程时域、频域、时频域各取什么深度学习模型可以直接吃原始波形但 SVM 和随机森林必须吃特征。为了公平对比我一般先做一套统一特征再让 CNN/LSTM/GRU 用原始窗口。时域取均方根、峭度、峰值因子、裕度因子频域取 FFT 后各频带能量占比时频域用 5 层小波包分解的能量熵。特征类型具体特征维度适用模型时域RMS、峭度、峰值因子、裕度因子4SVM、RF频域8 个频带能量占比8SVM、RF时频域小波包 5 层能量熵32SVM、RF原始波形三通道窗口3×2048CNN、LSTM、GRU峭度对冲击类异常特别敏感滚刀崩刃时峭度会明显抬升RMS 对整体磨损更敏感。这两类特征配合使用SVM 和随机森林的区分度就够用了。3. 五个模型怎么落地从 CNN 到随机森林的代码与参数3.1 CNN把振动窗口当图像处理CNN 在滚刀状态识别里的思路是把 3×2048 的窗口当成一张图用卷积核去抓局部冲击模式。我一般用三层一维卷积因为信号是时序的一维卷积比二维更省参数也更贴合物理意义。import torch import torch.nn as nn class CNN1D(nn.Module): def __init__(self, n_class3): super().__init__() self.net nn.Sequential( nn.Conv1d(3, 32, kernel_size7, padding3), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(32, 64, kernel_size5, padding2), nn.BatchNorm1d(64), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(64, 128, kernel_size3, padding1), nn.BatchNorm1d(128), nn.ReLU(), nn.AdaptiveAvgPool1d(1) ) self.fc nn.Linear(128, n_class) def forward(self, x): # x: (batch, 3, 2048) return self.fc(self.net(x).squeeze(-1))kernel_size7对应第一层感受野约 0.7ms能覆盖单次冲击AdaptiveAvgPool1d(1)把时间维压掉避免全连接层参数爆炸。训练时学习率 1e-3batch 64Adam 优化器早停 patience 设 10。CNN 的优点是训练快、对局部冲击敏感缺点是窗口一长就抓不住长程依赖滚刀从正常到磨损的渐变过程它看不全。3.2 LSTM 与 GRU抓滚刀状态的时序演化滚刀磨损是渐变过程单窗口看不出趋势需要把多个窗口串成序列。我一般把连续 20 个窗口作为一个序列样本每个窗口先过一个共享的 CNN 提特征再送进 LSTM 或 GRU。class CNNLSTM(nn.Module): def __init__(self, n_class3, hidden64, layers2): super().__init__() self.cnn nn.Sequential( nn.Conv1d(3, 32, 7, padding3), nn.ReLU(), nn.MaxPool1d(4), nn.Conv1d(32, 64, 5, padding2), nn.ReLU(), nn.MaxPool1d(4) ) self.lstm nn.LSTM(64, hidden, layers, batch_firstTrue, bidirectionalTrue, dropout0.3) self.fc nn.Linear(hidden * 2, n_class) def forward(self, x): # x: (batch, seq20, 3, 2048) b, s, c, w x.shape x x.view(b * s, c, w) feat self.cnn(x).mean(-1) # (b*s, 64) feat feat.view(b, s, -1) out, _ self.lstm(feat) return self.fc(out[:, -1, :])GRU 把nn.LSTM换成nn.GRU即可参数量少约 25%训练更快。双向 LSTM 能同时看前后文但滚刀状态识别是因果任务实际部署时未来窗口拿不到所以我更推荐单向。dropout0.3是防过拟合的关键序列样本少的时候可以提到 0.5。3.3 SVM 与随机森林小样本下的稳妥选择现场数据往往只有几百到几千个带标签窗口这时候 SVM 和随机森林反而比深度学习稳。SVM 用 RBF 核C和gamma用网格搜索定随机森林树数 200 到 500max_depth控制在 10 到 15 防过拟合。from sklearn.svm import SVC from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline from sklearn.model_selection import GridSearchCV svm_pipe Pipeline([ (scaler, StandardScaler()), (svm, SVC(kernelrbf, probabilityTrue)) ]) svm_param {svm__C: [1, 10, 100], svm__gamma: [scale, 0.01, 0.1]} svm_gs GridSearchCV(svm_pipe, svm_param, cv5, scoringf1_macro) rf RandomForestClassifier(n_estimators300, max_depth12, class_weightbalanced, n_jobs-1)SVM 对特征尺度敏感StandardScaler不能省。随机森林的class_weightbalanced在异常样本少的时候很重要否则模型会偏向多数类。这两个模型训练只要几分钟适合做基线也适合在数据量不足时先跑通流程。4. 避坑与排查滚刀状态识别里最容易翻车的五件事4.1 随机切分导致指标虚高现象测试集准确率 98%一上现场就掉到 60%。原因是切窗时用了随机划分同一段连续信号被分到训练和测试两边模型其实在背答案。解决按时间段或按刀具编号划分数据集训练集和测试集在时间上不重叠。4.2 类别不平衡被忽略现象异常类召回率极低模型几乎全预测成正常。原因是正常样本远多于异常样本。解决用class_weightbalanced、过采样或者 focal loss评估指标从准确率换成 macro-F1 和异常类召回率。4.3 重采样引入虚假频率现象电流信号重采样到 10kHz 后频谱里出现一堆高频噪声。原因是低采样率信号上采样只是插值不会带来新信息反而放大噪声。解决要么把振动降采样到低频要么对低频信号单独提特征再和振动特征拼接不要强行拉到同一采样率。4.4 归一化用了全局统计量现象离线训练很好在线推理时第一批数据就崩。原因是归一化用了包含测试集的全局均值方差在线时拿不到。解决归一化参数只在训练集上算保存下来推理时直接加载。4.5 序列样本跨了换刀点现象LSTM 在换刀前后误判率特别高。原因是序列窗口跨越了换刀时刻前后其实是两把刀的状态。解决切序列时以换刀点为边界不跨刀切窗。5. 让模型真正可用的两个进阶技巧第一个技巧是用滑动投票代替单次预测。现场部署时单窗口预测会抖我一般让模型对最近 10 个窗口输出概率取平均后再判类状态切换的误报能降一半以上。第二个技巧是留一个未知类。滚刀状态识别最怕的是遇到训练集里没见过的失效模式硬分到某一类反而误导检修。我的做法是在 SVM 里用概率阈值最大概率低于 0.6 就输出待人工确认在深度学习里加一个基于能量距离的 OOD 检测头。def sliding_vote(model, seq_windows, n_vote10): # seq_windows: 最近 n_vote 个窗口 model.eval() with torch.no_grad(): logits model(seq_windows) prob torch.softmax(logits, dim-1).mean(0) if prob.max() 0.6: return 待人工确认 return prob.argmax().item()验证方法上我习惯留一台设备的全部数据做跨设备测试而不是只做同设备交叉验证。同设备指标再高跨设备掉 20 个点都是常事这个数字才是能不能上现场的真实门槛。参数上投票窗口数n_vote取 8 到 15 之间太少压不住抖动太多响应变慢概率阈值 0.6 是我在几个项目里试出来的经验值样本少时可以降到 0.5。这套流程我从数据对齐一路搭到滑动投票最大的教训是模型选型从来不是瓶颈标签质量和数据划分方式才是决定这套滚刀状态识别能不能落地的关键。先把标签对齐、按时间切分做扎实再谈 CNN 还是 LSTM顺序反了就是白干。希望帮到你。本文还有配套的精品资源点击获取