1. 程式人生 > >遊戲AI之模糊邏輯(4)

遊戲AI之模糊邏輯(4)

采樣 子彈 jpg 均值 與運算 只需要 保持平衡 復雜 判斷

if(condition)
  then dosomething...

這次主要圍繞的是遊戲AI該如何模仿人類地判斷條件(condition)。

人類的邏輯

人類的邏輯思考是復雜的,模糊的。

一些人類邏輯思考的例子:“把面包切成中等厚度”,“這波我很強”,“你好騷啊”,“小A有點高”....

而對於計算機,它只認識離散的數值:
假設在一個問題中,智商劃分了3個集合:笨拙 = {70~89},平均 = {90~109},聰明 = {110~129}
如果比較一個智商89的人和智商90的人,則但因為計算機很難識別這些模糊的概念(“中等厚度”,“很強”,“好騷”,“笨拙”..),
所以只能根據普通集合得到結論是:89那人是笨拙的,而90那人不是。

這顯然有點不符合人類的邏輯。
為了讓計算機也能有類似人類的模糊邏輯,引入了模糊集合這個概念。

模糊變量

在介紹模糊集合之前,先介紹它的基本構成——模糊變量。

隸屬函數

模糊變量是由若幹個屬性代表的隸屬函數定義的,y值為隸屬度,隸屬度範圍為[0,1]。
當某個屬性的隸屬度越高,則說明該變量越接近這個屬性。

例如IQ是一種模糊變量:IQ = {笨拙,平均,聰明},由三個隸屬函數(分別代表藍線,橙線,灰線)定義邊界。

技術分享圖片

當某個人的IQ為95時,它對"笨拙”的隸屬度為0.25,對"平均"的隸屬度為0.75,對“聰明”的隸屬度為0

技術分享圖片

隸屬函數除了上面這種形狀,也可以有其他函數形狀:

技術分享圖片

此外,需要註意的是,模糊邏輯規定,對模糊變量的任意X值,所有隸屬函數值之和應等於1。

限制詞

使用限制詞可以修飾一個隸屬函數的形狀,變成一個新的隸屬函數。
主要有兩種修飾:

  • “非常”:FVery(x) = F(x)2
  • “有點”:FFairly(x) = √F(x);

當我們需要在IQ這個模糊變量需要“非常聰明”的隸屬函數時,
可以直接引用“非常”修飾詞來修飾“聰明”的隸屬函數。

在之前的例子中,
“非常笨拙”的隸屬度 = “笨拙”的隸屬度的平方 = 0.25^2 = 0.0625。

模糊集合

模糊集合則是1~n個模糊變量構成的集合,而這些集合一般都是用來進行一些運算獲得新的集合。

例如:“聰明”取反運算即是“不聰明”的集合;“高”和“聰明”的與運算即是又“高”又“聰明”的集合。

模糊集合運算符

  • OR或 : F1(x) OR F2(y)= max{F1(x),F2(y)}

  • AND與 : F1(x) AND F2(y) = min{F1(x),F2(y)}

  • NOT反 : F(x)‘ = 1-F(x)

在計算集合的具體隸屬度的時候,便使用上面運算規則來計算隸屬度。

例如:當“高”的隸屬度為0.7,“聰明”的隸屬度為0.5,則“高”AND“聰明”的隸屬度應為min{0.7,0.5} = 0.5

模糊規則

在引入模糊集合後,現在可以根據模糊集合來制定模糊規則。

這裏不做定義闡述,就用舉例直接理解模糊規則:

舉例,有一個模糊集合:

技術分享圖片

技術分享圖片

  • 模糊變量1:敵人距離 = {近,中,遠}
  • 模糊變量2:子彈數量 = {低,合適,超載}

其中制定了4條模糊規則:

  • 規則1:if(子彈數量低 AND 敵人距離遠)then 不期望攻擊
  • 規則2:if(子彈數量低 AND 敵人距離中)then 不期望攻擊
  • 規則3:if(子彈數量低 AND 敵人距離近)then 期望攻擊
  • 規則4:if(子彈數量合適 AND 敵人距離近)then 非常期望攻擊

通過規則,我們能夠計算出每條規則中條件的隸屬度,然後歸納為期望結果的隸屬度:

  • 規則1中:不期望攻擊的隸屬度 = “子彈數量低” AND “敵人距離遠” 的隸屬度
  • 規則2中:不期望攻擊的隸屬度 = “子彈數量低” AND “敵人距離中” 的隸屬度
  • 規則3中:期望攻擊的隸屬度 = “子彈數量低” AND “敵人距離近” 的隸屬度
  • 規則4中:非常期望攻擊的隸屬度 = “子彈數量合適” AND “敵人距離近” 的隸屬度

模糊推理

假設當前敵人距離是12.5,子彈數量是7.5。

  • 敵人距離近的隸屬度 = 0.5
  • 敵人距離中的隸屬度 = 0.5
  • 敵人距離遠的隸屬度 = 0
  • 子彈數量低的隸屬度 = 0.25
  • 子彈數量合適的隸屬度 = 0.75
  • 子彈數量超載的隸屬度 = 0

由此計算每條規則的期望結果的隸屬度:

  • 規則1:不期望攻擊的隸屬度 = 0
  • 規則2:不期望攻擊的隸屬度 = 0.25
  • 規則3:期望攻擊的隸屬度 = 0.25
  • 規則4:非常期望攻擊的隸屬度 = 0.5

對於同種結果的隸屬度,我們一般使用或運算進行合並隸屬度。

得到隸屬度結果:
不期望的隸屬度 = 0.25,期望的隸屬度=0.25 ,非常期望的隸屬度 = 0.5

然後我們還得另外準備一個模糊變量:期望變量
技術分享圖片

修剪:將形狀中限制在隸屬度結果的線下
技術分享圖片

通過修剪的方法將期望集合和這些隸屬度結果合成為一個新的模糊形狀:

技術分享圖片

這就是我們的推理結論。

去模糊化

最後一步就是去模糊化,把模糊推理之後得到的形狀結果變成一個具體準確的值(到底是做這個動作還是不做)。

最大值平均

最大值平均是一種去模糊化的方法:去模糊化的輸出值 = 最大隸屬度的形狀的平均值。

在上面的例子,0.5隸屬度為最大隸屬度,其形狀(非常期望形狀)的平均值為0.4375,所以它輸出期望值:0.4375

中心法

中心法是一種最準確的去模糊化方法,但也是最復雜的計算方法:輸出值 = 形狀的中心值,
所謂中心也就是把它放在一把尺子上能保持平衡的位置。

一般的,它使用采樣方法來獲取近似中心值:
在X軸上平均分布N個點進行采樣,計算再每個采樣點對總體隸屬度的貢獻之和,再除以采樣的隸屬度之和。
N越大,其結果越準確。

如圖,對9個點進行采樣:
技術分享圖片

技術分享圖片

計算出輸出期望值:

(0*0.25+12.5*0.25+25*0.25+37.5*0.25+37.5*0.5+50*0.25+62.5* 0.75+75*0.5+87.5*0.5+100*0.5)/(0.25+0.25+0.25+0.5+0.25+0.75+0.75+0.75+0.75)
= 50.6944

庫博方法

可以看到,在制定模糊規則的時候一個主要問題是隨著模糊變量的增加,其規則數量則以指數級的速度增加。

假設每個模糊變量有3種屬性。一個有3個模糊變量的模糊集合,完整的規則應該是有9個規則。而對於5個模糊變量的模糊集合,就已經需要125個規則了。更別說更多模糊變量..

庫博方法的工作原理也很簡單,只需把變量的復合(一般是指和運算)拆分成單個變量的規則:

  • if("聰明"和“長”)then 非常期望
  • if("聰明"和“中”)then 非常期望
  • if("聰明"和“短”)than 期望
  • if("平均"和“長”)than 非常期望
  • if("平均"和“中”)than 期望
  • if("平均"和“短”)than 期望
  • if("笨拙"和“長”)than 期望
  • if("笨拙"和“中”)than 期望
  • if("笨拙"和“短”)than 不期望

可以拆分為:

  • if("聰明")then 非常期望
  • if("平均")than 期望
  • if("笨拙")than 不期望
  • if(“長”)than 非常期望
  • if(“中”)than 期望
  • if(“短”)than 不期望

對於N個變量,用一般方法需要O(N2)個規則,庫伯方法則只需要O(N)個規則。

雖然上這種拆分表面上看對原規則語義幾乎是顛覆,
但是實際實驗結果,用庫博方法計算出來的期望值與一般方法計算出來的期望值相差不多。
當使用大的規則庫時,犧牲部分準確性而使用庫博方法絕對是值得的。

結語

實際上對AI的行為使用一定範圍的隨機數而不是模糊邏輯也是可行的,
但是可能會偶爾導致一些愚蠢的行為,除非反復驗證並確定好隨機數範圍從而保證不會出現意外的愚蠢。

意外的愚蠢例如:一個中立的NPC因為隨機到了某個仇恨值,有時可能會對主動攻擊玩家,有時該攻擊時卻不主動攻擊,這顯然是不對的。
但是利用模糊邏輯,它能根據各種潛在因素(玩家的犯罪記錄,聲譽,距離,衣著魅力等等)而不是隨機因素來確定仇恨值,從而達到更加逼真的攻擊行為。

遊戲AI之模糊邏輯(4)