識別實(shí)戰(zhàn):從振動信號特征工程到CNN/SVM模型部署)
簡介面向刀具磨損狀態(tài)識別場景的機(jī)器學(xué)習(xí)項(xiàng)目資源包整合CNN、LSTM、GRU、SVM、隨機(jī)森林等多種模型用于解決滾刀走刀數(shù)據(jù)下的磨損階段分類問題。整個資源包共包含15個文件核心為8個Python腳本分別負(fù)責(zé)數(shù)據(jù)合并、特征生成、模型訓(xùn)練與測試等環(huán)節(jié)4個CSV文件提供銑刀1、4、6的走刀數(shù)據(jù)集另有PNG示意圖與Markdown說明文檔方便快速理解代碼結(jié)構(gòu)。壓縮后僅2.54MB輕量且目錄結(jié)構(gòu)清晰數(shù)據(jù)劃分明確銑刀1共315個樣本用于訓(xùn)練銑刀4、6各315個樣本作為測試集可直接基于源碼運(yùn)行減少數(shù)據(jù)整理與預(yù)處理工作量。目前已吸引276人學(xué)習(xí)適合正在從事工業(yè)故障診斷、時間序列分類課題的開發(fā)者參考。借助這套源碼可深入掌握一維CNN對時間序列局部特征的捕捉能力同時對比LSTM、GRU在序列建模上的表現(xiàn)以及SVM、隨機(jī)森林等傳統(tǒng)模型的基準(zhǔn)效果訓(xùn)練與測試腳本已按上述劃分準(zhǔn)備好便于快速復(fù)現(xiàn)實(shí)驗(yàn)、替換不同模型并在此基礎(chǔ)上擴(kuò)展自己的特征工程方案。1. 用Python做滾刀狀態(tài)識別最容易被忽視的不是模型而是數(shù)據(jù)用Python做盾構(gòu)/TBM滾刀狀態(tài)識別大多數(shù)人一上來就選模型把CNN、LSTM、GRU、SVM、隨機(jī)森林挨個試一遍結(jié)果發(fā)現(xiàn)測試集指標(biāo)不錯現(xiàn)場一用就失靈。問題通常不在模型而在數(shù)據(jù)傳感器信號怎么切、標(biāo)簽怎么對齊、時頻圖怎么生成、不平衡樣本怎么處理這些環(huán)節(jié)決定識別系統(tǒng)能否穩(wěn)定落地。這里按一套可復(fù)用的工程流程把滾刀狀態(tài)識別的數(shù)據(jù)準(zhǔn)備、特征構(gòu)造、模型參數(shù)、訓(xùn)練排錯和部署閾值串起來適合正在做工業(yè)數(shù)據(jù)挖掘或設(shè)備健康管理的工程師參考也適合作為入門機(jī)器學(xué)習(xí)的完整實(shí)戰(zhàn)案例。2. 滾刀狀態(tài)識別的數(shù)據(jù)與特征工程從傳感器信號到CNN輸入模型只是流水線的后半段。滾刀狀態(tài)識別通常不直接拿原始電壓信號送給模型而是先完成切片、去噪、特征化和標(biāo)簽對齊。這一章按實(shí)際項(xiàng)目最常見的順序展開把數(shù)據(jù)采集和特征構(gòu)造中的關(guān)鍵坑位講清楚。2.1 數(shù)據(jù)采集與狀態(tài)標(biāo)簽對齊滾刀狀態(tài)識別用的數(shù)據(jù)工業(yè)現(xiàn)場最常見的是振動加速度信號傳感器安裝在刀盤或滾刀座附近同步采集的還有推進(jìn)速度、轉(zhuǎn)速、推力、扭矩等工藝參數(shù)。采樣頻率要覆蓋可能出現(xiàn)的故障頻率一般不低于1kHz實(shí)驗(yàn)臺條件下甚至?xí)?0kHz以上。如果只用推力、扭矩這類工藝參數(shù)模型學(xué)到的更接近掘進(jìn)工況而不是滾刀磨損所以振動信號才是識別磨損的核心來源。標(biāo)簽是監(jiān)督學(xué)習(xí)的起點(diǎn)。常見做法有兩種一種是在實(shí)驗(yàn)臺上對滾刀做定時磨損測量用磨損量連續(xù)值劃分狀態(tài)另一種是在盾構(gòu)機(jī)停機(jī)開倉時人工檢查滾刀磨損等級。第二種更貼近“狀態(tài)識別”的定義但檢查周期長標(biāo)簽量少。無論哪種都要注意標(biāo)簽對齊傳感器數(shù)據(jù)是連續(xù)流而標(biāo)簽對應(yīng)一個時間段如果直接把整段時間的樣本都標(biāo)成同一狀態(tài)會混入狀態(tài)切換前后的過渡數(shù)據(jù)。一般建議把標(biāo)簽邊界前后各裁掉一部分或者單獨(dú)設(shè)置一個驗(yàn)證集排除邊界樣本避免模型學(xué)到“換刀前后”的時序假象。2.2 信號切片、濾波與歸一化的具體做法連續(xù)信號需要切成樣本。常見窗口長度為1到2秒重疊率50%。這樣每個樣本保留至少一個旋轉(zhuǎn)周期的完整信息又不會因?yàn)榇翱谔虂G失低頻分量。切完之后做三類處理去趨勢、帶通濾波、歸一化。去趨勢用于消除傳感器零漂帶通濾波抑制低頻擾動和高頻噪聲歸一化讓不同掘進(jìn)環(huán)境的信號尺度可比。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 ) # 對數(shù)壓縮避免少量大值主導(dǎo)網(wǎng)絡(luò)梯度 return f, t, 10 * np.log10(Sxx 1e-10)參數(shù)說明detrend(typelinear)去掉線性趨勢項(xiàng)防止后續(xù)歸一化被緩慢漂移帶偏butter的4階帶通在1kHz采樣率下常用10~500Hz低頻段排除刀盤回轉(zhuǎn)分量高頻段濾掉電器噪聲filtfilt是零相位濾波避免群延遲導(dǎo)致標(biāo)簽和信號錯位。nperseg決定頻率分辨率值越大頻率越細(xì)但時間分辨率越低128在1kHz下約對應(yīng)0.128秒窗口適合滾刀沖擊類信號。2.3 時域、頻域和時頻圖像特征給CNN和SVM喂不同輸入CNN天然適合從時頻圖像里提取局部模式所以把一維信號轉(zhuǎn)成STFT灰度圖或小波時頻圖比直接輸入一維波形更穩(wěn)定。傳統(tǒng)模型則需要一組手工特征喂給SVM和隨機(jī)森林。特征類型典型特征適用模型時域RMS、峰值因子、峭度、波形因子SVM、隨機(jī)森林、LSTM頻域重心頻率、均方頻率、頻帶能量占比SVM、隨機(jī)森林時頻圖像STFT灰度圖、CWT尺度圖CNN原始序列多時間步振動幅度LSTM、GRU常見誤區(qū)是讓LSTM去吃STFT圖或者讓CNN去吃一維波形。CNN看到的是“整張圖的空間結(jié)構(gòu)”LSTM看到的是“時間步之間的順序依賴”。如果做混合模型需要保證數(shù)據(jù)量足夠否則容易過擬合。工程上更穩(wěn)的做法是分別建基線再決定是否融合。生成CNN輸入時只需把預(yù)處理后的信號切片交給make_spectrogram保存為灰度圖即可。2.4 類別不平衡與數(shù)據(jù)增強(qiáng)別讓正常樣本淹沒磨損信號正常滾刀的樣本遠(yuǎn)多于磨損和崩裂樣本直接訓(xùn)練會讓分類器把所有樣本都判為“正常”。處理方式分兩類對深度學(xué)習(xí)模型在時頻圖上做增強(qiáng)對傳統(tǒng)模型在特征空間做重采樣。時頻圖增強(qiáng)可以用時間掩碼、頻率掩碼和隨機(jī)裁剪類似語音識別的SpecAugment思路但裁剪幅度不要太大否則高頻沖擊部分被丟光。from imblearn.over_sampling import SMOTE from sklearn.model_selection import train_test_split # X_features 是手工特征y_labels 是狀態(tài)類別 X_train, X_test, y_train, y_test train_test_split( X_features, y_labels, test_size0.2, stratifyy_labels, random_state42 ) # 只在訓(xùn)練集上做SMOTE避免驗(yàn)證集信息泄漏 smote SMOTE(k_neighbors3, random_state42) X_train_res, y_train_res smote.fit_resample(X_train, y_train)參數(shù)說明stratifyy_labels保證切分后各類別比例一致k_neighbors3是SMOTE合成樣本時的近鄰數(shù)設(shè)置過小容易生成噪聲點(diǎn)過大則合成樣本貼近原始點(diǎn)、失去多樣性。注意SMOTE只適合手工特征空間不能用于一維序列或時頻圖否則會破壞時間連續(xù)性。3. 模型選型與核心參數(shù)CNN、LSTM、GRU、SVM、隨機(jī)森林怎么調(diào)才能對比不同模型的輸入和參數(shù)差異很大但對比時必須使用同一份驗(yàn)證集和同一組評估指標(biāo)否則得到的“誰更好”不成立。這一章講清楚每個模型在滾刀狀態(tài)識別里的定位以及動手前必須確定的參數(shù)。3.1 CNN處理時頻圖的關(guān)鍵參數(shù)CNN輸入形狀是(height, width, 1)height對應(yīng)頻率軸width對應(yīng)時間軸。我一般先用兩個卷積塊看收斂情況而不是一上來堆ResNet。卷積核用3×3池化用2×2最大值池化濾波器數(shù)量按32、64、128遞增。優(yōu)化器選Adam初始學(xué)習(xí)率1e-3配合學(xué)習(xí)率衰減。參數(shù)建議值說明batch_size16~64時頻圖占顯存較多太大容易OOMfilters32 - 64 - 128逐層翻倍kernel_size3×3對振動時頻圖的局部頻率-時間模式最穩(wěn)dropout0.3~0.5放在全連接層之前optimizerAdam(lr1e-3)后期用ReduceLROnPlateau降到1e-5這里的關(guān)鍵是池化次數(shù)。輸入圖如果只有32×32池化兩次就變成8×8再池化會丟失太多細(xì)節(jié)。CNN在滾刀識別里容易過擬合因?yàn)闃颖玖客ǔV挥袔浊У綆兹f所以Dropout和早停比網(wǎng)絡(luò)深度更重要。3.2 LSTM/GRU序列建模時間步長與門控單元選擇如果使用原始一維信號LSTM輸入形狀是(batch, time_steps, features)。time_steps決定模型能看到多長的歷史一般取采樣頻率的一半到一倍。例如1kHz采樣1秒窗口對應(yīng)1000個時間步但直接塞給LSTM會讓訓(xùn)練很慢。工程上會先降采樣到200~500Hz或者在一個時間步內(nèi)放若干個采樣點(diǎn)的統(tǒng)計(jì)量。參數(shù)LSTMGRUunits32~12832~128dropout0.2~0.40.2~0.4bidirectional可選可選return_sequences最后一層False同左GRU參數(shù)少一個門在中小數(shù)據(jù)集上比LSTM更穩(wěn)。滾刀狀態(tài)識別如果只有幾萬樣本優(yōu)先試驗(yàn)GRU。歸一化要按整個窗口的均值和標(biāo)準(zhǔn)差做不能在時間步內(nèi)部單獨(dú)做否則破壞幅值變化信息。3.3 SVM和隨機(jī)森林特征尺度與類別權(quán)重SVM對特征尺度極其敏感必須先用StandardScaler。RBF核是最常用選擇C是誤分類懲罰gamma控制單個樣本的影響半徑。隨機(jī)森林不要求標(biāo)準(zhǔn)化但需要對特征做重要性篩選否則樹的分裂會被無關(guān)特征干擾。兩個模型都建議設(shè)置class_weightbalanced讓模型自動提高少數(shù)類權(quán)重。模型關(guān)鍵參數(shù)排查方向SVMkernelrbf, C10, gammascaleC過大過擬合gamma過小欠擬合隨機(jī)森林n_estimators500, min_samples_leaf2葉子節(jié)點(diǎn)太小容易過擬合通用class_weightbalanced解決類別不平衡實(shí)際項(xiàng)目中SVM在小樣本特征集上往往比深度學(xué)習(xí)高因?yàn)槭止ぬ卣饕呀?jīng)壓縮了信息。隨機(jī)森林訓(xùn)練快還能輸出特征重要性適合作為篩選特征的工具。3.4 統(tǒng)一評估流程多模型對比不能只看準(zhǔn)確率不平衡數(shù)據(jù)下準(zhǔn)確率沒有意義要用macro F1和混淆矩陣。深度學(xué)習(xí)模型固定訓(xùn)練/驗(yàn)證/測試集切分傳統(tǒng)模型用5折交叉驗(yàn)證。最后統(tǒng)一輸出分類報(bào)告。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))參數(shù)說明EarlyStopping監(jiān)控驗(yàn)證集loss連續(xù)10輪不改善就停止訓(xùn)練restore_best_weightsTrue保證結(jié)束后的權(quán)重不是最后一輪而是驗(yàn)證集最優(yōu)的一輪。classification_report會輸出每個類別的precision、recall、F1比只看accuracy可靠得多。4. 從源碼到訓(xùn)練滾刀狀態(tài)識別項(xiàng)目結(jié)構(gòu)與實(shí)操代碼項(xiàng)目源碼通常會包含數(shù)據(jù)預(yù)處理、特征提取、模型訓(xùn)練三個模塊。這一章給出一套能直接運(yùn)行的代碼骨架并結(jié)合上一章的參數(shù)說明把散落的操作連起來。4.1 項(xiàng)目目錄與環(huán)境依賴怎么搭我習(xí)慣把數(shù)據(jù)、特征、模型、輸出分開配合統(tǒng)一的配置文件。目錄結(jié)構(gòu)如下rolling_cutter_status/ ├── data/ │ ├── raw/ # 原始傳感器數(shù)據(jù) │ ├── processed/ # 切片、去噪、增強(qiáng)后的數(shù)據(jù) │ └── labels.csv # 狀態(tài)標(biāo)簽 ├── 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/依賴環(huán)境建議用conda或venv隔離。常用包與用途依賴包用途numpy/scipy信號處理與數(shù)值計(jì)算pandas標(biāo)簽與特征表管理scikit-learnSVM、隨機(jī)森林、評估指標(biāo)imbalanced-learnSMOTE過采樣tensorflowCNN、LSTM、GRU訓(xùn)練matplotlib時頻圖繪制與結(jié)果可視化安裝時注意TensorFlow和Python版本兼容Windows上建議用WSL2或CPU版本跑小數(shù)據(jù)量實(shí)驗(yàn)GPU版本再放到服務(wù)器。4.2 傳統(tǒng)機(jī)器學(xué)習(xí)模型訓(xùn)練代碼SVM、隨機(jī)森林手工特征表通常已經(jīng)降到幾十維先讀入特征和標(biāo)簽再切訓(xùn)練測試集。SVM需要pipeline隨機(jī)森林可以直接用原始特征。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里做標(biāo)準(zhǔn)化 svm_model make_pipeline( StandardScaler(), SVC(kernelrbf, C10, gammascale, class_weightbalanced) ) svm_model.fit(X, y) # 隨機(jī)森林不要求標(biāo)準(zhǔn)化class_weight處理不平衡 rf_model RandomForestClassifier( n_estimators500, min_samples_leaf2, class_weightbalanced, n_jobs-1 ) rf_model.fit(X, y)參數(shù)說明class_weightbalanced讓模型在損失函數(shù)中提高少數(shù)類權(quán)重n_jobs-1使用所有CPU核并行訓(xùn)練但保存的模型文件會更大。SVM的gammascale表示按特征數(shù)自動縮放避免手動調(diào)參。4.3 深度學(xué)習(xí)模型訓(xùn)練代碼CNN、LSTM/GRUCNN讀入時頻譜圖輸入最后一維是通道數(shù)。這里以Keras為例先構(gòu)建模型再結(jié)合上一章的早停策略訓(xùn)練。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會報(bào)錯。paddingsame讓卷積不縮小特征圖尺寸池化負(fù)責(zé)降維。全連接層輸出128維加Dropout是為了抑制過擬合最后的Dense輸出類別數(shù)softmax概率和為1。訓(xùn)練LSTM/GRU時只需把輸入換成(batch, time_steps, features)模型第一層換成LSTM或GRU其余評估流程一致。4.4 訓(xùn)練排錯過擬合、數(shù)據(jù)泄漏和標(biāo)簽偏移實(shí)際訓(xùn)練中遇到的絕大多數(shù)問題可以從損失曲線和混淆矩陣?yán)锟闯鰜怼R韵率俏业呐挪楸憩F(xiàn)象可能原因?qū)Σ哂?xùn)練loss下降驗(yàn)證loss上升過擬合增強(qiáng)數(shù)據(jù)、增加dropout、減少epoch準(zhǔn)確率高但少數(shù)類召回低類別不平衡調(diào)整class_weight、用macro F1早停驗(yàn)證指標(biāo)高于測試指標(biāo)很多數(shù)據(jù)泄漏檢查歸一化和SMOTE是否只fit在訓(xùn)練集模型表現(xiàn)和標(biāo)簽隨機(jī)打亂后差不多標(biāo)簽時間對齊錯誤重新檢查標(biāo)簽邊界裁掉過渡段數(shù)據(jù)泄漏最隱蔽。如果先對全量數(shù)據(jù)做StandardScaler再切分測試集的信息已經(jīng)參與計(jì)算均值和方差測試結(jié)果會虛高。正確做法是只在訓(xùn)練集上計(jì)算統(tǒng)計(jì)量再應(yīng)用到驗(yàn)證和測試集。標(biāo)簽偏移可以通過時間偏移實(shí)驗(yàn)驗(yàn)證把標(biāo)簽整體平移若干秒后重新訓(xùn)練如果模型精度變化不大說明模型更多在學(xué)工況變化而不是滾刀狀態(tài)。5. 部署時的概率閾值調(diào)整滾刀狀態(tài)識別落地的最后一個技巧模型訓(xùn)練完直接把a(bǔ)rgmax結(jié)果接到現(xiàn)場報(bào)警系統(tǒng)會很難受因?yàn)樾盘栍胁▌訂蝹€樣本的預(yù)測類別會來回跳導(dǎo)致頻繁誤報(bào)。更穩(wěn)的做法是輸出每個類別的概率然后在業(yè)務(wù)層設(shè)置“置信度閾值”和“猶豫區(qū)”。例如只有最大概率超過0.7才更新當(dāng)前狀態(tài)概率在0.4到0.7之間保留上一次確認(rèn)狀態(tài)這樣現(xiàn)場顯示是平滑的不會被單次抖動帶偏。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: # 猶豫區(qū)維持上一個穩(wěn)定狀態(tài) return last_status代碼中的閾值需要根據(jù)現(xiàn)場誤報(bào)率調(diào)整。如果報(bào)警頻繁調(diào)高h(yuǎn)igh_thres如果希望更早發(fā)現(xiàn)磨損調(diào)低閾值。這個閾值還可以按滾刀服役時間做動態(tài)調(diào)整比如更換新刀后前50米提高閾值越接近預(yù)估壽命越敏感。另一個落地細(xì)節(jié)是模型導(dǎo)出和預(yù)處理參數(shù)固化。訓(xùn)練好的Keras模型可以先保存為H5或SavedModel再轉(zhuǎn)成ONNX或TFLite格式脫離Python環(huán)境部署到C或Java服務(wù)里。轉(zhuǎn)換前要確認(rèn)預(yù)處理邏輯一致特別是濾波系數(shù)和歸一化統(tǒng)計(jì)量必須和訓(xùn)練時完全相同否則概率分布會漂移現(xiàn)場效果大打折扣。model.save(models/cnn.h5) # 轉(zhuǎn)換成輕量化TFLite方便邊緣設(shè)備加載 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、歸一化均值方差寫進(jìn)配置文件與模型文件一起發(fā)布。這樣一旦現(xiàn)場出現(xiàn)異??梢韵葯z查配置是否被改過而不是懷疑模型本身。滾刀狀態(tài)識別最考驗(yàn)工程一致性數(shù)據(jù)和模型在訓(xùn)練時是什么樣子部署時就應(yīng)該原樣重現(xiàn)真正的精度不是訓(xùn)練出來的是每一步都不走樣地保下來的。本文還有配套的精品資源點(diǎn)擊獲取