1. 程式人生 > >人工智慧第三章(1)——無資訊搜尋(盲目搜尋) (附書本資料)

人工智慧第三章(1)——無資訊搜尋(盲目搜尋) (附書本資料)

摘要

本章旨在講清楚:1)搜尋問題如何形式化;2)樹搜尋,圖搜尋,及演算法評估;3)一些搜尋策略:寬度優先,一致代價,深度優先,深度受限,迭代加深,雙向搜尋。

前言

這一章說的是Agent,但是是搜尋Agent,所以主要講的是各種搜尋演算法(search algorithms)。

這篇文章的意義在於哪裡呢?
1)向大家展示如何形式化定義一個搜尋問題,又如何去求解;
2)通過講述各種盲目搜尋演算法,幫大家梳理無資訊搜尋的脈絡。

不多說了,得進入正題了。

一、形式化一個搜尋問題

1.1 問題的定義 [1]

用5個元件形式化定義一個search problem:
1)initial state 初始狀態
2)Actions 行動
3)transition model 轉移模型
4)goal test 目標測試
5)path cost 路徑耗散

前三個直接定義了問題的狀態空間(問題的解決方案通常就在這個狀態空間裡面)。

上述五個元素即定義了一個問題,通常把它們組織在一起成為一個數據結構,並以此作為問題求解演算法的輸入。

1.2 問題的解(solution)的定義

A solution to a problem is an action sequence that leads from the initial state to a goal state.

即:一個問題的解是:一個行動序列(注意:agent是能夠通過感知環境,進行思考,然後採取行動的,所以這篇文章的題目叫搜尋Agent)。

那最優解是什麼呢?
答:解的質量由路徑耗散函式度量,所有解里路徑耗散最小的解即為最優解。

1.3 為什麼要搜尋演算法?

因為狀態空間太大啦。比如,8數碼問題有362,880(排列組合,A98=362,880)個狀態,15數碼問題有A1615=20922789888000個狀態,24數碼就更加更加大了。

所以我們需要搜尋演算法(相當於一種求解模式吧,比那種“無頭蒼蠅”式的隨便找解的 是要好得多的。)來在巨大狀態空間中求解。

二、如何通過搜尋求解呢(主要講樹搜尋和圖搜尋)?

以羅馬尼亞問題(即:如何從羅馬尼亞的Arad走到Bucharest)為例,可能的行動序列(即問題的解)從搜尋樹中根節點的初始狀態出發:連線表示行動,節點表示狀態空間中的狀態(該問題總共20個地點,故有20個狀態)。搜尋的過程就是從初始狀態節點不斷擴充套件節點(狀態),指導goal test檢測到達到目標為止。

那麼,如何選擇將要擴充套件的狀態,對應的就是搜尋策略(圖搜尋,樹搜尋)了。這裡給出圖搜尋和樹搜尋的非形式化描述:

圖搜尋和樹搜尋的非形式化描述

解釋:對於樹搜尋,先從初始節點開始擴充套件,初始化邊緣(frontier,即待擴充套件的葉節點的集合),如果邊緣為空,就失敗唄(因為沒有能夠擴充套件的節點了,自然GG),否則,從邊緣中選擇一個葉節點並且並且把它從邊緣移除,如果這個葉節點包含目標狀態,那就返回對應的解。否則,擴充套件這個葉節點,並且把擴展出來的節點放到邊緣中(不斷探索可能的解)

對於圖搜尋,基本和樹搜尋一樣,但是圖搜尋有一個額外的處理重複狀態的過程。(需要:初始化一個explored set,如果這個葉節點被探索過了,就丟到explored set中;如果這個葉節點的擴充套件子節點也被探索過了,那就不加到frontier)

2.2 搜尋的資料結構

注意:樹搜尋和圖搜尋都是在“樹”這一個資料結構上進行的,所以搜尋演算法需要一個數據結構來記錄搜尋樹的構造過程。

所以對樹中每個節點n,定義如下資料結構

  • n.state:狀態
  • n.parent:父節點
  • n.action:父節點生成該節點時採取的行動
  • n.path-cost:代價,從初始節點到該節點的路徑消耗,也叫g(n)
子節點的構造程式碼

具體實現的時候,要用到
1)用佇列來存放節點(FIFO,LIFO,優先順序佇列)
2)用雜湊表存放已擴充套件節點表 (實現的好的話,插入和查詢操作的時間消耗是常數)

2.3 問題求解演算法的效能

四個方面:

  • 完備性(當問題有解時,這個演算法能否保證找到解)
  • 最優性(搜尋策略能否找到最優解)
  • 時間複雜度(找到解要花多長時間) 也叫搜尋代價
  • 空間複雜度(在執行搜尋的過程中需要多少記憶體)
    總代價=搜尋代價+記憶體使用(空間複雜度)

三、無資訊搜尋(盲目搜尋)策略

這些搜尋策略是以節點擴充套件的次序來分類的(寬度優先,一致代價,深度優先,深度受限,迭代加深,雙向搜尋)。

3.1 寬度優先搜尋 breadth-first search (BFS)

寬度優先搜尋是一般圖搜尋演算法的一個例項,每次總是擴充套件深度最淺的節點,這可以通過將邊緣組織成FIFO佇列來實現(即,新節點加入到佇列尾,淺層的老節點會在深層節點之前被擴充套件)。

效能:是完備的(只要有解,肯定能搜到。當然,前提是最淺的目標節點處於一個有限深度d,分支因子b也是有限的)BFS找到的永遠是最淺的目標節點,但不一定最優,只有當路徑代價是基於節點深度的非遞減函式時,BFS是最優的(最常見情況是所有行動要花費相同的代價)。
假設每個狀態都有b個後繼狀態,解的深度為d,那麼時間複雜度就是O(bd),空間複雜度也是O(bd)。這種指數級的複雜度就太大了。
(一般而言,指數級別複雜度的搜尋問題不能用無資訊的搜尋演算法求解,除非是規模很小的例項)

BFS 寬度優先虛擬碼

3.2 一致代價搜尋 Uniform-cost search (UCS)

一致代價搜尋擴充套件的是路徑消耗g(n)(從初始狀態到當前狀態的路徑耗散)最小的節點n。(可以通過將邊緣節點組織成按g值排序的佇列來實現)

這裡寫圖片描述

一致代價搜尋和寬度優先搜尋的區別:1)目標檢測應用於節點被選擇擴充套件時,而不是在節點生成的時候。原因:一致代價搜尋希望在替換代價更小的節點後再確認解;2)如果邊緣中的節點有更好的路徑到達該節點,那麼會引入一個測試。

效能:是最優的。如果每一步的代價都大於等於某個小的正常數,那麼就是完備的。

一致代價的複雜度較高:O(b1+[C/e]),其中C是最優解的代價,每個行動的代價至少為e,所以最壞情況下,這個複雜度要比BFS的複雜度bd大的多。(因為一致代價搜尋在探索包含代價大的行動之前,經常會探索代價小的行動步驟所在的很大的搜尋樹)

當所有單步耗散都相等時,複雜度變為bd+1。這種情況下,由於一致代價搜尋和BFS的第一個區別,一致代價搜尋會在深度d上做更多無用功(因為他是在選擇節點的時候才判斷是不是目標達到)。

3.3 深度優先 depth-first search (DFS)

深度優先總是擴充套件搜尋樹的當前邊緣節點集 中最深的節點(搜尋直接推到最深層)。如果最深層節點擴充套件完了,就回溯到下一個還有未擴充套件節點的深度稍淺的節點。

DFS使用LIFO佇列(最新生成的節點最早被擴充套件),而且要呼叫自己的遞迴函式來實現DFS演算法。(有深度界限的遞迴深度優先搜尋演算法)

這裡寫圖片描述

效能:
DFS的搜尋效率嚴重依賴於使用的是圖搜尋還是樹搜尋。
如果是圖搜尋(避免了重複狀態和冗餘路徑),那麼DFS在有限狀態空間就是完備的。
如果是樹搜尋,則不完備,因為會出現死迴圈(DFS演算法本身是沒有explored set的)。

不是最優的。

複雜度:時間複雜度受限於狀態空間的規模,為:O(bm),m是任一節點的最大深度。這比d(最淺解的深度)要大的多。
但是空間複雜度很給力,為O(bm)。所以DFS在AI的很多領域成為工作主力。

此外,還有一種變形叫做回溯搜尋(backtracking search):每次只產生一個後繼而不是生成所有後繼,每個被部分擴充套件的節點要記住下一個要生成的節點。這樣,記憶體只需要O(m)而不是O(mb)。

3.4 深度受限

設定界限l來避免DFS在無限狀態空間下搜尋失敗的尷尬情況。即,深度為l的節點被當做最深層節點(沒有後繼節點)來對待。

3.5 迭代加深的深度優先演算法 iterative deepening search(IDS)

IDS = DFS + BFS。
可以說是結合了寬度優先和深度優先的優點了:1)空間複雜度:O(bd) (和DFS一樣);2)在分支因子有限時完備,在路徑待機時節點深度的非遞減函式時最優(和BFS一樣)。

這裡寫圖片描述

3.6 雙向搜尋

一個從初始狀態開始搜,一個從目標狀態開始搜,當邊緣有交集,就說明找到了解。

好處:如果兩個都用BFS,那麼複雜度就變成了
O(bd/2)+O(bd/2),這肯定是要遠遠小於O(bd)的。所以說減小了複雜度。

四、總結

寫的有點累,因為知識點很多,而且我覺得也很難講清楚。畢竟這些知識都是“硬知識”,如果要講的非常生動,我覺得可能就不是我一上午(花了3個小時)能做完的事情了。

所以當然還是有點遺憾的,我也希望講的各種生動形象,但是如果真要生動形象的話,這一章裡面每一個知識點拿出來,都可以洋洋灑灑一大篇錦繡文章。我覺得可以做到,但是時間的確不允許。以後有機會,會重點將一些有針對性的知識點。

但是這篇文章的意義在於哪裡呢?
1)向大家展示如何形式化定義一個搜尋問題,又如何去求解;
2)通過講述各種盲目搜尋演算法,幫大家梳理無資訊搜尋的脈絡。(直接放在文章開頭是不錯的選擇)

所以還是有些價值的。希望以後能夠不斷進步,寫出更好的文章。

五、資料分享

這次沒有去找什麼資料,我就參考了[1]的第三章,當然這也是一本神書了,AI界大佬Stuart Russell的大作。檔案太大(有300多兆),我就不上傳到CSDN了,這裡給出網址(參考[2]),感興趣的同學可以自己去下。

參考文獻

[1] StuartJ.Russell, PeterNorvig, 諾維格,等. 人工智慧:一種現代的方法[J]. 2013.
[2] 人工智慧 一種現代的方法(第3版). http://www.aibbt.com/a/16340.html