遺傳算法

遺傳算法是一個頗有意思的算法。git

咱們都知道達爾文提出了偉大的「生物進化論」,他證實了全部的生物都不是上帝創造的,而是在遺傳、變異、生存鬥爭和天然選擇中,由簡單到複雜,由低等到高等,不斷髮展變化的。也就是:物競天擇、適者生存、優勝劣汰。github

達爾文的進化論給美國的科學家霍蘭德留下了深入的印象,但他從計算機科學的角度思考了這個問題,他想到,是否能夠像繁育良種馬和良種玉米同樣繁育程序。這也就是遺傳算法的由來。遺傳算法借鑑了進化生物學中的一些現象,包括遺傳、突變、天然選擇以及雜交等。算法

掃地機器人羅比

在《複雜》這本書中有個例子,羅比是一個掃地機器人,他生活在一個 10 * 10 格子的世界裏,這個世界隨機散落着易拉罐,且每一個格子最多隻有一個易拉罐。羅比的任務是清理這些易拉罐。世界的周圍都是牆壁。函數

羅比的世界

羅比的視野是有限的,他只能看到四周格子以及本身所在位置的狀況,也就是上下左右和當前位置五個格子的狀況。spa

每次清理工做羅比能夠執行 200 個動做,動做能夠是:向上走,向下走,向左走,向右走,隨機一個方向走、撿罐頭、不動。每個動做執行完之後都會有一個評分:若是撿罐頭時格子中有罐頭,那麼罐頭被撿起,加 10 分。若是撿罐頭的時候格子中沒有罐頭,扣 1 分。若是羅比撞到了牆,扣 5 分。設計

顯然,羅比儘量多撿到罐頭、別在沒罐頭的時候去撿、別撞牆,分數就越高。那麼,咱們須要設計一套策略,讓羅比根據當前所在位置的狀態去執行相應的動做,可以拿到最高的分。code

那麼,總共有多少種狀態?blog

每次羅比看到的格子爲:上下左右中,一共 5 個格子,而每一個格子有三種可能性:沒罐頭、有罐頭、牆壁。咱們把沒罐頭記爲 0,有罐頭記爲 1,是牆壁記爲 2。那麼狀態能夠列爲:rem

上下左右中
0 0 0 0 0
0 0 0 0 1
0 0 0 0 2
0 0 0 1 0
0 0 0 1 1
...
2 2 2 2 2

顯然,一共有 3 * 3 * 3 * 3 * 3 = 243 種狀態。字符串

而對於每一種狀態,羅比有 7 種動做能夠執行:

0: 向上走
1: 向下走
2: 向左走
3: 向右走
4: 隨機選取方向走
5: 撿罐頭
6: 什麼都不幹

因此,243 個狀態,每一個狀態 7 種動做,那麼策略的總數是 $7^243$ 個。要想遍歷全部的策略去求最優解顯然是不現實的,在這裏可使用遺傳算法,來 「進化」 出一個近似最優解。

遺傳算法設計

以前已經提到過了,遺傳算法借鑑了天然選擇中的思想,在遺傳算法中,也有「種羣」、「染色體」、「基因」、「雜交」、「變異」等概念。

試想咱們須要獲得的策略是什麼樣子的。羅比須要根據每一種格子的狀態去尋求一種動做,在上面已經提到過,格子的狀態分別是 000000000100002 以此類推。咱們能夠發現,這實際上就是全部的 5 位 3 進制數。

那麼,羅比的策略就能夠用一個字符串表示,字符串的長度是格子狀況的總數,每一位表明對應格子狀況所須要做出的策略,好比 152455021256444063355141362453351200451455123151604162324266004040256060052004316401456203443334225141156451050235106256354245063143011340422626044356444400300555631325215155436144345164455440161256251412661563442063025020602255536510141514365 。這個策略的第一位是 1,這表明着羅比所處的狀況是 00000 時,應該做出動做 1,也就是向下走。相似的,第二位是 5,表明羅比在 00001 時應該撿罐頭。

咱們須要經過遺傳算法找到最優的策略,這每個策略實際上就表明着個體,咱們經過一個字符串來表明它,這個字符串能夠稱爲染色體(基因組),染色體是基因的集合,種羣是染色體的集合。

遺傳算法首先須要隨機生成一個種羣,而後經過「天然選擇」來篩選他們,越優秀的個體越容易留下來,並不斷繁衍出優秀的子代,這樣通過一代又一代的選擇,最後留下的個體就是近似最優的。

對應到羅比問題中來,遺傳算法過程以下:

  1. 初始化種羣:隨機生成 200 個個體

  2. 計算適應度:對 200 個個體進行評分,評分的規則是讓羅比打掃 1000 次世界,每次打掃世界都是隨機生成的,且每次打掃羅比移動 200 步,最後算出這 1000 次打掃的平均分。

  3. 雜交:根據全部個體的得分,隨機選取兩個個體進行雜交,得分越高的個體越容易被選中。雜交會生成兩個子代,將子代放入新種羣。重複這個過程,直到新種羣的個數達到 200 個。

  4. 突變:子代的一個或多個基因會有必定的機率發生突變,發生突變的基因會隨機變爲其餘的動做,好比從 1 變爲 6。

  5. 迭代:重複以上的過程,直到達到 1000 代。

固然上面的 200、1000 這些數字都是人爲設定的,你也能夠設定其餘的,只要能獲得比較好的解就行。

是否是頗有意思,由於咱們根本不用動腦去設計策略,而是所有交給了計算機。固然這裏面還有適應度函數的設計、雜交的設計、參數的選定等使人傷腦筋的事情,但遺傳算法的過程提及來就是這樣。

適應度

在步驟 2 裏面,咱們對種羣中全部個體進行了評分,評分的實現也比較簡單,生成一個世界,根據策略在世界內進行 200 個動做,並把這個過程重複 1000 次便可,最後能拿到一個平均分。

選取父母

舉個栗子,假設種羣內只有 3 個個體,他們得分分別是 1, 2, 7,咱們須要進行兩次選擇,且得分越高的個體越容易被選中。這裏使用 輪盤賭 方法來選擇個體。

實際上也就是個求機率的問題,三個個體總分爲 1 + 2 + 7 = 10,那麼每一個個體佔比就能夠算出來:0.1, 0.2, 0.7。而後讓每一個個體的機率加上前一個個體的機率,也就是:0.1, 0.3, 1

這樣隨機生成一個 0 到 1 的數,而後從左往右去比較,小於哪一個個體就選擇哪一個個體便可。

當出現負數怎麼辦,好比 -5, 3, 9,這裏能夠給每一個元素都加上第一個元素的絕對值再加 1,也就是加 6,轉爲:1, 9, 15 ,而後再像上面那樣按輪盤賭便可。

事實上,這裏能夠有不少種方法能夠選擇,好比所有調完正數後讓每一個元素平方,或者對全部元素加上一個總步數 * 撞牆扣分,表明一次打掃中最多可能扣掉的分。這裏選擇方法的選取對整個遺傳算法影響也是很大的,須要設計一個比較合理的選擇方式。

雜交

選擇出父母以後,須要讓父母進行雜交,好比選取某一個位置,取父親的前半段加上母親的後半段,以及父親的後半段加母親的前半段。

203651
100344
取後三位交叉
203344
100651

交叉算子的方式還有其餘更復雜的。

突變

子代有很小的機率會發生基因突變,好比

203344 -> 206344

第三個位置的基因發生變化。

吐槽

實際上這個參數仍是很麻煩。。我調了很長時間,最後進化了 2000 次,最高得分大概維持在 380 附近,這是種羣平均分和種羣中最高分隨子代數的趨勢圖,能夠看到種羣確實在一點一點進化,若是參數更合理一點相信必定能達到幾乎滿分的得分的~

貼一個 380 分左右的策略:450351253450256256354356265152354252154454454351351464051353450055356644335603132054351253256352104350004552116414256156116103346453105056355052053324226604006321154130114255453253352312102112111412414140255154432364654062360530606611264324300

代碼

完整代碼在 這裏

相關文章
相關標籤/搜索