遺傳算法詳解(GA)(個人覺得很形象,很適合初學者)


本文是去年課題組周報中的一個專題講解,詳細講了GA,由於是周報,所以十分詳細。很適合初學者入門。文中也簡單提及了模擬退火算法。文章綜合參考了一些互聯網資料。發博客以備忘!

三:遺傳算法

照例先給出科學定義:

遺傳算法(Genetic Algorithm, GA)起源於對生物系統所進行的計算機模擬研究。它是模仿自然界生物進化機制發展起來的隨機全局搜索和優化方法,借鑒了達爾文的進化論和孟德爾的遺傳學說。其本質是一種高效、並行、全局搜索的方法,能在搜索過程中自動獲取和積累有關搜索空間的知識,並自適應地控制搜索過程以求得最佳解。

 

再給出相關術語:(各位看看就好,后面都會涉及到,再細說)

基因型(genotype):性狀染色體的內部表現;

表現型(phenotype):染色體決定的性狀的外部表現,或者說,根據基因型形成的個體的外部表現;

進化(evolution):種群逐漸適應生存環境,品質不斷得到改良。生物的進化是以種群的形式進行的。

適應度(fitness):度量某個物種對於生存環境的適應程度。

選擇(selection):以一定的概率從種群中選擇若干個個體。一般,選擇過程是一種基於適應度的優勝劣汰的過程。

復制(reproduction):細胞分裂時,遺傳物質DNA通過復制而轉移到新產生的細胞中,新細胞就繼承了舊細胞的基因。

交叉(crossover):兩個染色體的某一相同位置處DNA被切斷,前后兩串分別交叉組合形成兩個新的染色體。也稱基因重組或雜交;

變異(mutation):復制時可能(很小的概率)產生某些復制差錯,變異產生新的染色體,表現出新的性狀。

編碼(coding):DNA中遺傳信息在一個長鏈上按一定的模式排列。遺傳編碼可看作從表現型到基因型的映射。

解碼(decoding):基因型到表現型的映射。

個體(individual):指染色體帶有特征的實體;
種群(population):個體的集合,該集合內個體數稱為種群

的大小。

 

遺傳算法的有趣應用很多,諸如尋路問題,8數碼問題,囚犯困境,動作控制,找圓心問題(在一個不規則的多邊形中,尋找一個包含在該多邊形內的最大圓圈的圓心),TSP問題,生產調度問題,人工生命模擬等。下面我以袋鼠為例子講講遺傳算法。(因為袋鼠會跳)

 

遺傳算法中每一條染色體,對應着遺傳算法的一個解決方案,一般我們用適應性函數(fitness function)來衡量這個解決方案的優劣。所以從一個基因組到其解的適應度形成一個映射。可以把遺傳算法的過程看作是一個在多元函數里面求最優解的過程。 可以這樣想象,這個多維曲面里面有數不清的“山峰”,而這些山峰所對應的就是局部最優解。而其中也會有一個“山峰”的海拔最高的,那么這個就是全局最優解。而遺傳算法的任務就是盡量爬到最高峰,而不是陷落在一些小山峰。(另外,值得注意的是遺傳算法不一定要找“最高的山峰”,如果問題的適應度評價越小越好的話,那么全局最優解就是函數的最小值,對應的,遺傳算法所要找的就是“最深的谷底”)

 

 


問題的提出與解決方案:

讓我們先來考慮考慮下面這個問題的解決辦法。

已知一元函數:

 

 現在要求在既定的區間內找出函數的最大值

 

 “袋鼠跳”問題

既然我們把函數曲線理解成一個一個山峰和山谷組成的山脈。那么我們可以設想所得到的每一個解就是一只袋鼠,我們希望它們不斷的向着更高處跳去,直到跳到最高的山峰(盡管袋鼠本身不見得願意那么做)。所以求最大值的過程就轉化成一個“袋鼠跳”的過程。

作為對比下面簡單介紹“袋鼠跳”的幾種方式。

1. 爬山法(最速上升爬山法):

從搜索空間中隨機產生鄰近的點,從中選擇對應解最優的個體,替換原來的個體,不斷重復上述過程。因為爬山法只對“鄰近”的點作比較,所以目光比較“短淺”,常常只能收斂到離開初始位置比較近的局部最優解上面。對於存在很多局部最優點的問題,通過一個簡單的迭代找出全局最優解的機會非常渺茫。(在爬山法中,袋鼠最有希望到達最靠近它出發點的山頂,但不能保證該山頂是珠穆朗瑪峰,或者是一個非常高的山峰。因為一路上它只顧上坡,沒有下坡。)

2. 模擬退火:

這個方法來自金屬熱加工過程的啟發。在金屬熱加工過程中,當金屬的溫度超過它的熔點(Melting Point)時,原子就會激烈地隨機運動。與所有的其它的物理系統相類似,原子的這種運動趨向於尋找其能量的極小狀態。在這個能量的變遷過程中,開始時,溫度非常高, 使得原子具有很高的能量。隨着溫度不斷降低,金屬逐漸冷卻,金屬中的原子的能量就越來越小,最后達到所有可能的最低點。利用模擬退火的時候,讓算法從較大的跳躍開始,使到它有足夠的“能量”逃離可能“路過”的局部最優解而不至於限制在其中,當它停在全局最優解附近的時候,逐漸的減小跳躍量,以便使其“落腳 ”到全局最優解上。(在模擬退火中,袋鼠喝醉了,而且隨機地大跳躍了很長時間。運氣好的話,它從一個山峰跳過山谷,到了另外一個更高的山峰上。但最后,它漸漸清醒了並朝着它所在的峰頂跳去。)

3. 遺傳算法:

模擬物競天擇的生物進化過程,通過維護一個潛在解的群體執行了多方向的搜索,並支持這些方向上的信息構成和交換。是以面為單位的搜索,比以點為單位的搜索,更能發現全局最優解。(在遺傳算法中,有很多袋鼠,它們降落到喜瑪拉雅山脈的任意地方。這些袋鼠並不知道它們的任務是尋找珠穆朗瑪峰。但每過幾年,就在一些海拔高度較低的地方射殺一些袋鼠,並希望存活下來的袋鼠是多產的,在它們所處的地方生兒育女。)(或者換個說法。從前,有一大群袋鼠,它們被莫名其妙的零散地遺棄於喜馬拉雅山脈。於是只好在那里艱苦的生活。海拔低的地方彌漫着一種無色無味的毒氣,海拔越高毒氣越稀薄。可是可憐的袋鼠們對此全然不覺,還是習慣於活蹦亂跳。於是,不斷有袋鼠死於海拔較低的地方,而越是在海拔高的袋鼠越是能活得更久,也越有機會生兒育女。就這樣經過許多年,這些袋鼠們竟然都不自覺地聚攏到了一個個的山峰上,可是在所有的袋鼠中,只有聚攏到珠穆朗瑪峰的袋鼠被帶回了美麗的澳洲。)

 遺傳算法的實現過程

遺傳算法的實現過程實際上就像自然界的進化過程那樣。首先尋找一種對問題潛在解進行“數字化”編碼的方案。(建立表現型和基因型的映射關系)然后用隨機數初始化一個種群(那么第一批袋鼠就被隨意地分散在山脈上),種群里面的個體就是這些數字化的編碼。接下來,通過適當的解碼過程之后(得到袋鼠的位置坐標),用適應性函數對每一個基因個體作一次適應度評估(袋鼠爬得越高,越是受我們的喜愛,所以適應度相應越高)。用選擇函數按照某種規定擇優選擇(我們要每隔一段時間,在山上射殺一些所在海拔較低的袋鼠,以保證袋鼠總體數目持平。)。讓個體基因變異(讓袋鼠隨機地跳一跳)。然后產生子代(希望存活下來的袋鼠是多產的,並在那里生兒育女)。遺傳算法並不保證你能獲得問題的最優解,但是使用遺傳算法的最大優點在於你不必去了解和操心如何去“找”最優解。(你不必去指導袋鼠向那邊跳,跳多遠。)而只要簡單的“否定”一些表現不好的個體就行了。(把那些總是愛走下坡路的袋鼠射殺,這就是遺傳算法的精粹!)

 

所以我們總結出遺傳算法的一般步驟:

開始循環直至找到滿意的解。

1.評估每條染色體所對應個體的適應度。

2.遵照適應度越高,選擇概率越大的原則,從種群中選擇兩個個體作為父方和母方。

3.抽取父母雙方的染色體,進行交叉,產生子代。

4.對子代的染色體進行變異。

5.重復2,3,4步驟,直到新種群的產生。

結束循環。

 

 接下來,我們將詳細地剖析遺傳算法過程的每一個細節。

編制袋鼠的染色體----基因的編碼方式

受到人類染色體結構的啟發,我們可以設想一下,假設目前只有“0”,“1”兩種鹼基,我們也用一條鏈條把他們有序的串連在一起,因為每一個單位都能表現出 1 bit的信息量,所以一條足夠長的染色體就能為我們勾勒出一個個體的所有特征。這就是二進制編碼法,染色體大致如下:

010010011011011110111110

上面的編碼方式雖然簡單直觀,但明顯地,當個體特征比較復雜的時候,需要大量的編碼才能精確地描述,相應的解碼過程(類似於生物學中的DNA翻譯過程,就是把基因型映射到表現型的過程。)將過分繁復,為改善遺傳算法的計算復雜性、提高運算效率,提出了浮點數編碼。染色體大致如下:

1.2 –3.3 – 2.0 –5.4 – 2.7 – 4.3

(注:還有一種編碼方式叫符號編碼)

那么我們如何利用這兩種編碼方式來為袋鼠的染色體編碼呢?因為編碼的目的是建立表現型到基因型的映射關系,而表現型一般就被理解為個體的特征。比如人的基因型是46條染色體所描述的卻能解碼成一個眼,耳,口,鼻等特征各不相同的活生生的人。所以我們要想為“袋鼠”的染色體編碼,我們必須先來考慮“袋鼠”的“個體特征”是什么。也許有的人會說,袋鼠的特征很多,比如性別,身長,體重,也許它喜歡吃什么也能算作其中一個特征。但具體在解決這個問題的情況下,我們應該進一步思考:無論這只袋鼠是長短,肥瘦,黑白只要它在低海拔就會被射殺,同時也沒有規定身長的袋鼠能跳得遠一些,身短的袋鼠跳得近一些。當然它愛吃什么就更不相關了。我們由始至終都只關心一件事情:袋鼠在哪里。因為只要我們知道袋鼠在那里,我們就能做兩件必須去做的事情:

(1)通過查閱喜瑪拉雅山脈的地圖來得知袋鼠所在的海拔高度(通過自變量求適應函數的值。)以判斷我們有沒必要把它射殺。

(2)知道袋鼠跳一跳(交叉和變異)后去到哪個新位置。

如果我們一時無法准確的判斷哪些“個體特征”是必要的,哪些是非必要的,我們常常可以用到這樣一種思維方式:比如你認為袋鼠的愛吃什么東西非常必要,那么你就想一想,有兩只袋鼠,它們其它的個體特征完全同等的情況下,一只長得黑,另外一只長得不是那么黑。你會馬上發現,這不會對它們的命運有絲毫的影響,它們應該有同等的概率被射殺!只因它們處於同一個地方。(值得一提的是,如果你的基因編碼設計中包含了袋鼠黑不黑的信息,這其實不會影響到袋鼠的進化的過程,而那只攀到珠穆朗瑪峰的袋鼠黑與白什么的也完全是隨機的,但是它所在的位置卻是非常確定的。)

以上是對遺傳算法編碼過程中經常經歷的思維過程,必須把具體問題抽象成數學模型,突出主要矛盾,舍棄次要矛盾。只有這樣才能簡潔而有效的解決問題。

既然確定了袋鼠的位置作為個體特征,具體來說位置就是橫坐標。那么接下來,我們就要建立表現型到基因型的映射關系。就是說如何用編碼來表現出袋鼠所在的橫坐標。由於橫坐標是一個實數,所以說透了我們就是要對這個實數編碼。回顧我們上面所介紹的兩種編碼方式,最先想到的應該就是,對於二進制編碼方式來說,編碼會比較復雜,而對於浮點數編碼方式來說,則會比較簡潔。恩,正如你所想的,用浮點數編碼,僅僅需要一個浮點數而已。而下面則介紹如何建立二進制編碼到一個實數的映射。

明顯地,一定長度的二進制編碼序列,只能表示一定精度的浮點數。譬如我們要求解精確到六位小數,由於區間長度為2 – (-1) = 3 ,為了保證精度要求,至少把區間[-1,2]分為3 × 106等份。又因為

 

 

 所以編碼的二進制串至少需要22位。

把一個二進制串(b0,b1,....bn)轉化位區間里面對應的實數值通過下面兩個步驟。

(1)將一個二進制串代表的二進制數轉化為10進制數:

 

 

 (2)對應區間內的實數:

 

 

 (像極了模數轉換)

例如一個二進制串<1000101110110101000111>表示實數值0.637197。

 

 

 (糾正一個錯誤,這里是-1)

二進制串<0000000000000000000000>和<1111111111111111111111>則分別表示區間的兩個端點值-1和2。

好了,目前為止我們把袋鼠的染色體給研究透了,讓我們繼續跟進袋鼠的進化旅程
物競天擇--適應性評分與及選擇函數。

1.物競――適應度函數(fitness function)

自然界生物競爭過程往往包含兩個方面:生物相互間的搏斗與及生物與客觀環境的搏斗過程。但在我們這個實例里面,你可以想象到,袋鼠相互之間是非常友好的,它們並不需要互相搏斗以爭取生存的權利。它們的生死存亡更多是取決於你的判斷。因為你要衡量哪只袋鼠該殺,哪只袋鼠不該殺,所以你必須制定一個衡量的標准。而對於這個問題,這個衡量的標准比較容易制定:袋鼠所在的海拔高度。(因為你單純地希望袋鼠爬得越高越好。)所以我們直接用袋鼠的海拔高度作為它們的適應性評分。即適應度函數直接返回函數值就行了。

2.天擇――選擇函數(selection)

自然界中,越適應的個體就越有可能繁殖后代。但是也不能說適應度越高的就肯定后代越多,只能是從概率上來說更多。(畢竟有些所處海拔高度較低的袋鼠很幸運,逃過了你的眼睛。)那么我們怎么來建立這種概率關系呢?下面我們介紹一種常用的選擇方法――輪盤賭(Roulette Wheel Selection)選擇法。

比如我們有5條染色體,他們所對應的適應度評分分別為:5,7,10,13,15。

所以累計總適應度為:

 

 

 所以各個個體被選中的概率分別為:

 

 

 你可以想象一下,我們轉動輪盤,輪盤停下來的時候,指針會隨機地指向某一個個體所代表的區域,那么非常幸運地,這個個體被選中了。(很明顯,適應度評分越高的個體被選中的概率越大。)

注:還有精英選擇機制

 

遺傳變異――基因重組(交叉)與基因突變。

應該說這兩個步驟就是使得子代不同於父代的根本原因(注意,我沒有說是子代優於父代,只有經過自然的選擇后,才會出現子代優於父代的傾向。)。對於這兩種遺傳操作,二進制編碼和浮點型編碼在處理上有很大的差異,其中二進制編碼的遺傳操作過程,比較類似於自然界里面的過程,下面將分開講述。

1.基因重組/交叉(recombination/crossover)

(1)二進制編碼

二進制編碼的基因交換過程非常類似高中生物中所講的同源染色體的聯會過程――隨機把其中幾個位於同一位置的編碼進行交換,產生新的個體。

 

 

 (2)浮點數編碼

如果一條基因中含有多個浮點數編碼,那么也可以用跟上面類似的方法進行基因交叉,不同的是進行交叉的基本單位不是二進制碼,而是浮點數。而如果對於單個浮點數的基因交叉,就有其它不同的重組方式了,比如中間重組:隨機產生就能得到介於父代基因編碼值和母代基因編碼值之間的值作為子代基因編碼的值。比如5.5和6交叉,產生5.7,5.6。

考慮到“袋鼠跳”問題的具體情況――袋鼠的個體特征僅僅表現為它所處的位置。可以想象,同一個位置的袋鼠的基因是完全相同的,而兩條相同的基因進行交叉后,相當於什么都沒有做,所以我們不打算在這個例子里面使用交叉這一個遺傳操作步驟。(當然硬要這個操作步驟也不是不行的,你可以把兩只異地的袋鼠捉到一起,讓它們交配,然后產生子代,再把它們送到它們應該到的地方。)

2.基因突變(Mutation)

(1)二進制編碼

基因突變過程:基因突變是染色體的某一個位點上基因的改變。基因突變使一個基因變成它的等位基因,並且通常會引起一定的表現型變化。正如上面所說,二進制編碼的遺傳操作過程和生物學中的過程非常相類似,基因串上的“ 0”或“ 1”有一定幾率變成與之相反的“ 1”或“ 0”。例如下面這串二進制編碼:

101101001011001

經過基因突變后,可能變成以下這串新的編碼:

001101011011001

(2)浮點型編碼

浮點型編碼的基因突變過程一般是對原來的浮點數增加或者減少一個小隨機數。比如原來的浮點數串如下:

1.2,3.4,5.1, 6.0, 4.5

變異后,可能得到如下的浮點數串:

1.3,3.1,4.9, 6.3, 4.4

當然,這個小隨機數也有大小之分,我們一般管它叫“步長”。(想想“袋鼠跳”問題,袋鼠跳的長短就是這個步長。)一般來說步長越大,開始時進化的速度會比較快,但是后來比較難收斂到精確的點上。而小步長卻能較精確的收斂到一個點上。所以很多時候為了加快遺傳算法的進化速度,而又能保證后期能夠比較精確地收斂到最優解上面,會采取動態改變步長的方法。其實這個過程與前面介紹的模擬退火過程比較相類似。

到此為止,基因編碼,基因適應度評估,基因選擇,基因變異都一一實現了,剩下來的就是把這些遺傳過程的“零件”裝配起來了。(寫成代碼)

 

下面是上例的運行結果:

 

 紅點代表真實的最大點,由求導法可求的為f(1.85)=3.85

 

 

 

 總結:

編碼原則
完備性(completeness):問題空間的所有解都能表示為所設計的基因型;
健全性(soundness):任何一個基因型都對應於一個可能解;
非冗余性(non-redundancy):問題空間和表達空間一一對應。

適應度函數的重要性
適應度函數的選取直接影響遺傳算法的收斂速度以及能否找到最優解。一般而言,適應度函數是由目標函數變換而成的。

適應度函數設計不當有可能出現欺騙問題:
(1)進化初期,個別超常個體控制選擇過程;
(2)進化末期,個體差異太小導致陷入局部極值。

欺騙問題舉例:

還是袋鼠問題,如果低海拔的地方出現毒霧,會殺死袋鼠,只有爬上珠穆朗瑪峰頂端的袋鼠才能生存下來。

因為喜馬拉雅山脈有很多山峰,我們以高度作為適應度,case(1):如果不在珠峰的猴子若比在珠峰半山腰的猴子要高,因為種群大小不變,在珠峰的猴子可能就會被淘汰;case(2):100只猴子都不在珠峰;

1. 選擇的作用:優勝劣汰,適者生存;

2. 交叉的作用:保證種群的穩定性,朝着最優解的方向進化;

3. 變異的作用:保證種群的多樣性,避免交叉可能產生的局部收斂。
————————————————
版權聲明:本文為CSDN博主「boat_lee」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u010451580/article/details/51178225


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM