元網(wǎng)絡(luò)算法與Python實踐)
簡介面向多變量系統(tǒng)控制研究者與自動化專業(yè)學(xué)生這份資源提供了基于比例-積分-微分PID神經(jīng)元網(wǎng)絡(luò)實現(xiàn)解耦控制的完整MATLAB程序。針對多輸入多輸出系統(tǒng)中變量相互耦合、控制難度大的問題算法借助神經(jīng)網(wǎng)絡(luò)的自學(xué)習(xí)與非線性映射能力對PID參數(shù)進(jìn)行在線優(yōu)化并通過解耦矩陣把耦合系統(tǒng)轉(zhuǎn)換為多個獨立的單變量回路。壓縮包為rar格式包含六個文件全部為.m腳本總大小僅13KB涵蓋主程序、解耦邏輯、粒子群優(yōu)化算法、目標(biāo)函數(shù)及結(jié)果繪圖等腳本模塊各模塊分工明確便于讀者快速定位、運(yùn)行和修改。目前該資源已有三百二十九人學(xué)習(xí)下載適合用作控制理論課程設(shè)計、畢業(yè)設(shè)計仿真或工程控制方案預(yù)研的參考樣例。通過研讀代碼可以掌握解耦矩陣計算、神經(jīng)網(wǎng)絡(luò)模型構(gòu)建、PID參數(shù)整定與系統(tǒng)仿真驗證的完整流程為后續(xù)擴(kuò)展到更復(fù)雜工業(yè)過程提供可復(fù)用的實現(xiàn)基礎(chǔ)。1. 多變量耦合回路為什么常規(guī) PID 一投自動就互相打架過程控制現(xiàn)場最常遇到的一個畫面是兩個回路單獨切手動、單獨整定 PID 時都好好的一旦都投自動系統(tǒng)就開始周期性地互相拉扯輸出曲線像兩條在較勁的蛇。你以為是參數(shù)沒整好把比例度調(diào)來調(diào)去結(jié)果越調(diào)越糟。這往往不是 PID 參數(shù)的問題而是回路之間存在耦合你調(diào)的是其中一個回路但擾動順著耦合通道串到了另一個回路另一個回路的控制器又把自己的調(diào)整串回來。PID 神經(jīng)元網(wǎng)絡(luò)解耦控制算法要解決的正是這個問題它把常規(guī) PID 的比例、積分、微分運(yùn)算直接做成網(wǎng)絡(luò)結(jié)構(gòu)里的三種神經(jīng)元再用輸出層的連接權(quán)把多變量系統(tǒng)里回路間的耦合關(guān)系在線學(xué)出來讓解耦和整定同時完成。適合正在做多變量過程控制、想先在仿真里驗證控制方案再考慮現(xiàn)場落地的工程師。2. PID 神經(jīng)元網(wǎng)絡(luò)的結(jié)構(gòu)邏輯比例、積分、微分神經(jīng)元如何承擔(dān)解耦2.1 隱含層直接實現(xiàn) PID 律三種神經(jīng)元的輸入輸出規(guī)則PID 神經(jīng)元網(wǎng)絡(luò)和普通 BP 網(wǎng)絡(luò)最大的區(qū)別在隱含層。普通 BP 的隱含層神經(jīng)元用的是 sigmoid 或 tanh 這類非線性激活函數(shù)網(wǎng)絡(luò)到底學(xué)到什么規(guī)律外部很難解釋。PID 神經(jīng)元網(wǎng)絡(luò)的做法相反隱含層每個神經(jīng)元的運(yùn)算規(guī)則是事先定死的分別對應(yīng)比例、積分、微分三種操作。以雙入雙出系統(tǒng)為例輸入層每個回路取兩個量當(dāng)前誤差 e(k) 和誤差變化量 Δe(k)。隱含層每個回路對應(yīng)三個神經(jīng)元比例元輸出就是當(dāng)前誤差本身h_P e(k)它決定控制力對偏差的即時反應(yīng)積分元輸出是誤差的累積值h_I Σe(k)它負(fù)責(zé)消除靜差把長期存在的偏差一點點頂回來微分元輸出是當(dāng)前誤差與上一拍誤差之差h_D e(k) - e(k-1)它起到預(yù)測偏差走勢、抑制超調(diào)的作用。輸出層做的是線性加權(quán)和第 i 個控制量 u_i b_i Σ w_ij * h_j其中 h_j 遍歷所有回路的比例、積分、微分神經(jīng)元輸出。這里有一個關(guān)鍵設(shè)計輸出層沒有非線性激活函數(shù)。原因是控制回路的誤差信號在動態(tài)過程中變化范圍很大如果套一個 sigmoid誤差稍大就進(jìn)入飽和區(qū)梯度趨近于零在線學(xué)習(xí)就停擺了。線性加權(quán)和保證權(quán)值在任何時刻都能獲得有效的修正量。這樣做的意義在于PID 規(guī)律不是靠訓(xùn)練「學(xué)」出來的而是被結(jié)構(gòu)「保證」的。網(wǎng)絡(luò)要學(xué)的只是各條連接通路的權(quán)值也就是每個誤差成分對每個控制量該貢獻(xiàn)多大。這部分恰恰是耦合信息所在。2.2 輸出層權(quán)值就是隱式解耦矩陣?yán)斫饨怦钤淼年P(guān)鍵在于隱含層輸出的 h 向量包含了全部回路的誤差信息。回路 1 的比例元、積分元、微分元在 h 里回路 2 的也在 h 里。輸出層計算 u1 時會對所有這些分量加權(quán)求和包括來自回路 2 誤差的分量。這就帶來一個很有意思的性質(zhì)當(dāng)回路 2 因為設(shè)定值變化產(chǎn)生偏差時這個偏差會通過回路 2 的比例元和積分元進(jìn)入 h 向量再通過權(quán)值 w_12、w_22 等通道直接影響 u1。如果訓(xùn)練讓這些交叉權(quán)值收斂到合適的值u1 就會在回路 2 出現(xiàn)偏差的瞬間提前產(chǎn)生一個補(bǔ)償分量抵消回路 2 通過對象耦合通道對回路 1 的擾動。這就是解耦補(bǔ)償?shù)麄€過程沒有一個顯式的解耦矩陣。傳統(tǒng)的前饋解耦或?qū)蔷仃嚱怦钚枰冉ο竽P退愠鲴詈贤ǖ赖膫鬟f函數(shù)再設(shè)計補(bǔ)償器。PID 神經(jīng)元網(wǎng)絡(luò)的思路完全不同輸出層權(quán)值本身就是解耦矩陣而且它是通過在線梯度下降逐步調(diào)整的不需要精確的對象模型甚至能在耦合強(qiáng)度隨工況變化時持續(xù)自適應(yīng)修正。代價是權(quán)值收斂需要充分的激勵如果兩個回路的設(shè)定值長期不動交叉權(quán)值就學(xué)不到有效的耦合信息這一點到第 5 章會展開說。2.3 學(xué)習(xí)算法符號近似梯度加動量項為什么不用純 BP權(quán)值修正的目標(biāo)函數(shù)取誤差平方和 J 0.5 * Σ e_i2(k)e_i r_i - y_i。對權(quán)值 w_ij 求梯度時會碰到 ?J/?w_ij -e_i * (?y_i/?u_i) * h_j。問題來了?y_i/?u_i 是被控對象的增益工程上拿不到解析表達(dá)式尤其現(xiàn)場對象還有純延遲和非線性。常見做法是用穩(wěn)態(tài)增益的方向符號來近似也就是只保留 ?y_i/?u_i 的正負(fù)號幅值讓學(xué)習(xí)率去吸收。這樣每一拍的權(quán)值修正量近似為Δw_ij η * e_i * sign(G_i) * h_j α * Δw_ij(previous)其中 η 是學(xué)習(xí)率α 是動量因子G_i 是第 i 個回路對象增益的方向。更新時要特別注意如果 sign(G_i) 取反誤差不但不會減小反而會被放大輸出幾拍之內(nèi)就會頂?shù)较薹@個坑在第 5 章專門列了一條。為什么不直接用純 BP兩個原因。第一純 BP 依賴激活函數(shù)的導(dǎo)數(shù)而這里的輸出層是線性的梯度本身不含非線性壓縮信息直接用 BP 的誤差反傳公式意義不大。第二控制回路的誤差序列在動態(tài)階段經(jīng)常是振蕩的不帶動量項的梯度下降會在最優(yōu)解附近來回震蕩收斂極慢。動量項相當(dāng)于給權(quán)值更新加了慣性能濾掉高頻抖動讓權(quán)值沿誤差下降的主導(dǎo)方向平滑移動。實際實現(xiàn)時動量項取 0.8 左右學(xué)習(xí)率取 0.02 到 0.1具體調(diào)法見第 4 章。3. 用 Python 復(fù)現(xiàn)雙入雙出解耦控制對象模型、網(wǎng)絡(luò)類和訓(xùn)練循環(huán)3.1 被控對象帶交叉耦合的二階差分模型仿真需要先有一個能體現(xiàn)耦合的對象。常見做法是用兩個二階欠阻尼通道加上交叉項因為過阻尼對象單回路 PID 就能壓住看不出解耦的價值。下面這個離散模型是我常用的一組系數(shù)模擬某工藝過程中兩個相互關(guān)聯(lián)的溫控通道主通道有欠阻尼二階動態(tài)交叉通道增益約為主通道的一半左右。import numpy as np class CoupledPlant: 雙入雙出二階對象含交叉耦合項模擬某過程通道的離散化模型 def __init__(self, g11.0, g21.0): self.g1 g1 # 通道1增益攝動系數(shù) self.g2 g2 # 通道2增益攝動系數(shù) self.y1_1, self.y2_1 0.0, 0.0 # k-1 時刻輸出 self.y1_2, self.y2_2 0.0, 0.0 # k-2 時刻輸出 self.u1_1, self.u1_2 0.0, 0.0 # 控制量歷史 self.u2_1, self.u2_2 0.0, 0.0 def step(self, u1, u2): # 主通道本回路控制量驅(qū)動本回路輸出二階欠阻尼動態(tài) y1 1.63 * self.y1_1 - 0.67 * self.y1_2 0.34 * self.g1 * self.u1_2 y2 1.55 * self.y2_1 - 0.58 * self.y2_2 0.29 * self.g2 * self.u2_2 # 交叉耦合對方控制量串入本回路 y1 0.16 * self.g2 * self.u2_2 y2 0.13 * self.g1 * self.u1_2 self.y1_2, self.y2_2 self.y1_1, self.y2_1 self.y1_1, self.y2_1 y1, y2 self.u1_2, self.u2_2 self.u1_1, self.u2_1 self.u1_1, self.u2_1 u1, u2 return y1, y2這里用差分方程而不是傳遞函數(shù)是為了讓對象代碼足夠短方便直接嵌入訓(xùn)練循環(huán)。系數(shù) 1.63 和 -0.67 對應(yīng)離散域里阻尼比約 0.45、自然角頻率約 1.0 rad/s 的二階系統(tǒng)采樣周期取 0.1 秒時換算過來的近似值。耦合項 g1、g2 是給第 6 章攝動掃描預(yù)留的參數(shù)平時保持 1.0 即可。u 的延遲取 2 拍模擬對象固有的純滯后。3.2 PID 神經(jīng)元網(wǎng)絡(luò)控制器約 60 行可運(yùn)行實現(xiàn)控制器實現(xiàn)的核心是積分元狀態(tài)在每次 forward 時累加誤差微分元取當(dāng)前誤差與上一拍誤差之差比例元直接透傳誤差輸出層做線性加權(quán)和。注意輸出限幅和積分限幅是必須的否則訓(xùn)練初期權(quán)值稍大就會讓控制量飛出執(zhí)行機(jī)構(gòu)范圍。class PIDNeuralNet: PID神經(jīng)元網(wǎng)絡(luò)解耦控制器隱含層固定 P/I/D 運(yùn)算輸出層權(quán)值在線學(xué)習(xí) def __init__(self, n_loop2, lr0.05, momentum0.8, u_lim2.0, i_lim3.0): self.n n_loop self.lr lr self.momentum momentum self.u_lim u_lim # 控制量限幅 self.i_lim i_lim # 積分累積限幅防 windup self.h_dim n_loop * 3 # 每回路 比例/積分/微分 三個神經(jīng)元 # 輸出層權(quán)值小隨機(jī)初始化避免第一拍就打滿限幅 self.W np.random.uniform(-0.05, 0.05, (n_loop, self.h_dim)) self.b np.zeros(n_loop) # 輸出層偏置可學(xué)習(xí) self.vW np.zeros_like(self.W) # 動量緩沖 self.vb np.zeros_like(self.b) self.integrators np.zeros(n_loop) # 積分元累積狀態(tài) self.last_e np.zeros(n_loop) # 上一拍誤差 def forward(self, e): # e: 長度為 n 的誤差向量e r - y de e - self.last_e self.last_e e.copy() self.integrators e self.integrators np.clip(self.integrators, -self.i_lim, self.i_lim) # 組裝隱含層輸出向量 h h np.zeros(self.h_dim) for i in range(self.n): h[3 * i] e[i] # 比例元 h[3 * i 1] self.integrators[i] # 積分元 h[3 * i 2] de[i] # 微分元 u self.W h self.b return np.clip(u, -self.u_lim, self.u_lim), h def update(self, h, e, gain_sign): # 負(fù)梯度方向近似為 e * sign(G)G 為對象穩(wěn)態(tài)增益方向 delta e * gain_sign gradW np.outer(delta, h) # 對 W 的負(fù)梯度 gradb delta.copy() # 對 b 的負(fù)梯度 self.vW self.momentum * self.vW self.lr * gradW self.vb self.momentum * self.vb self.lr * gradb self.W self.vW self.b self.vbgain_sign 是每個回路對象增益的方向u 增大導(dǎo)致 y 增大就取 1.0反之為 -1.0。update 里的梯度方向與 2.3 節(jié)推導(dǎo)一致因為 ?J/?w -e * G * h梯度下降取負(fù)號后權(quán)值實際沿 e * sign(G) * h 的方向增加。邏輯上要記住這不是隨便定的方向而是「誤差為正時增強(qiáng)對應(yīng)控制通道、誤差為負(fù)時減弱對應(yīng)控制通道」的直觀體現(xiàn)。3.3 訓(xùn)練循環(huán)在線自整定的正確時序與收斂判斷訓(xùn)練采用在線自整定模式每個采樣周期做一次「對象演化 → 算誤差 → 生成控制量 → 更新權(quán)值」的循環(huán)。設(shè)定值序列要用不同周期的方波錯開保證兩個回路持續(xù)被激勵交叉耦合路徑才有機(jī)會被權(quán)值學(xué)習(xí)到。def run_train(steps1200): plant CoupledPlant() ctrl PIDNeuralNet(lr0.05, momentum0.8) # 兩路設(shè)定值用不同周期錯開保證耦合路徑被持續(xù)激勵 t np.arange(steps) r1 np.where(t % 400 200, 1.0, 0.5) r2 np.where(t % 500 250, 0.8, 0.3) y1_list, y2_list [], [] u1_now u2_now 0.0 # 第一拍先用零控制量 for k in range(steps): # 先用上一拍的控制量演化對象再算本拍誤差 y1, y2 plant.step(u1_now, u2_now) e np.array([r1[k] - y1, r2[k] - y2]) u1_now, u2_now, h ctrl.forward(e) ctrl.update(h, e, gain_signnp.array([1.0, 1.0])) y1_list.append(y1) y2_list.append(y2) tail slice(steps - 400, steps) mae1 np.mean(np.abs(np.array(y1_list)[tail] - r1[tail])) mae2 np.mean(np.abs(np.array(y2_list)[tail] - r2[tail])) print(末段 MAE y1:, round(mae1, 4), y2:, round(mae2, 4)) if __name__ __main__: run_train()循環(huán)里的時序是一個容易寫錯的地方對象演化必須使用上一拍算出的控制量而不是本拍剛算出來的 u。如果順序反了等于把控制量提前了一拍仿真會表現(xiàn)出虛假的「超前調(diào)節(jié)」看起來跟蹤很好換到真實對象上立刻露餡。訓(xùn)練結(jié)束后觀察末段 MAE 是否明顯收斂到小值同時可以打印前 200 拍和末 200 拍的平均絕對誤差作對比。如果末段誤差不降反升優(yōu)先檢查 gain_sign 和積分限幅這兩處是發(fā)散的高發(fā)區(qū)。4. 把參數(shù)調(diào)到能上線學(xué)習(xí)率、動量、初值與采樣周期的取舍4.1 一張參數(shù)表看懂異常表現(xiàn)PID 神經(jīng)元網(wǎng)絡(luò)的參數(shù)數(shù)量比普通 PID 多但沒有一個參數(shù)是「玄學(xué)」每個參數(shù)異常時都有可識別的現(xiàn)象。下表是我在仿真和半實物測試?yán)锓磸?fù)確認(rèn)過的對應(yīng)關(guān)系。參數(shù)推薦范圍異常表現(xiàn)調(diào)整策略學(xué)習(xí)率 η0.02 0.10偏大控制量高頻抖動偏小幾百拍誤差都降不下來從 0.05 起步出現(xiàn)抖動就減半動量項 α0.60 0.90過大階躍響應(yīng)超調(diào)明顯過小收斂慢且路徑曲折先用 0.8超調(diào)大就降到 0.7輸出層權(quán)值初值±0.01 ±0.05絕對值過大會導(dǎo)致第一拍控制量接近限幅用 0.05 以內(nèi)的小隨機(jī)積分累積限幅標(biāo)稱設(shè)定值的 2 5 倍過小靜差消不掉過大超調(diào)大且回落慢按誤差典型幅值乘 3 左右給控制量限幅執(zhí)行機(jī)構(gòu)飽和值的 1.2 倍左右限幅太緊會讓網(wǎng)絡(luò)長期在邊界上磨比真實飽和值略寬即可學(xué)習(xí)率和動量項是最常調(diào)的兩個旋鈕。學(xué)習(xí)率決定權(quán)值每一步走多遠(yuǎn)動量項決定權(quán)值是否記得上一步的走向。兩者配合不好時典型表現(xiàn)是學(xué)習(xí)率大加動量大輸出像鋸齒學(xué)習(xí)率小加動量小訓(xùn)練像蝸牛爬。我一般先固定動量 0.8調(diào)學(xué)習(xí)率到系統(tǒng)穩(wěn)定不抖再反過來微調(diào)動量。4.2 權(quán)值初值與誤差歸一化別讓第一拍就打滿執(zhí)行機(jī)構(gòu)輸出層權(quán)值初值用 0.05 以內(nèi)的小隨機(jī)數(shù)目的很明確訓(xùn)練第一拍時隱含層輸出 h 的數(shù)量級在 1 到 3 左右如果權(quán)值給到 0.5控制量第一拍就可能打到限幅之后積分元在飽和區(qū)里累積誤差權(quán)值修正方向被扭曲整個訓(xùn)練從起步就歪了。偏置 b 初始化為零即可讓網(wǎng)絡(luò)從「什么都不補(bǔ)償」的狀態(tài)開始學(xué)。誤差歸一化是容易被新手忽略的步驟。上面仿真里設(shè)定值在 0.3 到 1.0 之間誤差量級是 1 以內(nèi)直接可用。如果換到實際工藝參數(shù)比如溫度設(shè)定是 80 攝氏度流量是 50 立方米每小時誤差可能到幾十的量級這時候必須先把誤差縮放到 ±1 區(qū)間再送進(jìn)網(wǎng)絡(luò)否則積分元累積飛快限制幅形同虛設(shè)不同回路的誤差量級差異還會讓權(quán)值更新失衡。常見做法是每個回路單獨做縮放縮放系數(shù)取該回路設(shè)定值變化范圍的倒數(shù)。4.3 采樣周期決定微分元是幫手還是噪聲放大器的隱藏前提采樣周期在這類神經(jīng)元網(wǎng)絡(luò)控制器里是一個容易被低估的參數(shù)。采樣周期取主導(dǎo)時間常數(shù)的 1/10 到 1/5 是仿真對象的常用經(jīng)驗。太大會讓每一拍之間系統(tǒng)狀態(tài)變化過大微分元輸出變成大幅跳變等效增益被放大控制量會跟著毛刺太小則相鄰兩拍的誤差幾乎一樣微分元輸出接近零但測量噪聲被差分放大微分元從預(yù)測偏差變成噪聲放大器。一個額外的坑是純延遲。前面對象模型里 u 對 y 有 2 拍延遲采樣周期縮短并不能減少延遲拍數(shù)反而會讓延遲對應(yīng)的相位損失相對更大。這時候不要試圖靠調(diào)學(xué)習(xí)率找回穩(wěn)定性正確做法是讓網(wǎng)絡(luò)結(jié)構(gòu)里給誤差多留一拍的記憶或者在輸出層前面加一個移位寄存器存儲歷史控制效果。等效地把微分元的差分間隔從 1 拍擴(kuò)大到 2 到 3 拍也能緩解短采樣周期帶來的噪聲放大問題。5. PID 神經(jīng)元網(wǎng)絡(luò)解耦控制避坑五個常見排錯場景5.1 換一組設(shè)定值就發(fā)散訓(xùn)練陷入過擬合現(xiàn)象在某一組設(shè)定值序列下訓(xùn)練末段跟蹤誤差很漂亮一換設(shè)定值的幅值或周期系統(tǒng)就開始振蕩甚至發(fā)散。原因權(quán)值只在訓(xùn)練那組設(shè)定值附近被充分激勵輸出層權(quán)值記住了特定幅值下的誤差分布相當(dāng)于過擬合。積分元和比例元對不同幅值的響應(yīng)是線性的但耦合權(quán)值未必在別的幅值區(qū)間仍然合適。解決訓(xùn)練設(shè)定值序列里至少包含三組不同幅值、兩組不同周期的方波讓網(wǎng)絡(luò)見過多種誤差組合。另一個有用的習(xí)慣是訓(xùn)練結(jié)束后凍結(jié)權(quán)值換一組新設(shè)定值做驗證如果驗證誤差比訓(xùn)練誤差明顯大說明激勵不充分需要回去加訓(xùn)練序列而不是加學(xué)習(xí)率。5.2 靜差消不掉積分元被限幅截斷或者 bias 沒學(xué)到位現(xiàn)象系統(tǒng)穩(wěn)定了但輸出與設(shè)定值始終差一個固定值比如設(shè)定 1.0輸出穩(wěn)定在 0.93。原因兩處最容易出問題。一是積分累積限幅設(shè)得太小誤差累積到限幅值之后不再增長積分元的輸出被截斷權(quán)值再大也補(bǔ)不回誤差二是輸出層偏置 b 沒有被正確更新或者初值給得太大導(dǎo)致網(wǎng)絡(luò)在零誤差附近靠偏置硬撐。解決把積分累積限幅放寬到設(shè)定值幅度的 3 倍以上同時檢查 update 里偏置的修正量是否和權(quán)值修正量同數(shù)量級。偏置的學(xué)習(xí)率可以比權(quán)值略大因為偏置承擔(dān)的是穩(wěn)態(tài)補(bǔ)償。另一個排查辦法是人為給系統(tǒng)加一個恒值擾動看靜差是否隨著訓(xùn)練拍數(shù)增加而逐步縮小如果完全不縮小問題幾乎都出在積分限幅。5.3 一路調(diào)整另一路跟著抖耦合通道激勵不足現(xiàn)象回路 2 的設(shè)定值階躍變化回路 1 的輸出跟著明顯波動而且波動幅度不隨時間減弱。原因交叉權(quán)值沒有學(xué)到有效的解耦值。最典型的原因是訓(xùn)練過程中兩個回路的設(shè)定值同步變化回路 2 的誤差和回路 1 的誤差總是同時出現(xiàn)網(wǎng)絡(luò)無法區(qū)分哪個誤差來自哪個通道交叉權(quán)值被平均掉了。解決把兩個回路的設(shè)定值在時間上錯開讓系統(tǒng)分別經(jīng)歷「只有回路 2 動、回路 1 不動」和「只有回路 1 動、回路 2 不動」的階段。前文訓(xùn)練代碼里 r1 用 400 拍周期、r2 用 500 拍周期錯開效果已經(jīng)夠用。如果現(xiàn)場不允許大范圍錯開設(shè)定值可以在訓(xùn)練指標(biāo)里加入耦合懲罰項把交叉通道上多余的波動計進(jìn)損失函數(shù)但這需要能實時測量兩路輸出的波動實現(xiàn)起來比重排訓(xùn)練序列要麻煩。5.4 輸出一直頂限幅增益方向符號給反了現(xiàn)象訓(xùn)練開始后控制量直接沖上限幅輸出朝設(shè)定值相反的方向跑誤差越來越大幾拍后徹底發(fā)散。原因gain_sign 數(shù)組里有一個回路的符號給反了。前面推導(dǎo)里 Δw 的方向依賴 sign(G)如果實際對象是反作用u 增大導(dǎo)致 y 減小而 sign 給了 1權(quán)值更新方向完全反轉(zhuǎn)誤差會被持續(xù)放大而不是減小。這是這門算法里最隱蔽也最致命的錯誤因為符號錯時網(wǎng)絡(luò)一樣在「學(xué)習(xí)」只不過學(xué)的是反方向。解決在接入網(wǎng)絡(luò)前先對每個回路單獨做一次開環(huán)階躍測試記錄控制量增大時輸出的實際變化方向把符號寫死進(jìn)配置。如果對象特性會隨工況翻轉(zhuǎn)增益方向比如某些換熱過程在低溫段和高溫段增益符號不同需要在每個工況區(qū)間單獨確認(rèn)必要時用在線辨識的差商替代固定符號但差商會引入噪聲一般只在仿真里用。5.5 仿真滿意現(xiàn)場不行模型失配被網(wǎng)絡(luò)照單全收現(xiàn)象仿真里跟蹤和耦合抑制都很好放到真實對象或半實物環(huán)境里卻出現(xiàn)持續(xù)慢振蕩或者某一回路始終達(dá)不到設(shè)定值。原因仿真對象的參數(shù)是固定的網(wǎng)絡(luò)在訓(xùn)練過程中把對象特性「記」進(jìn)了權(quán)值對象實際增益、時間常數(shù)和純延遲稍有偏差權(quán)值就失配。PID 神經(jīng)元網(wǎng)絡(luò)和普通 PID 一樣對模型失配沒有天然的免疫力不會因為帶上了「網(wǎng)絡(luò)」兩個字就自動魯棒。解決訓(xùn)練完成后做一次參數(shù)攝動掃描把對象增益和時間常數(shù)在 ±20% 范圍內(nèi)打亂凍結(jié)權(quán)值重新跑同一組設(shè)定值看誤差和耦合度是否還在可接受范圍內(nèi)。如果掃描不過說明方案需要加魯棒化處理比如約束權(quán)值范數(shù)、降低學(xué)習(xí)率讓權(quán)值不要走得太遠(yuǎn)或者用一個帶參數(shù)的失配對象集做多對象聯(lián)合訓(xùn)練。這個驗證流程具體怎么做就是下一章的內(nèi)容。6. 進(jìn)階用對象攝動掃描給解耦結(jié)果做魯棒性驗收6.1 攝動掃描腳本與兩個判定指標(biāo)訓(xùn)練完的權(quán)值不能直接拿去現(xiàn)場用我習(xí)慣先做一輪攝動掃描。思路很簡單凍結(jié)訓(xùn)練好的網(wǎng)絡(luò)讓對象參數(shù)在一個范圍內(nèi)隨機(jī)變化反復(fù)跑同一組設(shè)定值序列統(tǒng)計誤差和耦合度。對象代碼里預(yù)留的 g1、g2 參數(shù)就是為這一步準(zhǔn)備的。def robustness_sweep(ctrl, rounds40, seed7): rng np.random.default_rng(seed) worst_coupling 0.0 worst_mae 0.0 for _ in range(rounds): g1 rng.uniform(0.8, 1.2) # 通道1增益攝動 ±20% g2 rng.uniform(0.8, 1.2) # 通道2增益攝動 ±20% plant CoupledPlant(g1g1, g2g2) # 用凍結(jié)權(quán)值跑一遍不調(diào)用 update mae1, mae2, coup evaluate_frozen(ctrl, plant) worst_coupling max(worst_coupling, coup) worst_mae max(worst_mae, (mae1 mae2) / 2) return worst_mae, worst_couplingevaluate_frozen 的寫法就是把第 3 章訓(xùn)練循環(huán)里的 ctrl.update 去掉其余時序不變。耦合度指標(biāo)我取回路 2 的設(shè)定值階躍期間回路 1 輸出的最大偏移量除以回路 2 設(shè)定值的變化幅值。這個比值在 10% 以內(nèi)算合格10% 到 30% 可以接受但要注意現(xiàn)場風(fēng)險超過 30% 說明解耦只在名義模型附近成立權(quán)值還需要重新訓(xùn)練或者增加訓(xùn)練序列的覆蓋范圍。這個過程是我每次改完網(wǎng)絡(luò)結(jié)構(gòu)都會跑一遍的固定動作。寧可多花半天把參數(shù)域掃完摸清方案的邊界在哪里也不愿意到現(xiàn)場才第一次看到系統(tǒng)在模型失配下的反應(yīng)。解耦控制算法的價值從來不只是仿真曲線好看而是換一組工況、換一組參數(shù)它還能不能站得住。希望幫到你。本文還有配套的精品資源點擊獲取