ARTICLE DETAIL

资讯详情

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

盾构机滚刀状态识别:Python机器学习CNN/LSTM/GRU/SVM/随机森林实战

盾构机滚刀状态识别:Python机器学习CNN/LSTM/GRU/SVM/随机森林实战 简介这份资源面向机械加工与智能制造方向的本科生、研究生及算法初学者提供一套基于机器学习的滚刀状态识别完整项目可用于毕业设计、期末大作业或课程设计。项目以Python实现涵盖CNN、LSTM、GRU、SVM、随机森林等多种模型帮助读者对比不同算法在刀具状态识别任务上的表现理解特征提取、数据预处理与模型训练评估的完整流程。压缩包共15个文件包含8个py源码、4个csv数据集、1个png结果图、1个md说明文档及gitignore配置整体约2.63MB源码与数据分离结构清晰便于直接运行与二次修改。目前已有233人学习下载。读者可获得可复现的模型代码、真实滚刀状态数据集、训练测试脚本及项目说明既能快速完成课题也能借此掌握机器学习分类任务的通用实现思路。1. 从一堆振动信号到滚刀状态这套源码到底能跑出什么结果盾构机在掘进时滚刀是不是磨损、是不是偏磨、是不是卡死现场往往靠人听、靠经验判断等发现异常停机换刀工期和成本都已经付出去了。这套 Python 基于机器学习的滚刀状态识别项目干的就是把振动或切削信号采集下来用 CNN、LSTM、GRU、SVM、随机森林这几类模型去判断滚刀当前处于哪种状态。它适合做毕业设计、课程大作业也适合刚接触机器学习、想找一个完整闭环项目练手的人。项目里带了data.csv、data_c1.csv、data_c4.csv、data_c6.csv这些数据文件还有merge_data.py、gen_feature.py、cnn.py、lstm.py、gru.py等脚本从数据合并、特征生成到模型训练和测试链路是完整的。你下载下来配好 Python 环境按顺序跑脚本就能看到不同模型在滚刀状态识别上的表现差异。2. 数据管线拆解merge_data.py 与 gen_feature.py 怎么把原始信号变成模型输入2.1 先看清数据文件的角色分工拿到压缩包别急着跑模型。先看数据文件data.csv通常是汇总后的主表data_c1.csv、data_c4.csv、data_c6.csv更像是按不同工况或不同采集批次拆出来的原始记录。merge_data.py的作用就是把这些分散的 CSV 合并成一份统一的数据集方便后续做特征和切窗。gen_feature.py则是把时序信号转成模型能吃的特征矩阵这一步决定了后面 CNN、LSTM 这些模型的上限。常见做法是先确认每个 CSV 的列名是否一致时间戳、通道号、标签列有没有缺失。如果列名不统一合并时会直接报 KeyError这是新手最容易翻车的地方。2.2 合并脚本的执行逻辑与参数检查merge_data.py一般会做三件事读取指定目录下的多个 CSV、按行拼接、输出一个合并后的文件。下面是我按这个项目结构还原出来的典型写法你可以对照源码看差异import pandas as pd import os # 数据目录按实际路径改 data_dir ./data # 要合并的文件列表项目里是 c1、c4、c6 这几份 file_list [data_c1.csv, data_c4.csv, data_c6.csv] df_list [] for f in file_list: path os.path.join(data_dir, f) # 统一按字符串读避免时间戳被自动解析成不同格式 df pd.read_csv(path, dtypestr) # 打上来源标记后面排查问题时能追溯 df[source_file] f df_list.append(df) # 按行合并ignore_index 重置索引 merged pd.concat(df_list, ignore_indexTrue) # 输出到主数据文件 merged.to_csv(data.csv, indexFalse) print(merged shape:, merged.shape)逻辑说明pd.read_csv里用dtypestr是为了防止不同文件里同一列被推断成不同类型比如有的文件里是1有的文件里是1.0合并后会出现隐式类型冲突。source_file这一列不是模型特征但排错时非常有用能快速定位某条异常样本来自哪个原始文件。参数上ignore_indexTrue保证合并后索引连续不保留原文件索引避免后续按索引切片时出现重复。2.3 特征生成从时序到样本矩阵gen_feature.py是这个项目里最值得细看的一环。滚刀状态识别的输入通常是振动信号或切削力信号原始数据是一长串时序点不能直接丢给 SVM 或随机森林。常见做法是滑窗切分每个窗口算一组统计特征比如均值、方差、峰值、峭度、均方根再拼成特征向量。import numpy as np import pandas as pd # 假设合并后的数据里signal 列是振动幅值label 列是状态标签 df pd.read_csv(data.csv) window_size 256 # 窗口长度按采样率调整 step 128 # 滑动步长通常取窗口一半 features [] labels [] for start in range(0, len(df) - window_size, step): window df[signal].iloc[start:start window_size].values.astype(float) label df[label].iloc[start window_size - 1] # 用窗口末尾标签 feat { mean: np.mean(window), std: np.std(window), rms: np.sqrt(np.mean(window ** 2)), peak: np.max(np.abs(window)), kurtosis: pd.Series(window).kurt(), } features.append(feat) labels.append(label) feat_df pd.DataFrame(features) feat_df[label] labels feat_df.to_csv(feature.csv, indexFalse) print(feature shape:, feat_df.shape)逻辑说明窗口长度window_size和步长step是两个关键参数。窗口太短统计量不稳定窗口太长样本数不够模型容易过拟合。步长取窗口一半是常见折中既能增加样本量又保留一定重叠。标签取窗口末尾是因为滚刀状态在时间上是渐变的用末尾标签更接近当前时刻的真实状态。如果你发现特征文件里样本数远少于预期先检查window_size是不是设得太大。提示gen_feature.py里如果用了pd.Series(window).kurt()注意 pandas 版本差异老版本对常量序列会返回 NaN最好加一个判断。3. 五类模型怎么选、怎么跑CNN、LSTM、GRU、SVM、随机森林的代码入口3.1 CNN 与 LSTM/GRU 的输入形状差异这个项目同时放了cnn.py、lstm.py、gru.py说明作者是想对比不同网络结构在滚刀状态识别上的效果。CNN 处理的是二维输入通常是(样本数, 时间步, 通道数)一维卷积在时间轴上滑动提取局部模式。LSTM 和 GRU 处理的是序列输入形状是(样本数, 时间步, 特征数)靠门控机制记住长期依赖。很多人直接把特征 CSV 丢给 CNN结果报维度错误就是因为 CNN 期望的是原始时序窗口而不是统计特征。如果你只有统计特征用 SVM 或随机森林更合适如果你想跑 CNN、LSTM得回到gen_feature.py里把原始窗口也保存下来。import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense # 假设 X_train 形状为 (样本数, 256, 1)y_train 是 one-hot 标签 model Sequential([ Conv1D(32, kernel_size5, activationrelu, input_shape(256, 1)), MaxPooling1D(pool_size2), Conv1D(64, kernel_size3, activationrelu), MaxPooling1D(pool_size2), Flatten(), Dense(64, activationrelu), Dense(num_classes, activationsoftmax), ]) model.compile(optimizeradam, losscategorical_crossentropy, metrics[accuracy]) model.fit(X_train, y_train, epochs30, batch_size32, validation_split0.2)逻辑说明Conv1D的kernel_size决定在时间轴上一次看多长的局部模式5 和 3 是常见组合。MaxPooling1D降采样减少参数量。Flatten把卷积输出拉平后接全连接层做分类。epochs和batch_size需要根据你的样本量调样本少的时候epochs设太大训练集准确率会飙到很高但验证集不动这就是过拟合。3.2 LSTM 与 GRU 的取舍lstm.py和gru.py结构相近区别在门控单元。LSTM 有三个门参数量大适合长序列GRU 只有两个门训练更快在小样本上往往表现不差。滚刀状态识别的序列长度通常不会特别长GRU 经常能拿到和 LSTM 接近的效果但训练时间更短。from tensorflow.keras.layers import LSTM, GRU, Dense def build_lstm(input_shape, num_classes): model Sequential([ LSTM(64, return_sequencesTrue, input_shapeinput_shape), LSTM(32), Dense(num_classes, activationsoftmax), ]) model.compile(optimizeradam, losscategorical_crossentropy, metrics[accuracy]) return model def build_gru(input_shape, num_classes): model Sequential([ GRU(64, return_sequencesTrue, input_shapeinput_shape), GRU(32), Dense(num_classes, activationsoftmax), ]) model.compile(optimizeradam, losscategorical_crossentropy, metrics[accuracy]) return model逻辑说明第一层return_sequencesTrue是为了把序列传给下一层第二层不再返回序列直接输出最后一个时间步的隐状态。input_shape要和你的窗口长度、特征数对齐。如果你发现 LSTM 训练特别慢先把units从 64 降到 32 试试滚刀状态识别不一定需要很大的隐层。3.3 SVM 与随机森林小样本下的稳妥选择Ext.py里大概率放了 SVM 和随机森林的对比代码。这两个模型对特征工程依赖更强但训练快、可解释性好适合在特征 CSV 上先跑一版基线。from sklearn.svm import SVC from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report import pandas as pd df pd.read_csv(feature.csv) X df.drop(columns[label]) y df[label] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) svm SVC(kernelrbf, C1.0, gammascale) svm.fit(X_train, y_train) print(SVM:) print(classification_report(y_test, svm.predict(X_test))) rf RandomForestClassifier(n_estimators200, random_state42) rf.fit(X_train, y_train) print(RF:) print(classification_report(y_test, rf.predict(X_test)))逻辑说明stratifyy保证训练集和测试集里各类别比例一致滚刀状态如果有类别不平衡这一步很关键。SVM 的C控制惩罚力度gamma控制核函数影响范围先用默认值跑通再调。随机森林的n_estimators设 200 通常够用再往上收益递减。classification_report能直接看到每个类别的 precision、recall、f1比只看准确率有用得多。4. 避坑与排查跑这套滚刀状态识别源码时最容易翻车的五个地方4.1 现象合并数据后样本数对不上标签列全是 NaN原因不同 CSV 的列名不一致或者标签列在某些文件里叫state在另一些里叫label。pd.concat按列名对齐对不上的列会填 NaN。解决合并前先打印每个文件的columns统一列名后再 concat。可以在merge_data.py里加一段assert set(df.columns) set(df_list[0].columns)做校验。4.2 现象CNN 训练时 loss 一直是 nan原因输入数据没有归一化振动幅值可能很大卷积层输出爆炸。或者标签没有做 one-hotcategorical_crossentropy收到整数标签会出错。解决对输入做标准化(x - mean) / std标签用to_categorical转成 one-hot。如果 loss 还是 nan把学习率从默认的 0.001 降到 0.0001 试试。4.3 现象LSTM 验证集准确率卡在某个值不动原因窗口切分时训练集和测试集有重叠或者数据没有按时间顺序划分导致信息泄漏。也可能是序列太长LSTM 记不住。解决按时间顺序切分前 70% 做训练后 30% 做测试不要随机打乱。如果序列确实长先把窗口长度减半或者换 GRU 试试。4.4 现象SVM 跑得特别慢内存爆掉原因特征维度太高或者样本量太大。SVM 的时间复杂度介于 O(n²) 和 O(n³) 之间几万条样本就会很吃力。解决先用随机森林跑一版基线再用SelectKBest或 PCA 降维把特征数压到几十维再喂给 SVM。核函数从rbf换成linear也能快很多。4.5 现象测试脚本cnn_test.py、lstm_test.py加载模型报错原因训练时保存的模型结构和测试时加载的结构不一致或者 Keras 版本不匹配。项目里如果用的是model.save(cnn.h5)测试时要用load_model(cnn.h5)不能重新定义结构。解决确认训练和测试用的是同一个脚本里的模型定义或者把模型结构单独抽成一个函数两边都调用它。Keras 版本差异大的话建议在虚拟环境里固定版本比如tensorflow2.10。5. 把模型跑稳之后交叉验证、混淆矩阵与一个我常用的验证习惯5.1 用交叉验证代替单次划分单次train_test_split的结果波动很大尤其是滚刀状态样本不多的时候。我一般会补一个 K 折交叉验证看模型在不同划分下的稳定性。from sklearn.model_selection import cross_val_score from sklearn.ensemble import RandomForestClassifier import pandas as pd df pd.read_csv(feature.csv) X df.drop(columns[label]) y df[label] rf RandomForestClassifier(n_estimators200, random_state42) scores cross_val_score(rf, X, y, cv5, scoringf1_macro) print(f1_macro per fold:, scores) print(mean f1_macro:, scores.mean())逻辑说明cv5表示五折scoringf1_macro对类别不平衡更敏感。如果五折的 f1 波动超过 0.1说明模型不稳定要么样本太少要么特征区分度不够。这时候别急着调参先回去看gen_feature.py里的窗口和特征选得对不对。5.2 混淆矩阵比准确率更能说明问题滚刀状态识别里把“正常”误判成“磨损”和把“磨损”误判成“正常”代价完全不同。混淆矩阵能直接看到哪一类容易被混淆。from sklearn.metrics import confusion_matrix import seaborn as sns import matplotlib.pyplot as plt y_pred rf.predict(X) cm confusion_matrix(y, y_pred) sns.heatmap(cm, annotTrue, fmtd, cmapBlues) plt.xlabel(Predicted) plt.ylabel(True) plt.show()逻辑说明如果某一类的召回率明显低说明模型漏检多可能需要给这一类加样本或者调整分类阈值。热力图上对角线越深越好非对角线上的数字就是误判。5.3 我自己的验证习惯每次跑完一个新模型我不会只看它输出的准确率。我会把cnn_test.py和lstm_test.py里的预测结果导出来和原始标签按时间对齐画一条对比曲线。如果模型在状态切换点附近总是滞后说明窗口切分时标签对齐有问题得回去改gen_feature.py里的标签取值方式。这个习惯帮我省了很多次“以为模型很好、实际一上现场就翻车”的后悔药。从那以后我每次拿到新的时序数据项目都强制先跑一遍标签对齐检查再谈模型选型。希望帮到你。本文还有配套的精品资源点击获取
返回列表