遺傳演算法庫DEAP的示例程式碼的學習和分析
最近看到用遺傳演算法最佳化量化引數的文章,覺得還是有很先進,就開始學習。這個文章主要是針對遺傳演算法庫DEAP的示例程式碼的學習和分析。
程式碼連結:其實有不少針對這段程式碼文章,這裡主要說說自己學習和體會。
原文連結如下:
在分析程式碼前,先說說這段程式碼幹了什麼。這段程式碼就是如果有一個陣列有十個隨機陣列成,如何得到一組十個最小隨機數,其和是最小的。理論上,最小的就是組合就是10個0,但是因這裡面因為引入了變異,可以獲得負數,所以可以組合變異生成負數值。
1. 定義型別,方法creator.create(name,base,**kargs)
這個有點類似設計模式的工廠模式,這個方法建立一個新的類,名字為引數name,繼承的父類為base,這個類的屬性如之後的引數名稱和引數值。
creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) 對應的就是類建立程式碼: class FitnessMin(base.Fitness): weights=(-1.0,) def __init__(self, values=()): super(FitnessMin, self).__init__(values=()) creator.create("Individual", list, fitness=creator.FitnessMin) 對應的就是類建立程式碼: class Individul(list): self.fitness=FitnessMin def __init__(self): ….
1.1 然後取看看base.Fitness這個父類,關鍵是weights這個屬性,主要是做比較用。分析程式碼,會發現把傳入的values序列和weights序列相乘,轉為元祖wvalues,返回的時候就相除返回values
defgetValues(self): returntuple(map(truediv,self.wvalues,self.weights)) defsetValues(self,values): try: self.wvalues=tuple(map(mul,values,self.weights))
2. 註冊方法;方法 toolbox.register (self,alias,function,*args,**kargs)
這個是一個比較核心的方法,引數第一個是別名,第二個是需要繫結的真正function,之後其實是針對這個方法的引數。這樣做就可以把方法和引數二次打包成一個新方法用於遺傳演算法,類似於方法覆蓋。
2.1 toolbox.register("attribute", random.random)
比如這個,就是給toolbox註冊了random.random,使用" attribute "別名,就是random.random()返回一個0-1直接隨機數,呼叫時候就是直接用toolbox.attr_float()
2.2 toolbox.register("individual", tools.initRepeat, creator.Individual,
toolbox.attr_float, n=IND_SIZE)
這個更加難以理解 , 是註冊一個方法別名“ individual ”,關聯 tools 原生方法 iniRepeat ,並且呼叫了三個引數。其中creator.Individual的父類就是 list ; 而toolbox.attr_float實際就是 random.random ; toolbox . individual實際效果就是initRepeat(list, random.random, 10 )。initRepeat(container, func, n)定義就是用 func 生成 n 個返回值,放在 container 。顯示出來如下一個數列裡面放置 10 個隨機數。
2.3 toolbox.register("population", tools.initRepeat, list, toolbox.individual)
有了上面基礎這個就理解,用一個list作為容器,然後防止toolbox.individual生成的隨機數list,組成雙層list。但是沒有給重複次數,所以要在呼叫時候給定。比如兩次的效果。
3. 定義運算, 方法還是之前註冊 register 方法,最重要就是 evaluate 這個方法必須自己實現。
3.1 def evaluate(individual):
return sum(individual),
toolbox.register("evaluate", evaluate)
實際呼叫就是把之前individual的list中是個隨機數,算出來隨機數求和。
3.2 toolbox.register("mate", tools.cxTwoPoint)
這個方法是交叉,輸入兩個長度相同資料,通常是陣列;返回兩個同樣長度,但是組成元素交叉互換的;類似於遺傳中的基因交叉。
3.2 toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1)
這個方法是呼叫高斯變異,提供遺傳變異,高斯變異我也不懂。就像下圖顯示的,輸入一個陣列,返回的會陣列變動後如下。
其中引數mu按照介紹是均值;sigma是標準差,這個值決定變異強度,如果sigma為0時候,沒有變異;indpb是獨立機率(Independent probability),決定變異機率,如果為1時候,所有元素都會變異,如果是0.1,就是0.1機率;
3.3 toolbox.register("select", tools.selTournament, tournsize=3)
這個方法呼叫的是
def selTournament(individuals, k, tournsize, fit_attr= "fitness" ):
輸入一個資料組集合,比如有 10 組 individual 資料組; k 是舉行多少次選拔,每舉行一次選拔得到一個最優解,如果 k 是 len(pop1) ,最後返回就是同樣長度陣列; tournsize 是每次在十個裡面選擇多少個個參加選拔,這裡選擇是隨機的,所以結果也是也看得到,雖然選擇最小,但是有 5.188 這樣明顯很大的。還有就是就算 tournsize 改成 10 ,返回應該就是最小單一值把,試了發現還不是,每次選參賽 individual 是可以重複的,就是可以有一個 individual 重複參加,算是一個邏輯 bug 。
還有就是就算 tournsize 改成 10情況
4. 演算法,前面所有要求的都定義好,後面就是一步步繁殖變異篩選了
pop = toolbox.population(n=50)
首先使用polulation方法生成一個50個individual例項,就像前面說的individual是一個有10個0-1隨機陣列成陣列。
fitnesses = map(toolbox.evaluate, pop)
利用map方法,對於pop這個list中每個individual操作,計算出每個individual是個隨機數的和,返回一個元祖。50個individual返回就是50個元祖。
for ind, fit in zip(pop, fitnesses):
ind.fitness.values = fit
這個使用了zip方法,把兩個陣列組合成一個新的元祖陣列,這個元祖包括一個individual陣列和fitness元祖,然後用ind,和fit遍歷,再把fit值賦值到individual上。
上面完成了第一代50個inidividual維護。
後面開始繁殖,首先定義出一些引數,後面用到時候說明。
CXPB, MUTPB, NGEN = 0.5, 0.2, 40
後面就是一個很長的邏輯,首先第一個定義了NGEN,進行多少代繁殖篩選,這裡NGEN是40代。
然後使用select方法,進行50次選拔,每次三個,保留其中individual fitnes最新的那個。
第一遍的select只是引用,所以還要克隆。
然後利用zip,把offspring中兩個不同individual組合成一個元祖陣列,這個元祖有兩個不同individual,然後有50%機會進行交叉繁殖。
同時有20%機會進行突變。
突變和繁殖後,這些individual都沒有fitness,後面就是就是給這些繁殖和突變的individual計算fitness並繫結。
然後用所以的下一代代替上一代。最後經過四十代繁殖返回pop
for g in range(NGEN): # Select the next generation individuals offspring = toolbox.select(pop, len(pop)) # Clone the selected individuals offspring = map(toolbox.clone, offspring) # Apply crossover and mutation on the offspring for child1, child2 in zip(offspring[::2], offspring[1::2]): if random.random() < CXPB: toolbox.mate(child1, child2) del child1.fitness.values del child2.fitness.values for mutant in offspring: if random.random() < MUTPB: toolbox.mutate(mutant) del mutant.fitness.values # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if not ind.fitness.valid] fitnesses = map(toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit # The population is entirely replaced by the offspring pop[:] = offspring
5. 執行 main() 就可以等到 40 代以後的 pop ,然後可以用遍歷發現各個 sum 都是負數,由於原來隨機並不會產生負數,應該都是高斯變異突變效果,而這些突變也很好保留下來。
最後, best_ind = tools.selBest(pop, 1 )[ ] 可以等到最好的一個 individual ,發現 individual 裡面都是負數,都是突變的值。
pop = main() for individual in pop: print(individual.fitness.values) print("-- End of (successful) evolution --") best_ind = tools.selBest(pop, 1)[0] print best_ind, best_ind.fitness.values
最後原始碼可以在我的GitHub裡面找到,
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22259926/viewspace-2639405/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 利用遺傳演算法庫DEAP優化交易策略演算法優化
- 優化演算法庫DEAP的粒子群優化演算法(PSO)示例程式碼分析優化演算法
- Python遺傳演算法框架DEAP-Operators and AlgorithmsPython演算法框架Go
- Python遺傳演算法框架DEAP-Creating TypesPython演算法框架
- 如何學習python遺傳演算法?Python演算法
- 粒子群演算法和遺傳演算法的比較演算法
- 基於Python的遺傳演算法特徵約簡(附程式碼)Python演算法特徵
- 遺傳演算法的基本框架演算法框架
- 遺傳演算法演算法
- Python-遺傳演算法君主交叉程式碼實現Python演算法
- 遺傳演算法 (轉)演算法
- swfupload的ASP上傳示例程式碼
- 基於遺傳演算法的地圖四色原理繪圖上色的Python程式碼演算法地圖繪圖Python
- 利用遺傳學演算法求解工作分配問題演算法
- 遺傳演算法到強化學習,一文介紹五大生物啟發式學習演算法演算法強化學習
- 透過MATLAB分別對比二進位制編碼遺傳最佳化演算法和實數編碼遺傳最佳化演算法Matlab演算法
- 常見的PID的演算法及程式碼示例演算法
- Spring 註解學習 詳細程式碼示例Spring
- 遺傳演算法(一):Basic GA演算法
- 遺傳演算法 (Genetic Algorithm)演算法Go
- 基於遺傳演算法的HFSS和C#聯合模擬(一)演算法C#
- 以中國傳統的孔子和老子的思想來分析忍者程式碼
- pytorch深度學習分類程式碼簡單示例PyTorch深度學習
- 重構遺留程式碼(9):分析 Concerns
- MATLAB實戰系列(十一)-多種群遺傳演算法的函式優化演算法(附MATLAB程式碼)Matlab演算法函式優化
- 人工智慧 (13) 遺傳演算法人工智慧演算法
- 10分鐘搞懂遺傳演算法演算法
- python遺傳演算法(詳解)Python演算法
- werkzeug原始碼分析——從官網的示例程式碼開始原始碼
- xargs 的示例程式碼.
- 遺傳演算法詳解與實驗演算法
- 遺傳演算法解決TSP問題演算法
- 遺傳演算法組卷使用心得演算法
- 遺傳演算法與C++實現演算法C++
- 遺傳演算法講解(Matlab描述)演算法Matlab
- SharePreference原始碼學習和多程式的場景原始碼
- 元啟發式演算法庫 MEALPY 初體驗-遺傳演算法為例演算法
- 開發人員使用遺留程式碼庫指南