python遺傳算法之geatpy的深入理解
今天我們來學(xué)習(xí)python中的遺傳算法的使用,我們這里使用的是geatpy的包進(jìn)行學(xué)習(xí),本博客主要從geatpy中的各種數(shù)據(jù)結(jié)構(gòu)一步一步進(jìn)行學(xué)習(xí),請大家耐心看完。
其實(shí)以前也學(xué)習(xí)過遺傳算法,但是主要使用matlab進(jìn)行編程的,后面覺得matlab太麻煩了,還是使用python方便些,于是開始繼續(xù)學(xué)習(xí)。
1. geatpy的安裝
首先是安裝geatpy,使用pip3命令進(jìn)行安裝即可:
pip3 install geatpy
出現(xiàn)如下提示即安裝成功:
2. geatpy的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)
geatpy中的大部分?jǐn)?shù)據(jù)都是都是使用numpy的數(shù)組進(jìn)行存儲和計(jì)算的,下面我將介紹遺傳算法中的概念是如何用numpy數(shù)據(jù)表示,以及行和列的含義。
2.1 種群染色體
遺傳算法中最重要的就是個(gè)體的染色體表示,在geatpy中種群染色體用Chrom表示,這是一個(gè)二維數(shù)組,其中每一行對應(yīng)一個(gè)個(gè)體的染色體編碼,Chrom的結(jié)構(gòu)如下:其中l(wèi)ind表示編碼的長度,Nind表示的是種群的規(guī)模(個(gè)體數(shù)量)。
2.2 種群表現(xiàn)型
種群表現(xiàn)型是是指種群染色體矩陣Chrom經(jīng)過解碼后得到的基因表現(xiàn)型矩陣Phen,每一行對應(yīng)一個(gè)個(gè)體,每一列對應(yīng)一個(gè)決策變量,Phen的結(jié)構(gòu)如下:其中Nvar表示變量的個(gè)數(shù)
Phen的值與采用的解碼方式有關(guān)。Geatpy提供二進(jìn)制/格雷碼編碼轉(zhuǎn)十進(jìn)制整數(shù)或?qū)崝?shù)的解碼方式。另外,在Geatpy也可以使用不需要解碼的“實(shí)值編碼”種群,這種種群的染色體的每一位就對應(yīng)著決策變量的實(shí)際值,即這種編碼方式下Phen等價(jià)Chrom。
2.3 目標(biāo)函數(shù)值
Geatpy采用numpy的array類型矩陣來存儲種群的目標(biāo)函數(shù)值。一般命名為ObjV,每一行對應(yīng)每一個(gè)個(gè)體,因此它擁有與Chrom相同的行數(shù);每一列對應(yīng)一個(gè)目標(biāo)函數(shù),因此對于單目標(biāo)函數(shù),ObjV會只有1列;而對于多目標(biāo)函數(shù),ObjV會有多列, ObjV的表示形式如下:
2.4 個(gè)體適應(yīng)度
Geatpy采用列向量來存儲種群個(gè)體適應(yīng)度(適應(yīng)度函數(shù)計(jì)算而來)。一般命名為FitnV,它同樣是numpy的array類型,每一行對應(yīng)種群矩陣的每一個(gè)個(gè)體。因此它擁有與Chrom相同的行數(shù),F(xiàn)itnV的格式如下:
注意:Geatpy中的適應(yīng)度遵循“最小適應(yīng)度為0”的約定。
2.5 違反約束程度矩陣
Geatpy采用numpy的array類型的矩陣CV(Constraint Violation Value)來存儲種群個(gè)體違反各個(gè)約束條件的程度。命名為CV,它的每一行對應(yīng)種群的每一個(gè)個(gè)體,因此它擁有與Chrom相同的行數(shù);每一列對應(yīng)一個(gè)約束條件,因此若有一個(gè)約束條件,那么CV矩陣就會只有一列,如有多個(gè)約束條件,CV矩陣就會有多列。如果設(shè)有num個(gè)約束,則CV矩陣的結(jié)構(gòu)如下圖所示:
CV矩陣的某個(gè)元素若小于或等于0,則表示該元素對應(yīng)的個(gè)體滿足對應(yīng)的約束條件。若大于0,則表示違反約束條件,在大于0的條件下值越大,該個(gè)體違反該約束的程度就越高。Geatpy提供兩種處理約束條件的方法,一種是罰函數(shù)法,另一種是可行性法則。在使用可行性法則處理約束條件時(shí),需要用到CV矩陣。
2.6 譯碼矩陣
所謂的譯碼矩陣,只是用來描述種群染色體特征的矩陣,如染色體中的每一位元素所表達(dá)的決策變量的范圍、是否包含范圍的邊界、采用二進(jìn)制還是格雷碼、是否使用對數(shù)刻度、染色體解碼后所代表的決策變量的是連續(xù)型變量還是離散型變量等等。
在只使用工具箱的庫函數(shù)而不使用Geatpy提供的面向?qū)ο蟮倪M(jìn)化算法框架時(shí),譯碼矩陣可以單獨(dú)使用。若采用Geatpy提供的面向?qū)ο蟮倪M(jìn)化算法框架時(shí),譯碼矩陣可以與一個(gè)存儲著種群染色體編碼方式的字符串Encoding來配合使用。
目前Geatpy中有三種Encoding,分別為:
- BG:(二進(jìn)制/格雷碼)
- RI:((實(shí)整數(shù)編碼,即實(shí)數(shù)和整數(shù)的混合編碼)
- P:(排列編碼,即染色體每一位的元素都是互異)
注:’RI’和’P’編碼的染色體都不需要解碼,染色體上的每一位本身就代表著決策變量的真實(shí)值,因此“實(shí)整數(shù)編碼”和“排列編碼”可統(tǒng)稱為“實(shí)值編碼”
以BG編碼為例,我們展示一下編譯矩陣FieldD。FieldD的結(jié)構(gòu)如下:
其中,lens,lb,ub,codes,scales,lbin,ubin,varTypes都是行向量,其長度等于決策變量的個(gè)數(shù)。
- lens:代表以條染色體中,每個(gè)子染色體的長度。
- lb:代表每個(gè)變量的上界
- ub:代表每個(gè)變量的下界
- codes:代表染色體字串用的編碼方式,[1,0,1]代表第一個(gè)變量用的格雷編碼,第二個(gè)變量用的二進(jìn)制編碼,第3個(gè)變量用的格雷編碼。
- scales:指明每個(gè)子串用的是算術(shù)刻度還是對數(shù)刻度。scales[i] = 0為算術(shù)刻度,scales[i] = 1為對數(shù)刻度(對數(shù)刻度很少用,可以忽略。)
- lbin:代表變量上界是否包含其范圍邊界。0代表不包含,1代表包含。‘[ ’和 ‘(’ 的區(qū)別
- ubin:代表變量下界是否包含其范圍邊界。0代表不包含,1代表包含。
- varTypes:代表決策變量的類型,元素為0表示對應(yīng)位置的決策變量是連續(xù)型變量;1表示對應(yīng)的是離散型變量。
例如:有以下一個(gè)譯碼矩陣
它表示待解碼的種群染色體矩陣Chrom解碼后可以表示成3個(gè)決策變量,每個(gè)決策變量的取值范圍分別是[1,10], [2,9], [3,15]。其中第一第二個(gè)變量采用的是二進(jìn)制編碼,第三個(gè)變量采用的是格雷編碼,且第一、第三個(gè)決策變量為連續(xù)型變量;第二個(gè)為離散型變量。
#通過種群染色體chrom和譯碼矩陣FieldD,可解碼成種群表現(xiàn)型矩陣。 import geatpy as ea Phen = ea.bs2ri(Chrom, FieldD)
2.7 進(jìn)化追蹤器
在使用Geatpy進(jìn)行進(jìn)化算法編程時(shí),常常建立一個(gè)進(jìn)化追蹤器(如pop_trace)來記錄種群在進(jìn)化的過程中各代的最優(yōu)個(gè)體,尤其是采用無精英保留機(jī)制時(shí),進(jìn)化追蹤器幫助我們記錄種群在進(jìn)化過程中的最優(yōu)個(gè)體。待進(jìn)化完成后,再從進(jìn)化追蹤器中挑選出“歷史最優(yōu)”的個(gè)體。這種進(jìn)化記錄器有多種,其中一種是numpy的array類型的,結(jié)構(gòu)如下:其中MAXGEN是種群進(jìn)化的代數(shù)(迭代次數(shù))。
trace的每一列代表不同的指標(biāo),比如第一列記錄各代種群的最佳目標(biāo)函數(shù)值,第二列記錄各代種群的平均目標(biāo)函數(shù)值…trace的每一行對應(yīng)每一代,如第一行代表第一代,第二行代表第二代…另外一種進(jìn)化記錄器是一個(gè)列表,列表中的每一個(gè)元素都是一個(gè)擁有相同數(shù)據(jù)類型的數(shù)據(jù)。比如在Geatpy的面向?qū)ο筮M(jìn)化算法框架中的pop_trace,它是一個(gè)列表,列表中的每一個(gè)元素都是歷代的種群對象。
3. geatpy的種群結(jié)構(gòu)
3.1 Population類
在Geatpy提供的面向?qū)ο筮M(jìn)化算法框架中,種群類(Population)是一個(gè)存儲著與種群個(gè)體相關(guān)信息的類。它有以下基本屬性:
- sizes : int -種群規(guī)模,即種群的個(gè)體數(shù)目。
- ChromNum : int -染色體的數(shù)目,即每個(gè)個(gè)體有多少條染色體。
- Encoding : str -染色體編碼方式。
- Field : array -譯碼矩陣,可以是FieldD或FieldDR。
- Chrom : array -種群染色體矩陣,每一行對應(yīng)一個(gè)個(gè)體的一條染色體。
- Lind : int -種群染色體長度。
- ObjV : array -種群目標(biāo)函數(shù)值矩陣。
- FitnV : array -種群個(gè)體適應(yīng)度列向量。
- CV : array -種群個(gè)體違反約束條件程度的矩陣。
- Phen : array -種群表現(xiàn)型矩陣。
可以直接對種群對象進(jìn)行提取個(gè)體、個(gè)體合并等操作,比如pop1和pop2是兩個(gè)種群對象,則通過語句“pop3 = pop1 + pop2”,即可把兩個(gè)種群的個(gè)體合并,得到一個(gè)新的種群。在合并的過程中,實(shí)際上是把種群的各個(gè)屬性進(jìn)行合并,然后用合并的數(shù)據(jù)來生成一個(gè)新的種群(詳見Population.py)。又比如執(zhí)行語句“pop3 = pop1[[0]]”,可以把種群的第0號個(gè)體抽取出來,得到一個(gè)新的只有一個(gè)個(gè)體的種群對象pop3。值得注意的是,種群的這種個(gè)體抽取操作要求下標(biāo)必須為列表或是Numpy array類型的行向量,不能是標(biāo)量(詳見Population.py)
3.2 PsyPopulation類
PsyPopulation類是Population的子類,它提供Population類所不支持的多染色體混合編碼。它有以下基本屬性:
- sizes : int -種群規(guī)模,即種群的個(gè)體數(shù)目。
- ChromNum : int -染色體的數(shù)目,即每個(gè)個(gè)體有多少條染色體。
- Encodings : list -存儲各染色體編碼方式的列表。
- Fields : list -存儲各染色體對應(yīng)的譯碼矩陣的列表。
- Chroms : list -存儲種群各染色體矩陣的列表。
- Linds : list -存儲種群各染色體長度的列表。
- ObjV : array -種群目標(biāo)函數(shù)值矩陣。
- FitnV : array -種群個(gè)體適應(yīng)度列向量。
- CV : array -種群個(gè)體違反約束條件程度的矩陣。
- Phen : array -種群表現(xiàn)型矩陣。
可見PsyPopulation類基本與Population類一樣,不同之處是采用Linds、Encodings、Fields和Chroms分別存儲多個(gè)Lind、Encoding、Field和Chrom。
PsyPopulation類的對象往往與帶“psy”字樣的進(jìn)化算法模板配合使用,以實(shí)現(xiàn)多染色體混合編碼的進(jìn)化優(yōu)化。
4. 求解標(biāo)準(zhǔn)測試函數(shù)——McCormick函數(shù)
遺傳算法求解以下函數(shù)的最小值:
代碼實(shí)現(xiàn):
#-*-coding:utf-8-*- import numpy as np import geatpy as ea#導(dǎo)入geatpy庫 import time """============================目標(biāo)函數(shù)============================""" def aim(Phen):#傳入種群染色體矩陣解碼后的基因表現(xiàn)型矩陣 x1 = Phen[:, [0]]#取出第一列,得到所有個(gè)體的第一個(gè)自變量 x2 = Phen[:, [1]]#取出第二列,得到所有個(gè)體的第二個(gè)自變量 return np.sin(x1 + x2) + (x1 - x2) ** 2 - 1.5 * x1 + 2.5 * x2+1 """============================變量設(shè)置============================""" x1 = [-1.5, 4]#第一個(gè)決策變量范圍 x2 = [-3, 4]#第二個(gè)決策變量范圍 b1 = [1, 1]#第一個(gè)決策變量邊界,1表示包含范圍的邊界,0表示不包含 b2 = [1, 1]#第二個(gè)決策變量邊界,1表示包含范圍的邊界,0表示不包含 #生成自變量的范圍矩陣,使得第一行為所有決策變量的下界,第二行為上界 ranges=np.vstack([x1, x2]).T #生成自變量的邊界矩陣 borders=np.vstack([b1, b2]).T varTypes = np.array([0, 0])#決策變量的類型,0表示連續(xù),1表示離散 """==========================染色體編碼設(shè)置=========================""" Encoding ='BG'#'BG'表示采用二進(jìn)制/格雷編碼 codes = [1, 1]#決策變量的編碼方式,兩個(gè)1表示變量均使用格雷編碼 precisions =[6, 6]#決策變量的編碼精度,表示解碼后能表示的決策變量的精度可達(dá)到小數(shù)點(diǎn)后6位 scales = [0, 0]#0表示采用算術(shù)刻度,1表示采用對數(shù)刻度#調(diào)用函數(shù)創(chuàng)建譯碼矩陣 FieldD =ea.crtfld(Encoding,varTypes,ranges,borders,precisions,codes,scales) """=========================遺傳算法參數(shù)設(shè)置========================""" NIND = 20#種群個(gè)體數(shù)目 MAXGEN = 100#最大遺傳代數(shù) maxormins = np.array([1])#表示目標(biāo)函數(shù)是最小化,元素為-1則表示對應(yīng)的目標(biāo)函數(shù)是最大化 selectStyle ='sus'#采用隨機(jī)抽樣選擇 recStyle ='xovdp'#采用兩點(diǎn)交叉 mutStyle ='mutbin'#采用二進(jìn)制染色體的變異算子 Lind =int(np.sum(FieldD[0, :]))#計(jì)算染色體長度 pc= 0.9#交叉概率 pm= 1/Lind#變異概率 obj_trace = np.zeros((MAXGEN, 2))#定義目標(biāo)函數(shù)值記錄器 var_trace = np.zeros((MAXGEN, Lind))#染色體記錄器,記錄歷代最優(yōu)個(gè)體的染色體 """=========================開始遺傳算法進(jìn)化========================""" start_time = time.time()#開始計(jì)時(shí) Chrom = ea.crtpc(Encoding,NIND, FieldD)#生成種群染色體矩陣 variable = ea.bs2ri(Chrom, FieldD)#對初始種群進(jìn)行解碼 ObjV = aim(variable)#計(jì)算初始種群個(gè)體的目標(biāo)函數(shù)值 best_ind = np.argmin(ObjV)#計(jì)算當(dāng)代最優(yōu)個(gè)體的序號 #開始進(jìn)化 for gen in range(MAXGEN): FitnV = ea.ranking(maxormins * ObjV)#根據(jù)目標(biāo)函數(shù)大小分配適應(yīng)度值 SelCh = Chrom[ea.selecting(selectStyle,FitnV,NIND-1),:]#選擇 SelCh = ea.recombin(recStyle, SelCh, pc)#重組 SelCh = ea.mutate(mutStyle, Encoding, SelCh, pm)#變異 # #把父代精英個(gè)體與子代的染色體進(jìn)行合并,得到新一代種群 Chrom = np.vstack([Chrom[best_ind, :], SelCh]) Phen = ea.bs2ri(Chrom, FieldD)#對種群進(jìn)行解碼(二進(jìn)制轉(zhuǎn)十進(jìn)制) ObjV = aim(Phen)#求種群個(gè)體的目標(biāo)函數(shù)值 #記錄 best_ind = np.argmin(ObjV)#計(jì)算當(dāng)代最優(yōu)個(gè)體的序號 obj_trace[gen,0]=np.sum(ObjV)/ObjV.shape[0]#記錄當(dāng)代種群的目標(biāo)函數(shù)均值 obj_trace[gen,1]=ObjV[best_ind]#記錄當(dāng)代種群最優(yōu)個(gè)體目標(biāo)函數(shù)值 var_trace[gen,:]=Chrom[best_ind,:]#記錄當(dāng)代種群最優(yōu)個(gè)體的染色體 # 進(jìn)化完成 end_time = time.time()#結(jié)束計(jì)時(shí) ea.trcplot(obj_trace, [['種群個(gè)體平均目標(biāo)函數(shù)值','種群最優(yōu)個(gè)體目標(biāo)函數(shù)值']])#繪制圖像 """============================輸出結(jié)果============================""" best_gen = np.argmin(obj_trace[:, [1]]) print('最優(yōu)解的目標(biāo)函數(shù)值:', obj_trace[best_gen, 1]) variable = ea.bs2ri(var_trace[[best_gen], :], FieldD)#解碼得到表現(xiàn)型(即對應(yīng)的決策變量值) print('最優(yōu)解的決策變量值為:') for i in range(variable.shape[1]): print('x'+str(i)+'=',variable[0, i]) print('用時(shí):', end_time - start_time,'秒')
效果圖:
結(jié)果如下:
5.參考文章
鏈接: geatpy說明文檔.
到此這篇關(guān)于python遺傳算法之geatpy的深入理解的文章就介紹到這了,更多相關(guān)python遺傳算法之geatpy內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python讀寫及備份oracle數(shù)據(jù)庫操作示例
這篇文章主要介紹了Python讀寫及備份oracle數(shù)據(jù)庫操作,結(jié)合實(shí)例形式分析了Python針對Oracle數(shù)據(jù)庫操作的相關(guān)庫安裝,以及使用cx_Oracle與pandas庫進(jìn)行Oracle數(shù)據(jù)庫的查詢、插入、備份等操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-05-05Python實(shí)現(xiàn)感知機(jī)(PLA)算法
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)感知機(jī)(PLA)算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12基于python實(shí)現(xiàn)可視化生成二維碼工具
這篇文章主要介紹了基于python實(shí)現(xiàn)可視化生成二維碼工具,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07詳解python中的lambda與sorted函數(shù)
這篇文章主要介紹了python中的lambda與sorted函數(shù)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下2020-09-09Python進(jìn)階篇之正則表達(dá)式常用語法總結(jié)
正則表達(dá)式是一個(gè)特殊的字符序列,它能幫助你方便的檢查一個(gè)字符串是否與某種模式匹配。本文為大家總結(jié)了一些正則表達(dá)式常用語法,希望有所幫助2022-08-08tensorflow實(shí)現(xiàn)tensor中滿足某一條件的數(shù)值取出組成新的tensor
今天小編就為大家分享一篇tensorflow實(shí)現(xiàn)tensor中滿足某一條件的數(shù)值取出組成新的tensor,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01python自動(dòng)化測試之DDT數(shù)據(jù)驅(qū)動(dòng)的實(shí)現(xiàn)代碼
這篇文章主要介紹了python自動(dòng)化測試之DDT數(shù)據(jù)驅(qū)動(dòng)的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07pycharm 如何取消連按兩下shift出現(xiàn)的全局搜索
這篇文章主要介紹了pycharm 如何取消連按兩下shift出現(xiàn)的全局搜索?下面小編就為大家介紹一下解決方法,還等什么?一起跟隨小編過來看看吧2021-01-01將tf.batch_matmul替換成tf.matmul的實(shí)現(xiàn)
這篇文章主要介紹了將tf.batch_matmul替換成tf.matmul的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06