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