GFS(Genetic Fuzzy Systems)—— 基于专家先验规则库和遗传算法相结合的智能体决策算法
文章目錄
- 1. FIS 系統(tǒng)(Fuzzy Inference Systems)
- 1.1 什么是 FIS 系統(tǒng)?
- 1.2 使用 FIS 算法的幾個步驟
- 2. GFS 系統(tǒng)(GA + FIS)
- 2.1 什么是基因遺傳算法(GA)?
- 2.2 使用GA算法進化FIS規(guī)則庫
在大規(guī)模的多智能體集群協(xié)同任務中,DRL往往很難取得較好的效用。一旦智能體數(shù)目規(guī)模變大,聯(lián)合行為空間和聯(lián)合觀測空間規(guī)模就會變得巨大無比,因此在許多大規(guī)模的多智能體協(xié)同任務中,基于規(guī)則的控制器是解決規(guī)模龐大問題的一個有效的方法。但基于規(guī)則的方法缺陷在于:面對一個陌生場景下人們往往很難以制定出一套較好的規(guī)則庫,這里的規(guī)則是指在 “什么樣的情況下” Agent 應該采取什么樣的 “行為”,其中 “情況” 和 “行為” 在大多數(shù)情況下我們都能夠較為容易的獲得,但 “情況-行為” 的規(guī)則映射是難以事先確定的。為此,人們想到可以預先定義一些隨機的規(guī)則,通過遺傳算法來嘗試對這些規(guī)則進行重組,通過查看新規(guī)則在場景中的得分,摒棄低得分的規(guī)則,保留高得分的規(guī)則,最終自我學習出一套較為完備的規(guī)則庫,這就是 GFS 的由來。
【參考連接】:GFS原理鏈接,FIS代碼包鏈接。
1. FIS 系統(tǒng)(Fuzzy Inference Systems)
1.1 什么是 FIS 系統(tǒng)?
FIS(Fuzzy Inference Systems)的全稱是模糊推理系統(tǒng),其主要作用是對變量做 “模糊化” 和 “去模糊化”(參考資料:這里)。那么什么是模糊化和去模糊化?這里用一個例子作為引入:假設你是一個應屆畢業(yè)生,現(xiàn)在需要選擇一個工作,那么你在挑選工作的時候可能會有這么幾個標準:
現(xiàn)在有幾家 offer 擺在了你面前,工作時長和薪資待遇都開放給你,你需要設計一個系統(tǒng)來幫你選擇去哪一家公司,你該如何讓計算機來理解你的標準呢?你該怎么樣讓計算機明白薪資多少算是 “高”,多少工作時長才算 ”長“?其實這里的 “薪資高” 和 “時長少” 都是人們內(nèi)心的主觀概念,人們也很難具體說出一個具體的數(shù)字,只能根據(jù)一個具體的數(shù)字來大致判斷這個數(shù)字是 “多” 還是 “少”,這就是 “模糊邏輯” 的概念,即將一個連續(xù)變量的值做模糊化,使其具體的數(shù)值被模糊為一個程度值。這里可以簡單理解為將一個具體的數(shù)值做分類,其被分類為 “少”、“中”、“多” 三類中的哪一類(真實得到的輸出是這個值被分為這三類分別的置信度是多少,這和 softmax 函數(shù)的概念很像,如果不能理解就簡單理解為歸類為著三類中的其中一類就行了)。
因此,FIS 的核心思想就在于:將連續(xù)變量模糊化,根據(jù)既定的規(guī)則得到一個模糊化的行為,最終再將這個行為去模糊化。 注意,通過模糊化后推理出的行為也是一個模糊變量,拿上面的例子來說,在薪資高工作時長一般的時候,所采取的行為是 “優(yōu)先考慮”,代表你很愿意去選擇這個工作,“愿意程度” 其本質(zhì)也應該是一個模糊變量,最終具體選擇這個工作與否需要你自己根據(jù) “愿意程度” 來作參考進行選擇,這個過程就叫做 “去模糊化”。
1.2 使用 FIS 算法的幾個步驟
使用 FIS 算法做推理包含以下幾個關鍵性的步驟:
以上 4 步是使用 FIS 算法最基本的 4 個步驟,下面將結合上面說到的找工作例子,使用 FIS 模糊推理來根據(jù)不同 offer 的薪資和工作時長來決定是否接受這個 offer。
- 輸入變量模糊化(分配隸屬函數(shù))
我們之前提到,對于一個輸入變量具體值,我們需要對其進行模糊化,使其變?yōu)?“程度變量”,隸屬函數(shù)的作用就是用來表征一個具體變量值屬于“高”、“中”、“低”三種程度的置信度。我們假設給定薪資范圍為:20 ~ 32(w),工作時長為:6 ~ 12(小時),我們畫出這兩個變量的隸屬函數(shù)圖像:
其中,“poor”、“average”、“good” 分別代表 “低”、“中”、“高” 三種不同的程度,隸屬函數(shù)就是這個三角形的函數(shù)。怎么根據(jù)隸屬函數(shù)來判斷一個具體的薪資值屬于哪一種程度呢?我們看這個圖的縱坐標,這是一個 0 ~ 1 的取值,y 軸的值就是代表這個值屬于這個程度的“置信度”。舉例來說,我們看橫坐標為 26 的點,這個橫坐標對應的黃色線(average)的 y 值取值為 1,這代表 26w 的年薪在整個年薪區(qū)間中屬于 “薪資中等” 這一個程度。我們現(xiàn)在換一個不這么特殊的點,當橫坐標為 24 的時候,藍線(poor)和黃線(average)都會有其對應的 y 值,藍線取值大概在 0.4 左右,黃線取值大概在 0.6 左右,這意味著 24w 的薪資有 0.4 的置信度被認為是 “薪資低”,0.6 的置信度被認為是 “薪資中等”。因此,通過隸屬函數(shù)我們能夠輕松的將一個輸入的 “具體值” 映射到一個 “程度” 上,這就是輸入變量的模糊化。 工作時長的隸屬函數(shù)也是同理,這里直接放上結果圖,不再做分析:
- 制定推理規(guī)則(根據(jù)輸入值推斷行為動作)
至此,我們已經(jīng)成功將輸入變量模糊化了,接下來我們需要制定規(guī)則,即在什么情況下采取什么樣的行為。參照 1.1 中提到的 4 條規(guī)則,這里我們把這些規(guī)則變成 FIS 算法內(nèi)部需要的規(guī)則格式。在 FIS 算法中,一條規(guī)則長這個樣子:
If "薪資高" and "工作時長少" Then "很愿意接受這份工作"可以看出來,在 FIS 算法內(nèi)部,規(guī)則由 “規(guī)則前件” + “行為后件” 組成,即 If 后面到 Then 之前的部分為規(guī)則前件,由多個模糊變量組成,各模糊變量之間由邏輯運算符 and 或者 or 連接;Then 之后為行為后件,代表在這樣的規(guī)則下應該采取哪一個行為。邏輯運算符 and 和 or 用于表示各模糊變量之間的關聯(lián)關系,這里的 and 和 or 和平時理解的稍有不同,平時 and 和 or 都是 0 和 1 之間運算,即 1 and 0 = 0,1 or 0 = 1。在 FIS 中,模糊變量的取值并不是非 0 即 1(因為是置信度),而是有可能為一個 float 值(0 ~ 1之間),因此這里的 and 指取兩個變量值中的最小值,or 指取兩個變量值中的最大值。(Example:0.8 and 0.2 = 0.2;0.7 or 0.4 = 0.7)
我們把上面的 4 條規(guī)則全部列舉出來,形成該問題下的 “規(guī)則庫”:
If "薪資高" and "工作時長少" Then "很愿意接受這份工作" If "薪資高" and "工作時長中等" Then "中等愿意接受這份工作" If "薪資中等" and "工作時長很長" Then "中等愿意接受這份工作" If "薪資低" Then "不怎么愿意接受這份工作"這樣我們就能根據(jù)一組模糊變量來推得一個行為的模糊變量,即接受這份工作的 “愿意程度”。
- 行為模糊變量推理,行為變量去模糊化
至此輸入模糊化和規(guī)則庫都已經(jīng)定義好了,我們現(xiàn)在就可以根據(jù)一組具體的輸入數(shù)據(jù)來推理出行為模糊變量了,我們這里舉例薪資為 22w,工作時長為 8 小時,輸入該系統(tǒng)會得到怎么樣的推理。首先對輸入薪資 22w 進行模糊化,通過查看隸屬函數(shù),我們能夠發(fā)現(xiàn) 22w 屬于 “較少程度” 的類型,且置信度為 0.64 左右:
再對 worktime 做模糊化,可以得到 8 個小時的工作時間屬于 “中等程度”,且置信度為 0.66 左右:
這樣我們就分別得到了 worktime 和 salary 的所屬程度類別以及他們的置信度,此時我們?nèi)ヒ?guī)則庫中尋找對應的規(guī)則:薪資為 “少” 且工作時長為 “中等” 的規(guī)則,通過查找與上述最后一條規(guī)則匹配:
If "薪資低" Then "不怎么愿意接受這份工作"因此我們所采取的行為應該是 “不怎么愿意接受這份工作”,但我們之前說到,這個推理出的行為變量同樣是一個 “模糊變量”(程度變量),代表著接受這個工作的 “愿意程度”。那么怎么去確定這個變量的置信度(這里可以理解為愿意程度)呢?這里就需要引入 “strength” 的概念,即 “置信強度 ” 的概念。其實這個值很好計算,如果規(guī)則是 A and B,那 strength 就等于 A 的置信度和 B 的置信度中較小的那一個,如果規(guī)則是 A or B,則取兩者置信度較大的即可。由于這里我們定義只要 “薪資低” 就不用考慮這個工作了,所以這里 strength 就等于薪資低的置信度 0.64,“接受行為” 的模糊變量隸屬函數(shù)如下:
我們 strength 值(0.64)去對相應的行為程度(規(guī)則中是 “不大愿意接受”)進行截取,截取后我們就可以得到一個輸出分布(Output Distribution),圖中淺藍色填充的部分就是輸出分布。如何去根據(jù)輸出分布確定行為的模糊程度值呢(去模糊化)?這里有兩種方法:Mean of Maximum(mmo)法、Center of Mass(com)法。
mmo 法是指找到被截區(qū)域最高的直線部分,取直線中點橫坐標作為行為去模糊化后的值,如下圖所示:
com 法是指取被截區(qū)域的質(zhì)心,將質(zhì)心點的橫坐標作為行為去模糊化后的值,如下圖所示:
在我給的例子中我選用的是 com 質(zhì)心法,可以看到去模糊化后 “愿意接受” 變量的行為值為 2.1 左右。
- 得到具體行為
現(xiàn)在我們已經(jīng)拿到了行為的 “愿意程度值” 了,現(xiàn)在要參考這個值作為行為決策了。這個部分的自由度就比較高了,你可以按照你自己的想法來進行行為決策,例如這里我將愿意程度范圍取值為 [0, 12],而最后可采取的行為只有 “接受” 和 “不接受”,因此我定義 “當愿意程度小于 6 則不接受”,“愿意程度大于 6 則接受”,上述例子中的行為值只有 2.1,因此選擇不接受該 offer。
- 一些特殊情況
紅色劃線部分為最終的聯(lián)合輸出分布,行為的橫坐標為劃線部分的質(zhì)心點橫坐標。上述例子的薪資輸入為 30w,工作時長為 8 小時,通過規(guī)則推理 “高薪資” + “一般工作時長” = “中等愿意接受工作”,可見 FIS 最終計算出的 accept 行為的去模糊值也落在 6.1,正好是 “中等愿意接受” 的范圍,和我們的預期相符。
- 實現(xiàn)代碼
上述代碼實現(xiàn)如下,代碼中使用了模糊推理運算三方庫 skfuzzy,安裝命令:
pip install -U scikit-fuzzy具體安裝細節(jié)和 API 相關見:這里。
""" @author: P_k_y """import skfuzzy as fuzz import numpy as np from skfuzzy import control as ctrlACTION_RANGE_MIN = 0 ACTION_RANGE_MAX = 13def main():# define fuzzy variablesalary = ctrl.Antecedent(np.arange(20, 33, 1), 'salary')worktime = ctrl.Antecedent(np.arange(6, 13, 1), 'worktime')# define fuzzy actionaccept = ctrl.Consequent(np.arange(ACTION_RANGE_MIN, ACTION_RANGE_MAX, 1), 'accept')# define the membership functionsalary.automf(3)worktime.automf(3)accept.automf(3)salary.view()worktime.view()# define the rulesrule1 = ctrl.Rule(salary["good"] & worktime["poor"], accept["good"])rule2 = ctrl.Rule(salary["good"] & worktime["average"], accept["average"])rule3 = ctrl.Rule(salary["average"] & worktime["good"], accept["average"])rule4 = ctrl.Rule(salary["poor"], accept["poor"])# define the simulationaccept_actor_ctrl = ctrl.ControlSystem([rule1, rule2, rule3, rule4])accept_actor = ctrl.ControlSystemSimulation(accept_actor_ctrl)# compute the final resultaccept_actor.input["salary"] = 30accept_actor.input["worktime"] = 8accept_actor.compute()print("How much would like to accept this offer: %.2f%%" % (float(accept_actor.output['accept']) / (ACTION_RANGE_MAX - 1) * 100))accept.view(sim=accept_actor)salary.view(sim=accept_actor)worktime.view(sim=accept_actor)if __name__ == '__main__':main()2. GFS 系統(tǒng)(GA + FIS)
2.1 什么是基因遺傳算法(GA)?
GA(Genetic Algorithm)算法是一種仿生學算法,其仿照生物進化時基因通過不斷重組和變異,優(yōu)勝劣汰,最終生存下來的都是優(yōu)秀的基因群組的原理。當我們現(xiàn)在有一堆規(guī)則的時候,我們并不能保證這些規(guī)則中定義在一種 “情況” 下采取某種 “行為” 是最優(yōu)的,因此我們可以考慮使用遺傳算法,將規(guī)則中的不同 “情況” 和不同 “行為” 做重組形成新的規(guī)則,最后按照這些新規(guī)則的表現(xiàn)好壞來決定保留或是摒棄這些新產(chǎn)生的規(guī)則。在有些很復雜的場景下,我們無法為規(guī)則庫中的每一條規(guī)則手動賦予對應行為,因此一般來說我們會為每一種 “情況” 隨機賦予一個 “行為”,再通過遺傳算法來學習到一個 “情況” 下所對應的最高效用的 “行為”。
我們還是拿找工作的例子來做說明,薪資待遇有高、中、低三種等級,工作時長同樣有高、中、低三種程度等級,則這兩個模糊變量做組合一共可以得到 3 * 3 = 9 條規(guī)則,因此一個完整的規(guī)則庫應該包含 9 條規(guī)則:
If "薪資高" and "工作時長長" Then ... If "薪資高" and "工作時長中等" Then ... If "薪資高" and "工作時長少" Then ... If "薪資中等" and "工作時長長" Then ... If "薪資中等" and "工作時長中等" Then ... If "薪資中等" and "工作時長短" Then ... If "薪資短" and "工作時長長" Then ... If "薪資短" and "工作時長中等" Then ... If "薪資短" and "工作時長短" Then ...規(guī)則前件的組合我們可以通過窮舉列出來,但是所對應的行為怎么辦呢,我們無法為每一個規(guī)則前件都賦予一個適合的動作行為,因此通常來說我們都可以隨機初始化這些前件對應的動作值,在這個例子中我們 “愿意接受offer” 模糊變量同樣也有高、中、低三個程度,我們用數(shù)字 0、1、2 來分別代替這3個行為變量,于是初始規(guī)則庫變?yōu)榱?#xff1a;
If "薪資高" and "工作時長長" Then 0 If "薪資高" and "工作時長中等" Then 1 If "薪資高" and "工作時長少" Then 1 If "薪資中等" and "工作時長長" Then 0 If "薪資中等" and "工作時長中等" Then 2 If "薪資中等" and "工作時長短" Then 1 If "薪資短" and "工作時長長" Then 2 If "薪資短" and "工作時長中等" Then 0 If "薪資短" and "工作時長短" Then 0011021200 就代表了規(guī)則庫策略,因為規(guī)則前件的順序是不變的,因此這一串數(shù)字就是我們的規(guī)則庫策略,能夠根據(jù)一中特定情況來選擇一個行為。但是這個數(shù)字串是我們隨機生成的,并不具有好的策略效用,因此我們需要通過遺傳算法來對這串數(shù)字串進行進化,從而得到一個具有較高得分的規(guī)則庫策略。
2.2 使用GA算法進化FIS規(guī)則庫
使用 GA 算法優(yōu)化 FIS 規(guī)則庫通常包括以下幾個步驟:
- 建立初始規(guī)則染色體群(population)
一個染色體群 population 中包含多條規(guī)則染色體,其中規(guī)則染色體是指一個具體的規(guī)則策略,2.1中提到的 “011021200” 就是一條規(guī)則染色體,其代表了一個具體的規(guī)則策略。初始的 population 中會包含多條 chromosome,一般都是通過隨機生成來得到的,chromosome 的長度為規(guī)則庫中所有規(guī)則的數(shù)目總和(該示例中為 9 ),例如一個 size 為 5 的 population 如下:
011021200 222010120 010201020 111020012 210120120- 進化規(guī)則染色體群
初始的染色體群是我們隨機生成的,里面的每一條規(guī)則染色體都不一定具有較好的效用,因此我們需要對該群組進行進化訓練,進化訓練一共分為以下 3 個步驟:選擇下一代父染色體群(select)、染色體交叉重組(cross)、染色體變異(mutate)。
由于染色體進化是一輪一輪迭代的,因此在下一輪進化迭代時我們需要選擇保留這一輪中哪些優(yōu)秀的染色體到下一輪。這和 “優(yōu)勝劣汰” 的思路很像,我們將這一代中那些得分高的規(guī)則染色體按較高概率保留到下一代中去,將那些得分低的規(guī)則染色體按照較低的概率保留,其中規(guī)則染色體的 “得分” 是通過將這個規(guī)則染色體應用到實際問題中去運行得到的反饋回報。例如,011021200 這個染色體中,對于 “薪資高” 且 “工作時長短” 這一個情況選擇的是 “不太愿意接受這個 offer” 這個行為,那很明顯你會覺得這是一個很差的行為決策,因此你會給這條規(guī)則染色體一個很低的得分,以表示這個規(guī)則是很差的規(guī)則,盡量不要保留到下一代 population 中去。具體示例如下:
當代染色體群:011021200 -> 0.82 score 222010120 -> 0.22 score010201020 -> 0.35 score111020012 -> 0.19 score210120120 -> 0.08 score下代父染色體群:011021200 (0.82 )011021200 (0.82 )010201020 (0.35 )011021200 (0.82 )222010120 (0.22 )上面展示了一個具體的例子,上半部分 -> 后代表的是當代的當前染色體得分,下半部分()內(nèi)是該染色體在上代染色體群中的得分。可以看出,當代染色體群中得分越高的染色體越有較高的概率被保留到下一代中去。
染色體交叉重組是指一個 population 中相鄰的兩條染色體之間進行交叉重組,從而得到新的規(guī)則染色體。交叉重組過程首先會隨機在染色體中隨機選擇一個點作為交換切斷點,兩條染色體交換被切斷點切斷的染色體片段,具體示例如下:
交叉前:01102 1200 # chromosome 1,切斷點 index 為 5 ( 1 條規(guī)則染色體被分為 2 段)22201 0120 # chromosome 2,切斷點 index 為 5 ( 1 條規(guī)則染色體被分為 2 段)交叉后:22201 1200 # 新的子代 chromosome 1(與另一染色體交換了第 1 個染色體片段)01102 0120 # 新的子代 chromosome 2(與另一染色體交換了第 1 個染色體片段)染色體變異是指在一條染色體上的某一個位置上的基因發(fā)生突變,基因突變分為前向突變與后向突變,首先隨機選擇一個突變切斷點,前向突變指切斷點前面的基因全部隨機突變成另一個行為值,后向突變指切斷點以后的基因全部隨機突變?yōu)榱硪粋€行為值,例如:
突變前:01102 1200 # 切斷點 index 為 5 ( 1 條規(guī)則染色體被分為 2 段)前向突變:10201 1200 # 前向突變子代 chromosome(突變斷點前的基因均重新隨機取值)后向突變:01102 2012 # 后向突變子代 chromosome(突變斷點后的基因均重新隨機取值)- 保存最優(yōu)規(guī)則策略
在完成了若干輪的進化后,通過篩選出該 population 中得分最高的一條 chromosome 即可得到最優(yōu)規(guī)則策略。在設定進化輪數(shù)的時候,我們可以使用閾值限定的方法,查看在一輪中最高得分的規(guī)則染色體得分是否到達了我們設置的閾值點,如果已有染色體滿足了我們設置的得分閾值即可停止進化,并保存滿足得分的規(guī)則染色體作為最終策略。
至此,這就是對 GFS 系統(tǒng)的全部內(nèi)容講解了,完整 GFS 代碼可以參見 我的GitHub。
總結
以上是生活随笔為你收集整理的GFS(Genetic Fuzzy Systems)—— 基于专家先验规则库和遗传算法相结合的智能体决策算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DeepMind 的马尔可夫决策过程(M
- 下一篇: js 月份加6个月_美国切削工具6月份订