車栗子 發自 凹非寺 量子位 出品 | 公眾號 QbitAI
車栗子 發自 凹非寺
要了解機器學習、了解神經網路,一種非常有趣的方式,就是找個小遊戲,自己實現一下。
遊戲里的每一位AI玩家 (智能體) ,都是一個小小的神經網路。
一開始,它們什麼都不懂,剛開局就GG。但有了進化演算法 (Evolution) ,AI可以在一代一代更迭中,掌握強大的遊戲技能。
比如,在這個賽車遊戲里,萌新車手跑出去不久便撞上了馬路牙子。不過,用不了幾代進化,就有AI車手可以毫髮無損地跑完一周。
AI賽車手如何快速煉成?
首先,要有一個龐大的車隊。
賽車AI的開發者,是一位叫做Johan Eliasson的程序猿。他的訓練計劃里,有650輛車同時訓練。
第二,AI開車需要一些空間信息。
這5條黃線代表5個距離,指示離馬路牙子還有多遠;
除此之外,AI還需要知道自己當前的速率,以及方向。
這樣算來,神經網路一共會接受7個輸入。
第三,就是讓神經網路不斷進化。
輸入七個值,處理一下,輸出兩個值:
一個代表方向盤,按照數值大小,分為左轉、右轉、方向不變三種操作;一個代表油門/剎車,按照數值大小,分成加速、減速、速率不變三種操作。
一個代表方向盤,按照數值大小,分為左轉、右轉、方向不變三種操作;
最開始,誰不知道遊戲規則,輸出值很隨機。
650輛車衝出去沒多久,路邊就出現了大批車輛的屍體。
但重要的是,依然有碩果僅存的汽車,不止通過了第一次的右轉考驗,也機智地發現下一處彎道應該猛烈左轉。
雖然,它並沒有成功掉頭,但依然是下一代的希望:進化演算法就是要在每一代里,選出最優秀的一隻或者幾隻智能體,繁育出色的後代。
(這裡,程序猿沒有找到一種很好的方法,讓系統自動選擇出優質的個體,於是就手動馬克了,反正也沒有訓練很多代。)
所以,第二代的650輛車,全是這一隻智能體的子嗣,各自有些輕微的變異:神經網路的權重發生小小的變化。
變異是為了保持車隊的多樣性,期待從中生產出更加優秀的個體,繁育下一代。
由於繼承了優良傳統,第二代汽車大部分都完成了第一次右轉,還有一小部分掉頭成功。
這一次,把衝到最前面的3輛車馬克一下,它們差一點就能達成兩次連續掉頭的S形操作。
既然,第三代的父母有3位,那麼繁育過程中除了變異之外,還涉及雜交:就是把不同的神經網路揉到一起:
第三代的表現更加精進,有的智能體完成了多次連續轉彎,勝利在望。
第四代,便有智能體跑完一周,值得紀念:
程序猿說:這效果比想像的好多了,之前我還有點懷疑,現在只能說機器學習好厲害。
第四代車隊中的佼佼者,已經不太撞到路肩,只是速度還很慢,就像一大波殭屍。
車隊的主人表示,後面的主要任務就是訓練速度。畢竟,這是賽車。
到了第十代,速度已經有了明顯的提升,不過依然不算快:
不知訓練了多少代,現在把每一代的優質選手放在一起跑。你看,好快:
AI不知道自己在開車,不知道有跑道。它只接收七個輸入的數值,不了解它們代表什麼意思,也不知道自己輸出的每一個決策,產生了怎樣的效果。
就算這樣,它還是學會了怎樣在遊戲世界裡更好地生存。
雖然,賽車遊戲的視頻,沒有講到程序猿用了怎樣簡單的神經網路。不過,可以通過另一個簡單的遊戲,來感受一下:
這個HTML 5實現, 也是進化演算法和神經網路共同的結晶。而且開源了。
它的作者ssusnic說,神經網路部分,用的是突觸神經網路 (Synaptic Neural Network) 庫。
沒有650輛車那麼多,種群里只有10隻小鳥。每一隻,都是一個三層的神經網路:
輸入層:兩個神經元隱藏層:六個神經元輸出層:一個神經元
輸入層:兩個神經元
輸入兩個值,代表小鳥當前距離下一個障礙物的相對位置,分成水平距離 (x) 和豎直距離 (y) 。
經過隱藏層的處理,輸出一個0-1之間的數值,決定下一步要不要扇翅膀:
如果大於0.5,就扇翅膀,反之就不操作。
第一代的小鳥,都是隨機神經網路 (Random Neural Networks) ,集體見光死。
全部陣亡之後,要選出四隻最優質的小鳥去繁殖。問題來了,肉眼看去相差無幾,要選哪幾隻?
並不需要手動選擇,而是用一個適應度函數 (Fitness Function) :
適應度 = 小鳥存活的最遠距離 - 小鳥到下一個障礙物的距離
適應度分數排名前四的小鳥,按下面的規則繁殖10個後代:
· 前兩名,雜交出一個後代· 4隻中隨機選兩隻,雜交出三個後代· 4隻中隨機選兩隻,分別直接複製,生成兩個 (和上代一樣的) 後代· 給每個後代加入一些變異
· 前兩名,雜交出一個後代
就這樣,來到第11代,已經有小鳥飛出很遠且毫髮無傷:
第23代,完全碾壓,可以換個遊戲了:
當然,不是所有遊戲都像小鳥扇翅膀這樣簡單。
吃豆人 (Pacman) 就是個更複雜的栗子。比如,前面要躲避的障礙物都是靜止的,Pacman的敵人是移動的,窮追不捨。
重點是,為了抓到Pacman,四個敵人還有各自不同的運動規則:
紅色鬼,直接瞄準Pacman的位置進發;粉色鬼,瞄準Pacman前方的第四格;藍色鬼,利用Pacman和紅色鬼的位置來搞伏擊;橙色鬼,原本和紅色鬼一樣,但當它和Pacman的距離近到8格以內,就會朝一個角落退縮,那是它出發的地方。
紅色鬼,直接瞄準Pacman的位置進發;
並且,Pacman吃到無敵大豆豆的時候,敵人還會從追擊模式轉成逃跑模式。
複雜的遊戲,自然也需要更加精密的演算法,來幫智能體進化。
名叫Code Bullet的程序猿,就用了一種叫做NEAT的神經進化演算法。
這種方法很特別,神經網路在迭代過程中,不止權重會變化,網路結構也會變複雜。
而網路結構越複雜,就可以支持越複雜的行為,讓Pacman在險惡的世界裡存活。
雖有強大的演算法,訓練還是要由淺入深。
先不加無敵大豆豆,也不加敵人,給AI一個簡單的世界。
這樣它就能吃光所有豆豆?不存在的。
第一代最優秀的智能體,也只會右轉不會左轉,還把自己困在一處,永遠走不出去。
第二代,有的選手已經學會了左轉,但依然會困住。
……
第十八代,眼看快要吃光豆豆,AI還是困死了自己。
在平靜中訓練20代之後,把敵人放出來,AI又要從手忙腳亂開始重新適應:
不過好在,智能體學以很快便學會了躲避敵人:
又過了40代,是時候加入無敵大豆豆了。
這一層防護令AI如有神助,就像在經歷了40代卧薪嘗膽之後,開啟了復仇模式,瘋狂追擊。
終於,有智能體在第七十三代通關成功:
視頻的畫外音里,程序猿的聲音都激昂了起來,這場戰役的勝利他期待已久。
除了發表獲獎感言,謝過各路親友的支持,他也沒忘在GitHub上分享代碼 (傳送門見文底) 。
同學,你也去搭個神經網路打遊戲吧,呆萌的遊戲也能打出熱血的氣質。
以後,神經網路可能就是你女朋友了。
(友情提示:雖然賽車遊戲沒有開源代碼,但OpenAI Gym裡面有賽車場,也可以去試試。)
賽車遊戲視頻傳送門:
OpenAI Gym賽車場:
Flappy Bird代碼傳送門:
Pacman代碼傳送門:
— 完 —
量子位 · QbitAI
?? ? 追蹤AI技術和產品新動態
戳右上角「+關注」獲取最新資訊↗↗
如果喜歡,請分享or點贊吧~比心?