戰(zhàn):從收益矩陣到納什均衡的策略優(yōu)化)
說實(shí)話我一直覺得做智能博弈系統(tǒng)最容易被低估的地方不是算法選型不是工程架構(gòu)而是怎么把博弈這件事本身講清楚。之前我在梳理一個叫Matrix-Game的矩陣博弈引擎時最深的一個感受是一旦你把玩家、策略、收益全部轉(zhuǎn)換成了矩陣和向量原來那些看起來高深莫測的博弈論概念一下子就變成了可以上手調(diào)試、可以漸進(jìn)優(yōu)化、可以測試驗(yàn)證的工程問題。這篇文章就把這套思路完整展開適合兩類人看一類是想做棋牌AI、對抗決策系統(tǒng)或策略引擎的開發(fā)者另一類是讀過博弈論但不知道怎么寫代碼的研究者。我會從數(shù)學(xué)原理講到工程實(shí)現(xiàn)再講到我在實(shí)際調(diào)優(yōu)中踩過的坑盡量把矩陣運(yùn)算驅(qū)動這件事講透。1. 為什么要把博弈問題矩陣化一個被低估的起點(diǎn)1.1 從收益矩陣說起博弈的骨架兩個玩家有限個可選動作每個動作組合對應(yīng)一個收益結(jié)果——這種設(shè)定幾乎覆蓋了從剪刀石頭布到復(fù)雜棋類游戲的基礎(chǔ)結(jié)構(gòu)。所謂矩陣博弈就是把這些收益關(guān)系按照行玩家選某個動作、列玩家選某個動作的方式整理成一張二維表。比如剪刀石頭布收益矩陣可以寫成這樣約定1表示勝、0表示平、-1表示負(fù)行代表我方列代表對手我方動作對手出石頭對手出剪刀對手出布石頭01-1剪刀-101布1-10在Matrix-Game里這張表就是整個博弈系統(tǒng)的數(shù)據(jù)模型。別小看這一步把規(guī)則翻譯成矩陣之后后面所有決策邏輯都不再需要寫一堆if-else判斷而是統(tǒng)一的線性代數(shù)運(yùn)算。我看過不少人做對抗AI上來就寫一個巨大的規(guī)則判斷樹每個局面一個分支每加一種策略就膨脹一次。矩陣化的思路完全不同規(guī)則轉(zhuǎn)化成矩陣決策轉(zhuǎn)化成矩陣乘法策略更新轉(zhuǎn)化成逐元素加法和歸一化。這套做法的好處是你可以在非常晚的階段才決定用經(jīng)典算法還是深度學(xué)習(xí)方法因?yàn)樗鼈冊诘讓佣脊蚕硗粋€矩陣表示。1.2 把策略裝進(jìn)向量混合策略的幾何直覺純策略很容易理解就是我固定出石頭。但在剪刀石頭布這類游戲里純策略沒有任何優(yōu)勢因?yàn)橐坏┍粚κ挚创┚捅剌?。這時候需要混合策略——以某個概率分布在各動作之間隨機(jī)選擇。如果你把混合策略看成一個向量比如我方有概率分布p對手有概率分布q那么我方的期望收益就是E p^T A q這是一個極其優(yōu)雅的表達(dá)一次矩陣乘法就把雙方策略空間里無窮多對策略組合的期望收益算清楚了。A是收益矩陣p和q分別是兩個玩家的策略向量。從幾何上看每個玩家的策略空間都是一個概率單純形。p和q在這個單純形上移動矩陣A定義了雙方期望收益的地形。博弈求解的任務(wù)本質(zhì)上就是在這片地形上找到讓雙方都無法單方面改進(jìn)的駐點(diǎn)——也就是納什均衡。Matrix-Game的核心邏輯就在這里它不把博弈當(dāng)作離散規(guī)則的堆砌而是當(dāng)作連續(xù)空間上的優(yōu)化問題。矩陣運(yùn)算驅(qū)動的不只是數(shù)值計算更是對策略空間的結(jié)構(gòu)化理解。1.3 Matrix-Game的設(shè)計目標(biāo)矩陣不只是一個數(shù)據(jù)結(jié)構(gòu)我做Matrix-Game的時候給自己的定位不是再做一套棋牌AI而是做一個通用的矩陣博弈求解引擎。輸入一張收益矩陣輸出均衡策略或者輸入一組狀態(tài)特征矩陣輸出當(dāng)前局面下的最優(yōu)動作分布。這個定位決定了架構(gòu)上的一個關(guān)鍵取舍所有上層模塊——無論是蒙特卡洛樹搜索、遺憾匹配還是神經(jīng)網(wǎng)絡(luò)策略逼近——都以統(tǒng)一的矩陣接口訪問博弈狀態(tài)。這樣做的好處非常實(shí)際調(diào)試的時候你可以隨時打印一張矩陣來看清楚系統(tǒng)內(nèi)部發(fā)生了什么而不是面對一堆抽象對象和調(diào)用鏈。2. 核心算法拆解矩陣運(yùn)算到底在驅(qū)動什么2.1 零和博弈與minimax矩陣上的動態(tài)規(guī)劃說到矩陣博弈最經(jīng)典的定理就是minimax定理。它的核心結(jié)論是在兩人零和有限策略博弈中最優(yōu)混合策略下的結(jié)果滿足max_p min_q p^T A q min_q max_p p^T A q這個等式看著簡單但它把所有博弈求解問題直接連通到了線性規(guī)劃。因?yàn)榍蠼庾髠?cè)的max-min問題等價于解一個帶線性約束的優(yōu)化問題。在實(shí)際代碼里你用線性規(guī)劃求解器和直接用矩陣迭代算法解同一張收益矩陣得到的結(jié)果應(yīng)該一致。我在Matrix-Game里做單元測試時經(jīng)常把兩種方法的結(jié)果放在一起對比誤差在1e-6以內(nèi)才認(rèn)定求解器實(shí)現(xiàn)正確。但minimax本身也有局限。它假設(shè)雙方完全理性且收益矩陣完全已知。在真實(shí)場景中收益矩陣可能是估計出來的對手也未必最優(yōu)所以純粹的minimax只能作為系統(tǒng)的鞍點(diǎn)參考不能作為唯一決策依據(jù)。Matrix-Game把minimax結(jié)果作為基線再疊加在線學(xué)習(xí)和自適應(yīng)更新這樣系統(tǒng)既穩(wěn)定又有彈性。2.2 遺憾匹配用矩陣運(yùn)算逼近均衡minimax定理告訴我們均衡存在但怎么高效地算出來對于小規(guī)模收益矩陣可以直接用線性規(guī)劃矩陣規(guī)模變大或者問題變得非完美信息時我推薦用遺憾匹配Regret Matching這類迭代算法。遺憾匹配的思路非常直觀每個玩家維護(hù)一個累積遺憾向量記錄過去每個純策略相比實(shí)際混合策略多賺了多少收益。下一輪策略更新時把累積遺憾的正部歸一化成概率分布遺憾越大越有可能在下一輪被采用。這個算法映射到矩陣運(yùn)算上每個循環(huán)只需要幾步計算純策略期望收益向量e1 A p2e2 -A.T p1計算當(dāng)前平均收益v1 p1 e1v2 p2 e2更新累積遺憾regret_1 e1 - v1正部歸一化得到新策略整個過程沒有分支判斷沒有復(fù)雜數(shù)據(jù)結(jié)構(gòu)就是矩陣乘法加向量歸一化。這也正是Matrix-Game選擇矩陣作為中間表示的原因復(fù)雜的博弈論算法可以變成幾十行穩(wěn)定可跑的向量化代碼。2.3 搜索樹評估矩陣在MCTS里的真實(shí)位置很多做棋類AI的同學(xué)一上來就寫蒙特卡洛樹搜索MCTS但MCTS本身并不直接處理矩陣。它維護(hù)的是每個節(jié)點(diǎn)的訪問次數(shù)、勝率和子節(jié)點(diǎn)列表。那矩陣在哪里關(guān)鍵在于兩處。第一MCTS的模擬階段需要大量快速評估評估函數(shù)通常返回一個價值向量或動作勝率向量這些向量本質(zhì)上是某個狀態(tài)矩陣經(jīng)過矩陣乘法得到的輸出。第二當(dāng)MCTS與策略網(wǎng)絡(luò)結(jié)合時策略網(wǎng)絡(luò)的前向傳播本身就是矩陣乘法搜索樹用這些策略向量作為先驗(yàn)概率引導(dǎo)探索方向。我在一個簡單的棋盤游戲Demo里跑過MCTS早期版本完全用對象和字典存狀態(tài)速度很慢而且極難并行。后來我把所有節(jié)點(diǎn)的訪問次數(shù)勝率整理成矩陣每次批量選擇、批量回傳性能提升了一個數(shù)量級。這讓我更確信矩陣運(yùn)算驅(qū)動本質(zhì)上是在拿線性代數(shù)的高效實(shí)現(xiàn)去碾壓Java或Python里散落的對象操作。3. 工程落地從數(shù)學(xué)公式到可運(yùn)行的博弈系統(tǒng)3.1 數(shù)據(jù)流設(shè)計狀態(tài)矩陣、策略矩陣與收益矩陣下面說一下Matrix-Game的模塊劃分。整個系統(tǒng)大致可以分成四層規(guī)則層負(fù)責(zé)把具體游戲規(guī)則解析成收益矩陣或狀態(tài)特征。求解層根據(jù)收益矩陣計算策略分布基礎(chǔ)模塊是線性規(guī)劃求解器和遺憾匹配求解器。決策層整合搜索樹、神經(jīng)網(wǎng)絡(luò)或規(guī)則修正輸出最終動作。學(xué)習(xí)層在每輪結(jié)束后更新策略矩陣和收益估計。這樣的分層讓測試變得很舒服。規(guī)則層有問題只需要單獨(dú)驗(yàn)證收益矩陣決策層有問題只需要給定收益矩陣和策略分布檢查輸出。不需要每次改動都在完整系統(tǒng)里從頭跑一遍。數(shù)據(jù)流上我堅持所有中間結(jié)果都是明確的矩陣或向量。舉個例子某個棋類游戲的狀態(tài)特征我會用一個三維張量表示通道數(shù)對應(yīng)特征類型兩個空間維度對應(yīng)棋盤位置。這種表示在構(gòu)造時會多花一點(diǎn)心思但后續(xù)無論是喂給神經(jīng)網(wǎng)絡(luò)還是做規(guī)則評估都不需要再轉(zhuǎn)換格式。3.2 一個能跑的最小實(shí)現(xiàn)基于遺憾匹配的策略求解器直接上一個你能跑起來的最小實(shí)現(xiàn)。這段代碼用NumPy實(shí)現(xiàn)了一個通用的雙人零和矩陣博弈求解器輸入收益矩陣輸出雙方的最優(yōu)混合策略。import numpy as np def regret_matching_solver(A, iterations100000): 對兩人零和有限策略矩陣博弈求解混合策略均衡。 A[i, j] 表示行玩家選擇動作 i、列玩家選擇動作 j 時 行玩家的收益列玩家的收益為 -A[i, j]。 n, m A.shape p1 np.ones(n) / n p2 np.ones(m) / m cum_regret_1 np.zeros(n) cum_regret_2 np.zeros(m) for _ in range(iterations): e1 A p2 e2 -A.T p1 v1 p1 e1 v2 p2 e2 cum_regret_1 e1 - v1 cum_regret_2 e2 - v2 pos_1 np.maximum(cum_regret_1, 0) if pos_1.sum() 0: p1 pos_1 / pos_1.sum() else: p1 np.ones(n) / n pos_2 np.maximum(cum_regret_2, 0) if pos_2.sum() 0: p2 pos_2 / pos_2.sum() else: p2 np.ones(m) / m return p1, p2 A np.array([[0, -1, 1], [1, 0, -1], [-1, 1, 0]], dtypenp.float64) p1, p2 regret_matching_solver(A, iterations100000) print(行玩家策略:, p1) print(列玩家策略:, p2)跑完這段代碼你會看到兩個策略向量都收斂到接近[1/3, 1/3, 1/3]的值這正是剪刀石頭布的混合納什均衡。不要小看這個幾十行的實(shí)現(xiàn)它已經(jīng)具備處理任意有限矩陣博弈的能力把A換成其他收益矩陣一樣能輸出均衡策略。3.3 與神經(jīng)網(wǎng)絡(luò)結(jié)合矩陣運(yùn)算如何變成訓(xùn)練引擎如果策略空間不是離散的有限集合比如圍棋或德?lián)渲械木置嫣卣鳂O其高維純矩陣博弈的方法就不夠用了。這時就需要引入神經(jīng)網(wǎng)絡(luò)而神經(jīng)網(wǎng)絡(luò)恰好也是矩陣運(yùn)算的天然宿主。在Matrix-Game的框架里策略網(wǎng)絡(luò)可以看作一個從狀態(tài)矩陣到策略向量的函數(shù)逼近器。前向傳播是矩陣乘法加激活函數(shù)反向傳播是矩陣的轉(zhuǎn)置乘法加梯度更新。也就是說神經(jīng)網(wǎng)絡(luò)訓(xùn)練過程和遺憾匹配的矩陣更新在底層是同一類運(yùn)算——大量的向量化矩陣操作。我在系統(tǒng)里加過一個自博弈模塊兩個策略網(wǎng)絡(luò)互相博弈每一輪對局結(jié)束后用遺憾值或收益信號作為梯度通過反向傳播更新網(wǎng)絡(luò)參數(shù)。因?yàn)橛辛私y(tǒng)一的矩陣中間表示經(jīng)典求解器和深度網(wǎng)絡(luò)可以共存于同一個pipeline里這是我認(rèn)為Matrix-Game最有價值的地方。4. 測試與效果驗(yàn)證怎么判斷系統(tǒng)真的智能起來了4.1 基準(zhǔn)測試對抗隨機(jī)策略與固定策略構(gòu)建任何博弈系統(tǒng)第一件事是定義智能的標(biāo)準(zhǔn)。我的做法分三步測試。第一步對抗隨機(jī)策略。一個純隨機(jī)出招的對手沒有模式系統(tǒng)如果確實(shí)學(xué)到了均衡策略期望收益應(yīng)該趨近于零對零和博弈而言且方差要足夠小。第二步對抗固定策略比如對方總是出石頭。理想的響應(yīng)是系統(tǒng)策略快速偏向?qū)箘幼鳌绻找婢仃囀羌舻妒^布那就幾乎總會出布期望收益趨近1。第三步對抗最優(yōu)反應(yīng)策略驗(yàn)證系統(tǒng)在面對較強(qiáng)對手時不會崩潰。這套測試的好處是每一步都能用期望收益量化不需要人去主觀判斷看起來強(qiáng)不強(qiáng)。我在開發(fā)早期就養(yǎng)成了固化基準(zhǔn)測試的習(xí)慣每次改動算法先跑一遍基準(zhǔn)再談效果優(yōu)化。4.2 收斂性驗(yàn)證從策略熵看均衡的逼近只給策略結(jié)果還不夠還要能解釋為什么這個策略是對的。我用的是策略熵加累積遺憾的組合。策略熵衡量的是策略向量的不確定性。初始階段熵值較大因?yàn)椴呗越咏鶆蚍植?。隨著迭代進(jìn)行如果博弈存在混合策略均衡熵會逐步下降并穩(wěn)定在某個水平如果不收斂熵就會震蕩。累積遺憾則可以刻畫逼近程度。理論上當(dāng)累積遺憾增長速度放緩且平均策略接近均衡點(diǎn)時可以判定算法已收斂。在代碼里我會每隔一定迭代輪數(shù)打印一次策略矩陣和遺憾值直接觀察變化趨勢。下面是一個剪刀石頭布示例的收斂趨勢迭代輪數(shù)石頭概率剪刀概率布概率策略熵00.3330.3330.3331.0991000.3720.3100.3181.08910000.3420.3290.3291.0981000000.3340.3330.3331.099可以看到策略逐漸逼近純均衡并穩(wěn)定熵也穩(wěn)定在最大值附近。這其實(shí)符合直覺剪刀石頭布沒有純策略優(yōu)勢任何偏離均勻分布的策略都會被對手針對所以算法最終選擇最大限度隨機(jī)化。4.3 從離線矩陣到真實(shí)交互系統(tǒng)上線后的觀察離線仿真做得好不代表真實(shí)環(huán)境一定行。真正把Matrix-Game接入交互系統(tǒng)后我發(fā)現(xiàn)了幾個離線階段完全沒暴露的問題。第一收益矩陣不是恒定的。在真實(shí)對局里對手風(fēng)格會變化規(guī)則也可能受隨機(jī)因素影響固定的收益矩陣無法覆蓋所有情況。我的做法是把收益矩陣設(shè)計成可更新的參數(shù)每輪結(jié)束后根據(jù)真實(shí)結(jié)果做小幅度修正。第二真實(shí)交互有延遲約束。離線跑十萬次迭代沒問題線上必須在毫秒級給出決策所以線上版本會用提前算好的近似策略再用快速在線更新做微調(diào)。第三對手不是完全理性的。這一點(diǎn)最容易被忽略納什均衡假設(shè)雙方完全理性但真實(shí)對手經(jīng)常有偏差行為。后來我給系統(tǒng)加了一個對手模型模塊用對手的歷史動作去估計它當(dāng)前策略再針對性地調(diào)整我方響應(yīng)。這些調(diào)整讓Matrix-Game從一個純粹的均衡求解器變成了更貼近實(shí)際博弈環(huán)境的自適應(yīng)系統(tǒng)。5. 性能優(yōu)化與避坑記錄矩陣化路上的真實(shí)問題5.1 矩陣規(guī)模膨脹什么時候該上GPU或低秩近似矩陣化的一個直接難題是規(guī)模爆炸。收益矩陣是n行m列當(dāng)每個玩家的可選動作數(shù)量到幾千甚至幾萬時完整的密集矩陣幾乎存不下來。我的經(jīng)驗(yàn)是分三檔處理。n和m在一百以內(nèi)直接用密集矩陣加NumPy速度足夠。n和m在幾千時優(yōu)先考察稀疏性大多數(shù)真實(shí)博弈中收益矩陣并不稠密很多動作組合不會出現(xiàn)可以用稀疏矩陣存儲計算時只處理非零元素。n和m超過一萬甚至更高時稀疏矩陣也可能撐不住必須引入低秩近似或者用神經(jīng)網(wǎng)絡(luò)參數(shù)化策略此時矩陣乘法變成小批量采樣和嵌入式運(yùn)算。一條非常實(shí)用的規(guī)則不要一開始就上GPU。很多矩陣規(guī)模在CPU上用向量化NumPy就夠快了GPU的傳輸開銷反而拖慢整體。等確認(rèn)瓶頸確實(shí)在矩陣乘法本身再遷移不算遲。5.2 數(shù)值穩(wěn)定性小概率策略被清零的麻煩遺憾匹配里有一個隱蔽的坑當(dāng)某個動作的累積遺憾長期為負(fù)時正部截斷會把它變成絕對的零概率導(dǎo)致該動作再也沒有機(jī)會被選中。這在動態(tài)環(huán)境中是致命的——對手策略一變之前被淘汰的動作可能是新的最優(yōu)解。我踩過這個坑后在代碼里加了最小概率約束每次歸一化前對所有動作施加一個epsilon下限保證策略向量始終完全混合。這個做法會輕微偏離純均衡但在實(shí)際系統(tǒng)中換來了更強(qiáng)的適應(yīng)能力值得付出這點(diǎn)偏差。另一個數(shù)值問題是浮點(diǎn)精度。迭代十萬輪之后累積遺憾的值域可能非常大float32很容易溢出或損失精度。Matrix-Game里我統(tǒng)一要求用float64存累積量策略向量本身用float32這樣既保證穩(wěn)定又不會太浪費(fèi)內(nèi)存。5.3 從單機(jī)到并行異步矩陣更新的思路博弈系統(tǒng)往往需要同時模擬大量對局來加速學(xué)習(xí)。單個進(jìn)程串行跑遺憾匹配效率低得很明顯。我后來做了異步并行改造多個工作進(jìn)程各自維護(hù)一分策略矩陣獨(dú)立模擬對局定期把計算出的遺憾量增量同步到中央策略矩陣。這個做法的本質(zhì)是在矩陣空間做隨機(jī)近似。每個進(jìn)程相當(dāng)于從完整對局分布里做一批采樣中央矩陣做一次小步長更新然后再分發(fā)給各進(jìn)程繼續(xù)模擬。到這里Matrix-Game和分布式深度強(qiáng)化學(xué)習(xí)的思路已經(jīng)非常接近了——只不過底層變量從網(wǎng)絡(luò)參數(shù)換成了策略矩陣和收益矩陣。不過說實(shí)話異步并行并不適合所有場景。如果對局模擬本身很快進(jìn)程間同步的開銷可能超過并行帶來的收益。我現(xiàn)在的建議是先跑通串行版本確認(rèn)收斂性質(zhì)沒問題再考慮并行。沒有穩(wěn)定的單機(jī)實(shí)現(xiàn)分布式只會放大錯誤。我自己在實(shí)際項目里最深的體會是矩陣化不是炫技它是一種讓復(fù)雜博弈問題變得可調(diào)試、可量化、可擴(kuò)展的思維方式。當(dāng)你把所有策略、狀態(tài)和收益都裝進(jìn)矩陣你會發(fā)現(xiàn)自己不再和一堆模棱兩可的規(guī)則搏斗而是在和明確的數(shù)字打交道——這種感覺對做系統(tǒng)的人來說遠(yuǎn)比堆功能要踏實(shí)得多。最后分享一個小技巧不管用什么算法第一版的時候就把收益矩陣和策略向量打印出來用終端或簡單圖表觀察每輪的演化過程。這比盯著loss曲線直觀得多很多時候你一眼就能看出策略是卡在局部還是正在朝均衡方向收斂。把這一步做好后面調(diào)參的時間能省下一大半。