ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

滚刀状态识别实战:从振动信号特征工程到CNN/SVM模型部署

滚刀状态识别实战:从振动信号特征工程到CNN/SVM模型部署 简介面向刀具磨损状态识别场景的机器学习项目资源包整合CNN、LSTM、GRU、SVM、随机森林等多种模型用于解决滚刀走刀数据下的磨损阶段分类问题。整个资源包共包含15个文件核心为8个Python脚本分别负责数据合并、特征生成、模型训练与测试等环节4个CSV文件提供铣刀1、4、6的走刀数据集另有PNG示意图与Markdown说明文档方便快速理解代码结构。压缩后仅2.54MB轻量且目录结构清晰数据划分明确铣刀1共315个样本用于训练铣刀4、6各315个样本作为测试集可直接基于源码运行减少数据整理与预处理工作量。目前已吸引276人学习适合正在从事工业故障诊断、时间序列分类课题的开发者参考。借助这套源码可深入掌握一维CNN对时间序列局部特征的捕捉能力同时对比LSTM、GRU在序列建模上的表现以及SVM、随机森林等传统模型的基准效果训练与测试脚本已按上述划分准备好便于快速复现实验、替换不同模型并在此基础上扩展自己的特征工程方案。1. 用Python做滚刀状态识别最容易被忽视的不是模型而是数据用Python做盾构/TBM滚刀状态识别大多数人一上来就选模型把CNN、LSTM、GRU、SVM、随机森林挨个试一遍结果发现测试集指标不错现场一用就失灵。问题通常不在模型而在数据传感器信号怎么切、标签怎么对齐、时频图怎么生成、不平衡样本怎么处理这些环节决定识别系统能否稳定落地。这里按一套可复用的工程流程把滚刀状态识别的数据准备、特征构造、模型参数、训练排错和部署阈值串起来适合正在做工业数据挖掘或设备健康管理的工程师参考也适合作为入门机器学习的完整实战案例。2. 滚刀状态识别的数据与特征工程从传感器信号到CNN输入模型只是流水线的后半段。滚刀状态识别通常不直接拿原始电压信号送给模型而是先完成切片、去噪、特征化和标签对齐。这一章按实际项目最常见的顺序展开把数据采集和特征构造中的关键坑位讲清楚。2.1 数据采集与状态标签对齐滚刀状态识别用的数据工业现场最常见的是振动加速度信号传感器安装在刀盘或滚刀座附近同步采集的还有推进速度、转速、推力、扭矩等工艺参数。采样频率要覆盖可能出现的故障频率一般不低于1kHz实验台条件下甚至会到10kHz以上。如果只用推力、扭矩这类工艺参数模型学到的更接近掘进工况而不是滚刀磨损所以振动信号才是识别磨损的核心来源。标签是监督学习的起点。常见做法有两种一种是在实验台上对滚刀做定时磨损测量用磨损量连续值划分状态另一种是在盾构机停机开仓时人工检查滚刀磨损等级。第二种更贴近“状态识别”的定义但检查周期长标签量少。无论哪种都要注意标签对齐传感器数据是连续流而标签对应一个时间段如果直接把整段时间的样本都标成同一状态会混入状态切换前后的过渡数据。一般建议把标签边界前后各裁掉一部分或者单独设置一个验证集排除边界样本避免模型学到“换刀前后”的时序假象。2.2 信号切片、滤波与归一化的具体做法连续信号需要切成样本。常见窗口长度为1到2秒重叠率50%。这样每个样本保留至少一个旋转周期的完整信息又不会因为窗口太短丢失低频分量。切完之后做三类处理去趋势、带通滤波、归一化。去趋势用于消除传感器零漂带通滤波抑制低频扰动和高频噪声归一化让不同掘进环境的信号尺度可比。import numpy as np from scipy import signal def preprocess_signal(raw, fs1000, lowcut10, highcut500): # 去趋势去除线性漂移 detrended signal.detrend(raw, typelinear) # 巴特沃斯带通滤波order4 b, a signal.butter(4, [lowcut, highcut], btypebandpass, fsfs) filtered signal.filtfilt(b, a, detrended) # z-score归一化消除振幅尺度差异 normalized (filtered - np.mean(filtered)) / np.std(filtered) return normalized def make_spectrogram(signal_1d, fs1000, nperseg128): # 短时傅里叶变换返回频率轴、时间轴和功率谱 f, t, Sxx signal.spectrogram( signal_1d, fsfs, npersegnperseg, noverlapnperseg // 2 ) # 对数压缩避免少量大值主导网络梯度 return f, t, 10 * np.log10(Sxx 1e-10)参数说明detrend(typelinear)去掉线性趋势项防止后续归一化被缓慢漂移带偏butter的4阶带通在1kHz采样率下常用10~500Hz低频段排除刀盘回转分量高频段滤掉电器噪声filtfilt是零相位滤波避免群延迟导致标签和信号错位。nperseg决定频率分辨率值越大频率越细但时间分辨率越低128在1kHz下约对应0.128秒窗口适合滚刀冲击类信号。2.3 时域、频域和时频图像特征给CNN和SVM喂不同输入CNN天然适合从时频图像里提取局部模式所以把一维信号转成STFT灰度图或小波时频图比直接输入一维波形更稳定。传统模型则需要一组手工特征喂给SVM和随机森林。特征类型典型特征适用模型时域RMS、峰值因子、峭度、波形因子SVM、随机森林、LSTM频域重心频率、均方频率、频带能量占比SVM、随机森林时频图像STFT灰度图、CWT尺度图CNN原始序列多时间步振动幅度LSTM、GRU常见误区是让LSTM去吃STFT图或者让CNN去吃一维波形。CNN看到的是“整张图的空间结构”LSTM看到的是“时间步之间的顺序依赖”。如果做混合模型需要保证数据量足够否则容易过拟合。工程上更稳的做法是分别建基线再决定是否融合。生成CNN输入时只需把预处理后的信号切片交给make_spectrogram保存为灰度图即可。2.4 类别不平衡与数据增强别让正常样本淹没磨损信号正常滚刀的样本远多于磨损和崩裂样本直接训练会让分类器把所有样本都判为“正常”。处理方式分两类对深度学习模型在时频图上做增强对传统模型在特征空间做重采样。时频图增强可以用时间掩码、频率掩码和随机裁剪类似语音识别的SpecAugment思路但裁剪幅度不要太大否则高频冲击部分被丢光。from imblearn.over_sampling import SMOTE from sklearn.model_selection import train_test_split # X_features 是手工特征y_labels 是状态类别 X_train, X_test, y_train, y_test train_test_split( X_features, y_labels, test_size0.2, stratifyy_labels, random_state42 ) # 只在训练集上做SMOTE避免验证集信息泄漏 smote SMOTE(k_neighbors3, random_state42) X_train_res, y_train_res smote.fit_resample(X_train, y_train)参数说明stratifyy_labels保证切分后各类别比例一致k_neighbors3是SMOTE合成样本时的近邻数设置过小容易生成噪声点过大则合成样本贴近原始点、失去多样性。注意SMOTE只适合手工特征空间不能用于一维序列或时频图否则会破坏时间连续性。3. 模型选型与核心参数CNN、LSTM、GRU、SVM、随机森林怎么调才能对比不同模型的输入和参数差异很大但对比时必须使用同一份验证集和同一组评估指标否则得到的“谁更好”不成立。这一章讲清楚每个模型在滚刀状态识别里的定位以及动手前必须确定的参数。3.1 CNN处理时频图的关键参数CNN输入形状是(height, width, 1)height对应频率轴width对应时间轴。我一般先用两个卷积块看收敛情况而不是一上来堆ResNet。卷积核用3×3池化用2×2最大值池化滤波器数量按32、64、128递增。优化器选Adam初始学习率1e-3配合学习率衰减。参数建议值说明batch_size16~64时频图占显存较多太大容易OOMfilters32 - 64 - 128逐层翻倍kernel_size3×3对振动时频图的局部频率-时间模式最稳dropout0.3~0.5放在全连接层之前optimizerAdam(lr1e-3)后期用ReduceLROnPlateau降到1e-5这里的关键是池化次数。输入图如果只有32×32池化两次就变成8×8再池化会丢失太多细节。CNN在滚刀识别里容易过拟合因为样本量通常只有几千到几万所以Dropout和早停比网络深度更重要。3.2 LSTM/GRU序列建模时间步长与门控单元选择如果使用原始一维信号LSTM输入形状是(batch, time_steps, features)。time_steps决定模型能看到多长的历史一般取采样频率的一半到一倍。例如1kHz采样1秒窗口对应1000个时间步但直接塞给LSTM会让训练很慢。工程上会先降采样到200~500Hz或者在一个时间步内放若干个采样点的统计量。参数LSTMGRUunits32~12832~128dropout0.2~0.40.2~0.4bidirectional可选可选return_sequences最后一层False同左GRU参数少一个门在中小数据集上比LSTM更稳。滚刀状态识别如果只有几万样本优先试验GRU。归一化要按整个窗口的均值和标准差做不能在时间步内部单独做否则破坏幅值变化信息。3.3 SVM和随机森林特征尺度与类别权重SVM对特征尺度极其敏感必须先用StandardScaler。RBF核是最常用选择C是误分类惩罚gamma控制单个样本的影响半径。随机森林不要求标准化但需要对特征做重要性筛选否则树的分裂会被无关特征干扰。两个模型都建议设置class_weightbalanced让模型自动提高少数类权重。模型关键参数排查方向SVMkernelrbf, C10, gammascaleC过大过拟合gamma过小欠拟合随机森林n_estimators500, min_samples_leaf2叶子节点太小容易过拟合通用class_weightbalanced解决类别不平衡实际项目中SVM在小样本特征集上往往比深度学习高因为手工特征已经压缩了信息。随机森林训练快还能输出特征重要性适合作为筛选特征的工具。3.4 统一评估流程多模型对比不能只看准确率不平衡数据下准确率没有意义要用macro F1和混淆矩阵。深度学习模型固定训练/验证/测试集切分传统模型用5折交叉验证。最后统一输出分类报告。from sklearn.metrics import classification_report, confusion_matrix from tensorflow.keras.callbacks import EarlyStopping model.compile( losssparse_categorical_crossentropy, optimizeradam, metrics[accuracy] ) early EarlyStopping( monitorval_loss, patience10, restore_best_weightsTrue ) history model.fit( X_train, y_train, validation_data(X_val, y_val), epochs50, batch_size32, callbacks[early] ) y_pred np.argmax(model.predict(X_test), axis1) print(classification_report(y_test, y_pred)) print(confusion_matrix(y_test, y_pred))参数说明EarlyStopping监控验证集loss连续10轮不改善就停止训练restore_best_weightsTrue保证结束后的权重不是最后一轮而是验证集最优的一轮。classification_report会输出每个类别的precision、recall、F1比只看accuracy可靠得多。4. 从源码到训练滚刀状态识别项目结构与实操代码项目源码通常会包含数据预处理、特征提取、模型训练三个模块。这一章给出一套能直接运行的代码骨架并结合上一章的参数说明把散落的操作连起来。4.1 项目目录与环境依赖怎么搭我习惯把数据、特征、模型、输出分开配合统一的配置文件。目录结构如下rolling_cutter_status/ ├── data/ │ ├── raw/ # 原始传感器数据 │ ├── processed/ # 切片、去噪、增强后的数据 │ └── labels.csv # 状态标签 ├── features/ │ ├── extract_features.py │ └── make_spectrograms.py ├── models/ │ ├── train_cnn.py │ ├── train_lstm_gr.py │ ├── train_svm_rf.py │ └── evaluate.py ├── configs/ │ └── params.yaml └── outputs/ ├── checkpoints/ └── reports/依赖环境建议用conda或venv隔离。常用包与用途依赖包用途numpy/scipy信号处理与数值计算pandas标签与特征表管理scikit-learnSVM、随机森林、评估指标imbalanced-learnSMOTE过采样tensorflowCNN、LSTM、GRU训练matplotlib时频图绘制与结果可视化安装时注意TensorFlow和Python版本兼容Windows上建议用WSL2或CPU版本跑小数据量实验GPU版本再放到服务器。4.2 传统机器学习模型训练代码SVM、随机森林手工特征表通常已经降到几十维先读入特征和标签再切训练测试集。SVM需要pipeline随机森林可以直接用原始特征。import pandas as pd from sklearn.svm import SVC from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline train_df pd.read_csv(features/train_features.csv) X train_df.drop(label, axis1).values y train_df[label].values # SVM尺度敏感pipeline里做标准化 svm_model make_pipeline( StandardScaler(), SVC(kernelrbf, C10, gammascale, class_weightbalanced) ) svm_model.fit(X, y) # 随机森林不要求标准化class_weight处理不平衡 rf_model RandomForestClassifier( n_estimators500, min_samples_leaf2, class_weightbalanced, n_jobs-1 ) rf_model.fit(X, y)参数说明class_weightbalanced让模型在损失函数中提高少数类权重n_jobs-1使用所有CPU核并行训练但保存的模型文件会更大。SVM的gammascale表示按特征数自动缩放避免手动调参。4.3 深度学习模型训练代码CNN、LSTM/GRUCNN读入时频谱图输入最后一维是通道数。这里以Keras为例先构建模型再结合上一章的早停策略训练。import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout # spectrograms shape: (N, height, width) X np.load(data/processed/spectrograms.npy) y np.load(data/processed/labels.npy) X X[..., np.newaxis] # 增加通道维度 num_classes len(np.unique(y)) model Sequential([ Conv2D(32, (3, 3), activationrelu, paddingsame, input_shapeX.shape[1:]), MaxPooling2D((2, 2)), Conv2D(64, (3, 3), activationrelu, paddingsame), MaxPooling2D((2, 2)), Flatten(), Dense(128, activationrelu), Dropout(0.4), Dense(num_classes, activationsoftmax) ]) model.summary()说明X[..., np.newaxis]把(N, height, width)变成(N, height, width, 1)否则Conv2D会报错。paddingsame让卷积不缩小特征图尺寸池化负责降维。全连接层输出128维加Dropout是为了抑制过拟合最后的Dense输出类别数softmax概率和为1。训练LSTM/GRU时只需把输入换成(batch, time_steps, features)模型第一层换成LSTM或GRU其余评估流程一致。4.4 训练排错过拟合、数据泄漏和标签偏移实际训练中遇到的绝大多数问题可以从损失曲线和混淆矩阵里看出来。以下是我的排查表现象可能原因对策训练loss下降验证loss上升过拟合增强数据、增加dropout、减少epoch准确率高但少数类召回低类别不平衡调整class_weight、用macro F1早停验证指标高于测试指标很多数据泄漏检查归一化和SMOTE是否只fit在训练集模型表现和标签随机打乱后差不多标签时间对齐错误重新检查标签边界裁掉过渡段数据泄漏最隐蔽。如果先对全量数据做StandardScaler再切分测试集的信息已经参与计算均值和方差测试结果会虚高。正确做法是只在训练集上计算统计量再应用到验证和测试集。标签偏移可以通过时间偏移实验验证把标签整体平移若干秒后重新训练如果模型精度变化不大说明模型更多在学工况变化而不是滚刀状态。5. 部署时的概率阈值调整滚刀状态识别落地的最后一个技巧模型训练完直接把argmax结果接到现场报警系统会很难受因为信号有波动单个样本的预测类别会来回跳导致频繁误报。更稳的做法是输出每个类别的概率然后在业务层设置“置信度阈值”和“犹豫区”。例如只有最大概率超过0.7才更新当前状态概率在0.4到0.7之间保留上一次确认状态这样现场显示是平滑的不会被单次抖动带偏。import numpy as np def commit_status(proba, last_status, high_thres0.7, low_thres0.4): confidence np.max(proba) predicted int(np.argmax(proba)) if confidence high_thres: return predicted elif confidence low_thres: return last_status else: # 犹豫区维持上一个稳定状态 return last_status代码中的阈值需要根据现场误报率调整。如果报警频繁调高high_thres如果希望更早发现磨损调低阈值。这个阈值还可以按滚刀服役时间做动态调整比如更换新刀后前50米提高阈值越接近预估寿命越敏感。另一个落地细节是模型导出和预处理参数固化。训练好的Keras模型可以先保存为H5或SavedModel再转成ONNX或TFLite格式脱离Python环境部署到C或Java服务里。转换前要确认预处理逻辑一致特别是滤波系数和归一化统计量必须和训练时完全相同否则概率分布会漂移现场效果大打折扣。model.save(models/cnn.h5) # 转换成轻量化TFLite方便边缘设备加载 converter tf.lite.TFLiteConverter.from_keras_model(model) tflite_model converter.convert() with open(models/cnn.tflite, wb) as f: f.write(tflite_model)部署时建议把lowcut、highcut、nperseg、归一化均值方差写进配置文件与模型文件一起发布。这样一旦现场出现异常可以先检查配置是否被改过而不是怀疑模型本身。滚刀状态识别最考验工程一致性数据和模型在训练时是什么样子部署时就应该原样重现真正的精度不是训练出来的是每一步都不走样地保下来的。本文还有配套的精品资源点击获取
返回列表