化VMD-CNN的軸承故障診斷全流程解析)
簡介面向軸承故障診斷與卷積神經(jīng)網(wǎng)絡結合的工程資源適合信號處理方向的研究生、工程師及機器學習初學者。方法采用高階變分模態(tài)分解對西儲大學不同轉速下的驅(qū)動端振動信號進行多層次分解提取本征模式函數(shù)并削弱噪聲再由CNN自動學習空間特征完成磨損、裂紋等故障模式的分類識別。壓縮包共15個文件約60.73MB核心為9個.m腳本覆蓋主程序、特征提取、網(wǎng)絡正則化模塊和五種適應度函數(shù)3個xlsx存放不同轉速的原始振動數(shù)據(jù)1個xlsx為HO-VMD特征提取后的數(shù)據(jù)集便于對比驗證另附1個txt安裝說明和1個pdf河馬優(yōu)化算法論文輔助復現(xiàn)與理解參數(shù)尋優(yōu)原理。目前已有203人學習下載可直接運行整個診斷流程也可基于不同轉速數(shù)據(jù)和多種熵類適應度函數(shù)進一步調(diào)參適用于課題預研、入門實踐及算法改進。1. 西儲大學軸承故障診斷HO-VMD-CNN這條路解決什么問題一臺風機軸承的振動信號里藏著故障的類型、位置和嚴重程度但原始波形根本不適合直接扔給神經(jīng)網(wǎng)絡。很多團隊在西儲大學CWRU軸承數(shù)據(jù)集上做實驗CNN結構改了一輪又一輪準確率卡在八九成上不去問題往往出在前處理信號沒分解干凈故障沖擊被噪聲淹沒。HO-VMD-CNN 是這類問題的標準解法——HO哈里斯鷹優(yōu)化自動給 VMD 選最優(yōu)的模態(tài)數(shù)和懲罰因子VMD 把原始振動信號拆成一簇有物理含義的 IMFCNN 再從分解后的多通道信號上學判別特征。這套流程適合手里有振動數(shù)據(jù)、想把故障類別自動分出來的人尤其適合被 VMD 兩個參數(shù)折磨過的調(diào)參工。2. VMD為什么需要HO來救從模態(tài)混疊到參數(shù)黑洞VMD變分模態(tài)分解把一段振動信號同時拆成 K 個離散模態(tài)每個模態(tài)被約束在一個窄頻帶里。背后的優(yōu)化目標是所有模態(tài)帶寬之和最小同時要求 K 個模態(tài)加起來能完整還原原始信號。這個思路比 EMD經(jīng)驗模態(tài)分解干凈EMD 靠極值插值遞歸剝皮對噪聲和采樣率敏感容易出現(xiàn)模態(tài)混疊VMD 轉成一個帶約束的變分問題用交替方向乘子法迭代求解分解結果穩(wěn)定得多。軸承故障的典型特征是周期性沖擊沖擊在頻域上會產(chǎn)生以故障特征頻率為中心的一簇邊帶VMD 天然適合把這些頻帶分離開。VMD 的理論形式也不復雜對每個模態(tài) u_k 做 Hilbert 變換得到解析信號再乘上指數(shù)項把頻譜搬到基頻附近最后求梯度范數(shù)。迭代過程中中心頻率 ω_k 和模態(tài) u_k 交替更新直到滿足收斂容差。工程里不需要自己實現(xiàn)這么一整套流程直接用現(xiàn)成的 vmdpy 庫就行但要理解兩個關鍵參數(shù)K 是模態(tài)總數(shù)alpha 是帶寬懲罰因子。這兩個參數(shù)不經(jīng)過尋優(yōu)直接拍腦袋定后面的 CNN 做得再漂亮也白搭。2.1 VMD在軸承信號上到底做了什么以 CWRU 驅(qū)動端 12 kHz 采樣加速度信號為例正常軸承能量分散在全頻帶看不到明顯峰值內(nèi)圈故障時沖擊調(diào)制出的高頻共振帶和低頻特征頻率帶同時出現(xiàn)。VMD 分解出的第一個模態(tài)往往捕獲幅值優(yōu)勢頻帶后面幾個模態(tài)捕獲諧波和殘余噪聲。K 設小了故障沖擊和噪聲被塞進同一個模態(tài)CNN 學到的是混疊后的復合特征K 設大了一個真實頻帶會被攔腰切成兩段出現(xiàn)沒有物理意義的虛假模態(tài)。alpha 控制模態(tài)帶寬的緊致程度alpha 太小模態(tài)帶寬過寬相鄰模態(tài)互相重疊alpha 太大模態(tài)被壓得過窄迭代不易收斂還可能丟掉沖擊的邊帶成分。這兩個參數(shù)互相耦合單靠看包絡譜人工判斷眼睛根本不夠用。參數(shù)影響對象典型表現(xiàn)K模態(tài)數(shù)模態(tài)數(shù)量K 過小導致模態(tài)混疊、能量交叉K 過大會出現(xiàn)無意義的虛假模態(tài)alpha懲罰因子模態(tài)帶寬過小帶寬寬、模態(tài)重疊過大帶寬窄、迭代慢或發(fā)散tau噪聲容忍重建保真度工程上一般設 0依靠保真項約束init初始化方式收斂路徑用 1均勻初始化避免過度依賴首模態(tài)VMD 的輸出是一組模態(tài)數(shù)組 ushape 是 (K, 信號長度)每個模態(tài)都是一條一維時域波形。后面做 CNN 輸入時這 K 個模態(tài)就是 K 個通道和圖像的 RGB 三通道類似。區(qū)別在于圖像通道是像素矩陣這里每個通道是獨立的時間序列長度可以人為截斷。這意味著 CNN 的結構要選一維卷積而不是二維卷積輸入張量是 (batch, K, length)。2.2 包絡熵把分解質(zhì)量變成一把刻度尺要讓優(yōu)化算法去搜 K 和 alpha先得有一個數(shù)值指標能評價“這組參數(shù)分解得好不好”。最常見的指標是包絡熵。計算方式是對模態(tài)信號做 Hilbert 變換求出包絡 a(t)歸一化成概率分布 p_i a(i) / Σa然后算信息熵 E -Σ p_i · log p_i。正常軸承振動包絡接近隨機噪聲概率分布平坦熵值高故障軸承的沖擊在包絡上呈現(xiàn)稀疏的尖峰概率分布集中在少數(shù)點上熵值低。VMD 參數(shù)選得好時故障模態(tài)的包絡熵會比欠分解參數(shù)低一大截這就把“分解質(zhì)量”變成了一個可以數(shù)值比較的標量。實際應用中每次尋優(yōu)都要對整段訓練信號跑一次 VMD算每個模態(tài)的包絡熵。常見做法是取 K 個模態(tài)里的最小包絡熵作為該組參數(shù)的適應度因為軸承故障沖擊的能量往往集中在一個主導模態(tài)上最小包絡熵能捕獲這個主導故障模態(tài)。也有文獻取平均包絡熵或加權熵思路一樣只是尺度不同。用包絡熵做適應度有個隱含前提包絡熵越低故障沖擊越突出后續(xù)分類越容易。這個前提在大部分軸承數(shù)據(jù)上成立但不是絕對成立后面第 5 章會專門講它的邊界。2.3 人工試參和網(wǎng)格搜索為什么都不夠用手工試參的流程是選一組 K 和 alpha跑 VMD看各 IMF 的包絡譜比對特征頻率換一組再跑。CWRU 每個類別采樣時間約 10 秒按 2048 點滑窗能切出幾百個樣本一次 VMD 耗時幾十到幾百毫秒試 8 組參數(shù)乘 10 個類別半天就過去了。最麻煩的是 K 和 alpha 互相影響K5 配合 alpha2000 時看起來不錯但 K6 時 alpha2000 反而過分解單獨調(diào)一個參數(shù)沒法收斂到好組合。網(wǎng)格搜索能系統(tǒng)覆蓋參數(shù)空間但組合數(shù)膨脹K 取 3 到 10alpha 按對數(shù)間隔取 15 個值就是 8×15120 次 VMD。對一條 12 kHz、10 萬點的信號120 次分解足夠跑一個多小時而且網(wǎng)格是離散的最優(yōu) alpha 往往不在網(wǎng)格點上。更關鍵的是CWRU 有多種負載和多個故障直徑不同數(shù)據(jù)段的最優(yōu) K 和 alpha 不一定相同網(wǎng)格搜索只能針對某一段信號換一段信號又要重來。把參數(shù)選擇當成黑盒子優(yōu)化問題用 HO 這類群體智能算法直接搜是目前最省事的做法。3. 用HO為VMD找最優(yōu)參數(shù)優(yōu)化映射與可復現(xiàn)代碼3.1 哈里斯鷹優(yōu)化怎么映射到VMD尋優(yōu)哈里斯鷹優(yōu)化Harris Hawks Optimization簡稱 HO是近年比較常用的群體智能算法模擬哈里斯鷹在沙漠中捕獵兔子的行為。兔子位置代表當前最優(yōu)解鷹群在探索階段隨機棲息尋找兔子在開發(fā)階段根據(jù)兔子逃跑能量做軟包圍、硬包圍、漸進式俯沖。把它用到 VMD 參數(shù)尋優(yōu)上一個鷹的位置就是一組候選參數(shù) [K, alpha]適應度就是跑完 VMD 得到的包絡熵。鷹群在 K-alpha 構成的二維平面上移動每一輪迭代更新所有鷹的位置然后比較每一處的適應度保留當前最優(yōu)兔子位置。K 本身是整數(shù)但 HO 的位置更新是連續(xù)值。常見處理方式是把 K 當連續(xù)變量參與鷹的位置運算評價適應度時再 round 成整數(shù)。這樣做的好處是算法不用做離散編碼壞處是 K 的梯度幾乎為零可能出現(xiàn) K 在連續(xù)幾次迭代里都不變。如果發(fā)現(xiàn) K 一直卡在同一數(shù)值可以改用離散映射把 K 編碼成 [0,1] 連續(xù)值解碼時映射到 3 到 10 的整數(shù)區(qū)間。兩種做法我都試過對 CWRU 數(shù)據(jù)來說連續(xù)取整通常夠用因為 alpha 才是真正敏感的參數(shù)。3.2 邊界設計K和alpha的范圍為什么要這樣定邊界設得不對尋優(yōu)結果是廢的。CWRU 12 kHz 數(shù)據(jù)上K 取 3 到 10 比較穩(wěn)妥小于 3 會把正常信號和故障沖擊壓在一起大于 10 噪聲會被逐條拆成獨立模態(tài)。alpha 取 500 到 5000alpha 太小帶寬約束失效模態(tài)之間互相混疊alpha 太大迭代代價成倍上升還可能不收斂。另一個容易忽略的細節(jié)是采樣方式alpha 在數(shù)千量級跨越很大初始化時要在指數(shù)空間采樣即 np.logspace(np.log(500), np.log(5000), n)而不是線性空間的均勻分布。否則 alpha 大概率落到 500 到 2000 之間5000 附近幾乎永遠采樣不到搜索空間被實際拉窄。種群規(guī)模和迭代次數(shù)也要克制。種群數(shù)量 10 到 20 個迭代 20 到 30 次一次完整尋優(yōu)要跑 200 到 400 次 VMD。對一條 12 kHz、幾萬點的信號來說這個量級在幾分鐘到十幾分鐘可以接受。如果信號長度超過 20 萬點建議把種群降到 6、迭代降到 15先對一小段代表性信號尋優(yōu)再把最優(yōu)參數(shù)應用到全部信號上不要試圖一次尋優(yōu)吃下整條長信號。3.3 HHO-VMD尋優(yōu)代碼與參數(shù)說明下面是基于 vmdpy 和 numpy 的完整尋優(yōu)代碼。vmdpy 是 VMD 的常見 Python 封裝pip install vmdpy 就能裝。如果環(huán)境裝不上把 VMD 函數(shù)體換成自己實現(xiàn)的變分模態(tài)分解即可接口不變。import numpy as np from scipy.signal import hilbert from vmdpy import VMD def envelope_entropy(signal): # 對信號取希爾伯特包絡歸一化后計算信息熵 amp np.abs(hilbert(signal)) amp amp / (np.sum(amp) 1e-12) return -np.sum(amp * np.log(amp 1e-12)) def vmd_cost(pos, signal): # pos 就是一組 [K, alpha]K 轉成整數(shù)再進入 VMD k int(round(pos[0])) alpha float(pos[1]) # 參數(shù)順序signal, alpha, tau, K, DC, init, tol # tau0 表示不額外引入噪聲控制DC0 不提取直流init1 均勻初始化 try: u, _, _ VMD(signal, alpha, 0, k, 0, 1, 1e-7) except Exception: # VMD 發(fā)散時返回一個大數(shù)作為懲罰 return 1e6 # 取 K 個模態(tài)里最小的包絡熵作為適應度 entropy np.array([envelope_entropy(m) for m in u]) return np.min(entropy) def hho_vmd(signal, bounds, pop10, iterations20, seed1): rng np.random.default_rng(seed) dim len(bounds) # 指數(shù)空間初始化 alpha線性空間初始化 K lo np.array([b[0] for b in bounds]) hi np.array([b[1] for b in bounds]) pos np.zeros((pop, dim)) for d in range(dim): if d 1: # alpha 維度用對數(shù)均勻采樣 log_lo, log_hi np.log(lo[d]), np.log(hi[d]) pos[:, d] np.exp(rng.uniform(log_lo, log_hi, pop)) else: pos[:, d] rng.uniform(lo[d], hi[d], pop) # 初始化兔子位置全局最優(yōu) best pos[0].copy() best_val vmd_cost(best, signal) for t in range(iterations): for i in range(pop): r rng.random() if r 0.5: # 探索階段隨機跳向種群里的其他位置或當前最優(yōu) if rng.random() 0.5: q rng.integers(0, pop) pos[i] pos[q] - rng.random() * np.abs(pos[q] - pos[i]) else: pos[i] best - rng.random() * np.abs(best - pos[i]) else: # 開發(fā)階段這里簡化成朝最優(yōu)位置收縮完整的 HHO 有四種包圍策略 pos[i] best - 0.2 * np.abs(best - pos[i]) * rng.random() # 越界處理直接裁剪到邊界 pos[i] np.clip(pos[i], lo, hi) # 評估本輪每個鷹位置 for i in range(pop): val vmd_cost(pos[i], signal) if val best_val: best_val val best pos[i].copy() return best, best_val # 示例signal 是 CWRU 的一條整段振動信號12kHz長度至少幾萬點 # bounds 順序是 [K_min, K_max], [alpha_min, alpha_max] # best_params, best_entropy hho_vmd(signal, bounds[[3, 10], [500, 5000]])這段代碼有幾個關鍵設計。vmd_cost 里把 K round 成整數(shù)alpha 保留浮點VMD 調(diào)用參數(shù)順序不能錯尤其是 tau 和 DC工程上固定為 0。適應度取最小包絡熵而不是平均包絡熵原因前面說過軸承故障能量集中在一個主導模態(tài)。HHO 的探索階段用了兩種隨機跳躍開發(fā)階段簡化成收縮包圍不是文獻里的完整四策略但對二維參數(shù)尋優(yōu)已經(jīng)夠用主要是收斂快、代碼短。種群設 10迭代設 20總共 200 次 VMD 調(diào)用一條 5 萬點信號大約 3 到 5 分鐘跑完。如果想把 K 也處理得更細膩可以改成離散映射pos[:,0] 約束在 [0,1]解碼時 k 3 int(round(pos[:,0] * 7))這樣 K 的每一步變化都能被算法感知到。代價是搜索空間變成一深一淺兩條腿收斂速度略降。建議先跑一次連續(xù)取整版如果發(fā)現(xiàn) K 始終不變且包絡熵不理想再換離散映射。4. 分解結果如何喂給CNN樣本構造與訓練配置4.1 從CWRU原始文件到訓練樣本先分解再滑窗CWRU 數(shù)據(jù)集按故障位置和故障直徑組織文件。常見做法是取 12 kHz 驅(qū)動端加速度信號做十分類正常用 97.mat0 馬力內(nèi)圈故障用 105、106、107 對應 0.007/0.014/0.021 英寸滾動體故障用 118、119、120外圈故障用 130、131、132。外圈故障在數(shù)據(jù)里有 3 點鐘、6 點鐘、12 點鐘三個方向通常只用其中一個方向比如 3 點鐘避免類別數(shù)膨脹。每個文件信號長度約 12 萬點對應 10 秒采樣樣本量完全夠用。關鍵時序是先分解再滑窗不是先滑窗再分解。對整段信號做一次 VMD得到 (K, 整段長度) 的模態(tài)數(shù)組然后從模態(tài)數(shù)組上滑窗取 (K, 2048) 的樣本。這樣做的好處是 VMD 的邊界效應只出現(xiàn)在整段信號的開頭和結尾中間所有窗口的分解質(zhì)量一致。如果先滑窗再逐窗口分解每個窗口兩端都有邊界效應等于每個樣本都被污染。import numpy as np from vmdpy import VMD def make_samples(signal, label, opt_k, opt_alpha, window2048, overlap0.5): # 對整段信號做一次 VMD得到 opt_k 個模態(tài) u, _, _ VMD(signal, opt_alpha, 0, opt_k, 0, 1, 1e-7) # u shape 是 (opt_k, len(signal)) # 丟棄開頭和結尾各 256 點規(guī)避邊界效應 u u[:, 256: -256] step int(window * (1 - overlap)) samples [] labels [] for start in range(0, u.shape[1] - window, step): samples.append(u[:, start:start window]) labels.append(label) return np.stack(samples), np.array(labels)樣本標簽是數(shù)字編碼十類對應 0 到 9?;爸丿B率用 0.5窗口 2048 點在 12 kHz 采樣下約等于 0.17 秒包含足夠多的沖擊周期。這里 window 不用設太大2048 點對 CNN 來說既保留了局部沖擊細節(jié)又不至于讓特征圖尺寸過大。樣本量方面一條 12 萬點信號去掉兩端邊界后按 1024 步長能切出約 110 個樣本10 個類別合計 1000 個樣本已經(jīng)能支撐一個小型 CNN 訓練。訓練集和測試集的劃分要格外小心。不能直接把全部樣本隨機打亂再切因為相鄰窗口高度相關訓練集和測試集會互相“抄答案”。正確做法是按文件來源切分每個類別的 10 秒信號前 60% 只進訓練集后 40% 只進測試集再在訓練集內(nèi)部做 80/20 的驗證集劃分。這樣測試樣本和訓練樣本來自不同的時間片段才有評估意義。4.2 1D-CNN結構通道數(shù)、核大小與感受野CNN 的輸入是 (batch, K, 2048)K 就是 VMD 尋優(yōu)得到的模態(tài)數(shù)通常在 4 到 8 之間。因為輸入是一維時間序列所以用一維卷積 Conv1d。第一層卷積核大小建議設大一點比如 kernel_size64、stride4。理由是一個沖擊周期在 12 kHz 下大約持續(xù) 50 到 150 點64 點的卷積核能覆蓋住半個到一個沖擊周期相當于讓第一層先做一次波形模板匹配。后續(xù)卷積核縮小到 3負責組合局部特征。全連接層不要堆太深。軸承故障分類任務的特征復雜度遠低于圖像識別兩層全連接足夠第一層 256第二層 10。全連接層多了訓練集準確率能到 100%測試集反而掉 2 到 3 個百分點典型的過擬合。Dropout 放 0.5只在全連接前加一層即可。下面是模型的 PyTorch 定義。import torch import torch.nn as nn class VMDCNN(nn.Module): def __init__(self, n_channels, n_classes10): super().__init__() # 一維卷積分支K 個模態(tài)當作 K 個通道 self.branch nn.Sequential( nn.Conv1d(n_channels, 32, kernel_size64, stride4, padding32), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(32, 64, kernel_size3, stride2, padding1), nn.BatchNorm1d(64), nn.ReLU(), nn.AdaptiveAvgPool1d(128) ) self.fc nn.Sequential( nn.Flatten(), nn.Linear(64 * 128, 256), nn.ReLU(), nn.Dropout(0.5), nn.Linear(256, n_classes) ) def forward(self, x): return self.fc(self.branch(x))這個結構很常規(guī)沒有花哨模塊。第一層 padding32 是為了補 kernel_size64 帶來的長度損失配合 stride4 把 2048 點輸入壓到 512 左右。中間那層 Conv1d 的 stride2 繼續(xù)壓縮分辨率最后一層 AdaptiveAvgPool1d 把特征圖統(tǒng)一到固定長度這樣即使窗口長度變了全連接層的輸入維度也不變。想用多尺度 CNN 做并行卷積也是可以的但對 CWRU 這個規(guī)模的數(shù)據(jù)集作用不大單分支結構已經(jīng)足夠很多實驗結果都印證了這一點。4.3 PyTorch訓練循環(huán)與超參配置訓練超參按常見動作維護習慣來設Adam 優(yōu)化器學習率 1e-3batch size 64epoch 50weight decay 1e-4遇到驗證集連續(xù) 5 輪不升就把學習率乘 0.5。50 輪并不是固定值早停機制會在驗證集不再提升時提前截斷避免浪費時間。import torch def train_vmd_cnn(model, train_loader, val_loader, epochs50, lr1e-3, devicecuda): model.to(device) opt torch.optim.Adam(model.parameters(), lrlr, weight_decay1e-4) lr_scheduler torch.optim.lr_scheduler.ReduceLROnPlateau(opt, factor0.5, patience3) loss_fn nn.CrossEntropyLoss() for epoch in range(epochs): model.train() total_loss 0.0 for x, y in train_loader: x, y x.to(device), y.to(device) opt.zero_grad() pred model(x) loss loss_fn(pred, y) loss.backward() opt.step() total_loss loss.item() * x.size(0) model.eval() val_correct 0 val_total 0 with torch.no_grad(): for x, y in val_loader: x, y x.to(device), y.to(device) pred model(x) val_correct (pred.argmax(1) y).sum().item() val_total y.size(0) val_acc val_correct / val_total lr_scheduler.step(val_acc) # 實際項目里可以把 TQDM 進度條和模型保存加在這里訓練循環(huán)本身沒有特別之處重點在于配置。batch size 用 64因為樣本本身只有一兩千用 128 會減少梯度更新次數(shù)收斂變慢。學習率初始 1e-3 是 Conv1d 任務最穩(wěn)的起點低于 5e-4 收斂太慢高于 2e-3 容易振蕩。weight_decay 主要約束全連接層卷積層參數(shù)共享本身就帶正則效果不用額外加太多。這里的 ReduceLROnPlateau 的 patience 是 3意思是驗證集連續(xù) 3 輪不升就降學習率比固定 step 降學習率更穩(wěn)。4.4 測試集評估混淆矩陣與準確率訓練完在測試集上做最終評估輸出準確率和混淆矩陣。評估時只跑前向不計算梯度預測結果和真實標簽對比。常見的十類問題里最容易混的是內(nèi)圈故障 0.007 英寸和滾動體故障 0.007 英寸兩者都是輕微故障沖擊幅值小、特征頻率接近CNN 很難區(qū)分。如果有幾個類互相混淆不要急著改網(wǎng)絡結構先把對應類別的 VMD 模態(tài)畫出來看看是不是分解不干凈。import numpy as np from sklearn.metrics import confusion_matrix test_correct 0 test_total 0 all_pred [] all_true [] model.eval() with torch.no_grad(): for x, y in test_loader: x, y x.to(device), y.to(device) pred model(x) test_correct (pred.argmax(1) y).sum().item() test_total y.size(0) all_pred.extend(pred.argmax(1).cpu().numpy()) all_true.extend(y.cpu().numpy()) print(ftest accuracy: {test_correct / test_total:.4f}) cm confusion_matrix(all_true, all_pred) print(cm)測試準確率能到 95% 以上說明流程基本通了但別急著高興。下一步要看跨負載表現(xiàn)這一步能篩掉很多只在特定轉速下有效的假方案。測試集評估之后模型就不要再回頭調(diào)參了否則測試集就變成了訓練集的一部分后面的結果全是水分。5. HO-VMD-CNN最常翻車的5個環(huán)節(jié)現(xiàn)象與排查5.1 坑1K上限設大VMD直接發(fā)散現(xiàn)象K 上限設到 12 或 15尋優(yōu)過程中 VMD 返回的模態(tài)數(shù)組里出現(xiàn) NaN或者分解結果能量遠大于原始信號包絡熵突然跳到一個荒謬的大數(shù)。原因K 超過信號實際可分的頻帶數(shù)量后交替方向乘子法會把噪聲一個點一個點地拆開迭代數(shù)值穩(wěn)定性崩盤。解決把 K 的上限壓到 10同時在 vmd_cost 里顯式檢查返回值是否包含 NaN一旦發(fā)現(xiàn)就返回一個很大的懲罰值讓優(yōu)化算法自動繞過這些區(qū)域。我見過有人把 K 上限設到 20跑了三個小時全部白費。5.2 坑2包絡熵局部最優(yōu)兩次尋優(yōu)結果對不上現(xiàn)象固定隨機種子跑出 K6、alpha2800換一個種子變成 K8、alpha1200兩者的包絡熵差距不到 5%。原因包絡熵曲面不是光滑的單峰函數(shù)很多參數(shù)組合的評價結果幾乎一樣HO 收斂到哪個峰取決于初始種群位置。解決同一信號跑三次尋優(yōu)每次換隨機種子取包絡熵最小且出現(xiàn)次數(shù)最多的參數(shù)組合或者把尋優(yōu)結果當作起點在鄰域內(nèi)再用幾個固定組合排查。不要期待一次尋優(yōu)就得到唯一最優(yōu)解HO 的本質(zhì)是給出一個很好的候選區(qū)間。5.3 坑3樣本切分重疊測試準確率虛高現(xiàn)象全局隨機切分樣本時測試準確率 98%改成按時間片劃分后掉到 91%模型結構一個字母沒改。原因滑窗重疊率 0.5 時相鄰樣本有 50% 長度的波形完全一樣隨機劃分會造成訓練集和測試集里出現(xiàn)“孿生樣本”測試準確率虛高。解決按原始文件的時間段劃分每個文件前 60% 進訓練集、后 40% 進測試集再做數(shù)據(jù)增強或交叉驗證也要以文件為單位分組。很多人用 sklearn 的 train_test_split 直接切默認隨機打亂這個坑踩得無聲無息。5.4 坑4換個負載準確率掉一半現(xiàn)象0 馬力數(shù)據(jù)訓練驗證 99%拿到 2 馬力數(shù)據(jù)上直接掉到 70%。原因CWRU 的負載檔位對應不同轉速負載增大后轉速下降故障特征頻率跟著偏移振動幅值也變大模型在訓練集里只見過 0 馬力的統(tǒng)計特征。解決訓練集里混合 0、1、2 馬力數(shù)據(jù)測試集放 3 馬力如果目標是單負載部署至少對每個樣本做 z-score 歸一化消除幅值差異。特征頻率偏移靠歸一化解決不了只能靠多負載數(shù)據(jù)覆蓋轉速范圍。5.5 坑5包絡熵最優(yōu)的參數(shù)端到端反而變差現(xiàn)象HO 搜出來的 K 和 alpha 包絡熵最低換到 CNN 上準確率比固定參數(shù) K5、alpha2000 還低一個多點。原因適應度函數(shù)是單模態(tài)最小包絡熵它評價的是“某個模態(tài)沖擊是否突出”而 CNN 分類需要的是所有模態(tài)的判別信息兩者不完全一致。解決不要把包絡熵當作最終標準它只是搜索向?qū)?。尋?yōu)得到候選參數(shù)后用三組參數(shù)做對比固定經(jīng)驗值、HO 最優(yōu)質(zhì)、人為微調(diào)值各訓一次 CNN看測試準確率決定最終采用哪個。這套流程看著笨但在很多數(shù)據(jù)集上固定參數(shù)并不輸給尋優(yōu)參數(shù)往往是人為微調(diào)后的組合拿到最好結果。6. 這套方案值不值得信混淆矩陣、t-SNE與跨負載驗收6.1 混淆矩陣看模型在哪里犯糊涂測試集準確率只是一個平均值真正暴露問題的是混淆矩陣。拿 CWRU 十分類來說如果 0.007 英寸內(nèi)圈故障那一列里混入了不少滾動體故障的預測說明這兩種輕微故障的頻帶在 VMD 分解后仍然有重疊CNN 學到的特征不夠清晰。這時候第一反應不是加卷積層而是看這兩個類別的模態(tài)波形和包絡譜差異在哪必要時把 K 整體加 1 或減 1 重新尋優(yōu)。6.2 t-SNE看特征是否真正聚攏混淆矩陣之外t-SNE 是檢查特征質(zhì)量最直觀的工具。用測試集跑一次前向把全連接層之前的特征抽出來做二維降維可視化后如果同一類聚成一團、不同類之間有明顯間隔說明 VMD 分解把故障特征分好了如果各類混成一灘再調(diào) CNN 結構也沒有意義。from sklearn.manifold import TSNE import matplotlib.pyplot as plt features, labels [], [] model.eval() with torch.no_grad(): for x, y in test_loader: f model.branch(x.to(device)).cpu().numpy() features.append(f.reshape(f.shape[0], -1)) labels.append(y.numpy()) feat np.concatenate(features) lab np.concatenate(labels) tsne TSNE(n_components2, perplexity30, random_state1).fit_transform(feat) plt.scatter(tsne[:, 0], tsne[:, 1], clab, cmaptab10, s4) plt.show()perplexity 要和樣本量匹配樣本幾百個時用 5 到 15樣本上千時用 30 左右。t-SNE 只能定性判斷看到重疊不一定是模型的問題也可能是可視化參數(shù)選得不合適要和混淆矩陣的數(shù)據(jù)互相印證。6.3 跨負載測試才是最終驗收西儲大學數(shù)據(jù)有 0、1、2、3 馬力四檔負載如果只用 0 馬力訓練、2 馬力測試大多數(shù)方案準確率都會明顯下滑這很正常。但一個值得投入的方案應該做到訓練集包含 0 和 1 馬力測試集用 2 和 3 馬力準確率依然保持在 90% 以上。做到這一點需要 VMD 參數(shù)在多個工況下有適應性而不是針對某一段信號過擬合。我在實際工程里的習慣是把跨負載測試當作硬性門檻達不到就回頭檢查樣本歸一化和數(shù)據(jù)集劃分而不是繼續(xù)加網(wǎng)絡深度。這套 HO-VMD-CNN 流程我最大的教訓是不要為了“最優(yōu)”去找最優(yōu)包絡熵是導航不是保險最終說了算的是測試集上的泛化表現(xiàn)尤其是在沒見過的負載上。把每個環(huán)節(jié)都跑通之后這套流程能穩(wěn)定幫我省掉一半調(diào)參時間也希望幫到你。本文還有配套的精品資源點擊獲取