【Python Deap庫】遺傳算法/遺傳編程 進化算法基於python DEAP庫深度解析講解

前言

看了很多,發現這個遺傳算法,進化算法是一個非常有用的一個方法。而且可解釋性遠遠強於神經網絡。之前寫了一篇博文,專門講解基於DEAP庫的python編程,來編寫遺傳算法,但是那一篇主要偏重代碼,出於想要深入理解代碼的含義,因此專門記下這篇博文,既是筆記,也是分享。


所有的用python實現的代碼,請看這個博文:
GEAP 遺傳算法/遺傳編程 genetic programming + python(deap庫)實現
如果需要還有這兩個:
遺傳算法GA和遺傳編程GP有什麼不同?
粒子羣算法PSO 和 遺傳算法GA 的相同點和不同點


概述

“物競天擇,優勝劣汰”, 達爾文提出了著名的生物進化理論,即所有的動植物都是由較早期、較原始的形式演變而來的。而遺傳編程(遺傳規劃)則在數學和計算機科學領域應用了這一演化過程:從基數較爲龐大的原始、粗糙的程序種羣中通過評估適應性選擇父系、進行遺傳操作生成新一代種羣,再判斷終止條件決定是否再次迭代、生成下一代種羣。類比如下:
在這裏插入圖片描述
在這裏插入圖片描述
講到這裏可否理解了,進化算法的本質就是模擬優勝劣汰,下面進入正題

啓發式的理解(重點)

整個包含以下幾個方面!一定要看一下

  1. 個體編碼(Individual representation): 將問題的解空間編碼映射到搜索空間的過程。常用的編碼方式有二值編碼(Binary),格雷編碼(Gray),浮點編碼(Floating-point)等。
    簡單的說就是你怎麼表示一個個體,使用01010101010101來表示一個個體,還是用1238583241來表示一個個體
  2. 評價(Evaluation): 設定一定的準則評價族羣內每個個體的優秀程度。這種優秀程度通常稱爲適應度(Fitness)。
    基於你的個體編碼,判斷你的個體編碼好不好的一個評價函數
  3. 配種選擇(Mating selection): 建立準則從父代中選擇個體參與育種。儘可能選擇精英個體的同時也應當維護種羣的多樣性,避免算法過早陷入局部最優。
    你要選擇哪些個體參與育種,也就是參與下面那一個環節
  4. 變異(Variation): 變異過程包括一系列受到生物啓發的操作,例如重組(Recombination),突變(mutation)等。通過變異操作,父代的個體編碼以一定方式繼承和重新組合後,形成後代族羣。
    保留下來的個體,進行重組,突變等等
  5. 環境選擇(Environmental selection): 將父代與子代重組成新的族羣。這個過程中育種得到的後代被重新插入到父代種羣中,替換父代種羣的部分或全體,形成具有與前代相近規模的新族羣。
    生下來的個體 按道理講應該是比父類數量少的,一般都會補全到和父類的size相同,補全的方案就叫做環境選擇
  6. 停止準則(Stopping crieterion): 確定算法何時停止,通常有兩種情況:算法已經找到最優解或者算法已經選入局部最優,不能繼續在解空間內搜索。

咱們看個流程圖理解理解:
在這裏插入圖片描述

優化問題的定義

這個不再理解範圍內,但是,如果要用python編程進化算法的話,就需要先設置這個問題。
單優化問題creator.create('FitnessMin', base.Fitness, weights=(-1.0, ))

  • 在創建單目標優化問題時,weights用來指示最大化和最小化。此處-1.0即代表問題是一個最小化問題,對於最大化,應將weights改爲正數,如1.0。
  • 另外即使是單目標優化,weights也需要是一個tuple,以保證單目標和多目標優化時數據結構的統一。
  • 對於單目標優化問題,weights 的絕對值沒有意義,只要符號選擇正確即可。

多優化問題:creator.create('FitnessMulti', base.Fitness, weights=(-1.0, 1.0))

  • 對於多目標優化問題,weights用來指示多個優化目標之間的相對重要程度以及最大化最小化。如示例中給出的(-1.0, 1.0)代表對第一個目標函數取最小值,對第二個目標函數取最大值。

個體編碼

  • 實數編碼(Value encoding):直接用實數對變量進行編碼。優點是不用解碼,基因表達非常簡潔,而且能對應連續區間。但是實數編碼後搜索區間連續,因此容易陷入局部最優。
  • 二進制編碼(Binary encoding):在二進制編碼中,用01兩種數字模擬人類染色體中的4中鹼基,用一定長度的01字符串來描述變量。其優點在於種羣多樣性大,但是需要解碼,而且不連續,容易產生Hamming cliff(例如0111=7, 1000=8,改動了全部的4位數字之後,實際值只變動了1),在接近局部最優位置時,染色體稍有變動,就會使變量產生很大偏移(格雷編碼(Gray coding)能夠克服漢明距離的問題,但是實際問題複雜度較大時,格雷編碼很難精確描述問題)。
    在這裏插入圖片描述
  • 序列編碼(Permutation encoding):通常在求解順序問題時用到,例如TSP問題。序列編碼中的每個染色體都是一個序列。
  • 粒子(Particles):粒子是一種特殊個體,主要用於粒子羣算法。相比普通的個體,它額外具有速度、速度限制並且能記錄最優位置。

初始族羣的創建

  • 一般族羣:這是最常用的族羣類型,族羣中沒有特別的順序或者子族羣。
    toolbox.register('population', tools.initRepeat, list, toolbox.individual)
  • 同類羣(Demes):同類羣即一個族羣中包含幾個子族羣。在有些算法中,會使用本地選擇(Local selection)挑選育種個體,這種情況下個體僅與同一鄰域的個體相互作用。
toolbox.register("deme", tools.initRepeat, list, toolbox.individual)

DEME_SIZES = 10, 50, 100
population = [toolbox.deme(n=i) for i in DEME_SIZES]
  • 粒子羣:粒子羣中的所有粒子共享全局最優。在實現時需要額外傳入全局最優位置與全局最優適應度給族羣。
creator.create("Swarm", list, gbest=None, gbestfit=creator.FitnessMax)
toolbox.register("swarm", tools.initRepeat, creator.Swarm, toolbox.particle)

評價

評價部分是根據任務的特性高度定製的,DEAP庫中並沒有預置的評價函數模版。
這裏給一個例子

from deap import base, creator, tools
import numpy as np
# 定義問題
creator.create('FitnessMin', base.Fitness, weights=(-1.0,)) #優化目標:單變量,求最小值
creator.create('Individual', list, fitness = creator.FitnessMin) #創建Individual類,繼承list

# 生成個體
IND_SIZE = 5
toolbox = base.Toolbox()
toolbox.register('Attr_float', np.random.rand)
toolbox.register('Individual', tools.initRepeat, creator.Individual, toolbox.Attr_float, n=IND_SIZE)

# 生成初始族羣
N_POP = 10
toolbox.register('Population', tools.initRepeat, list, toolbox.Individual)
pop = toolbox.Population(n = N_POP)

# 定義評價函數
def evaluate(individual):
  return sum(individual), #注意這個逗號,即使是單變量優化問題,也需要返回tuple

# 評價初始族羣
toolbox.register('Evaluate', evaluate)
fitnesses = map(toolbox.Evaluate, pop)
for ind, fit in zip(pop, fitnesses):
  ind.fitness.values = fit
  print(ind.fitness.values)

# 結果:
# (2.593989197511478,)
# (1.1287944225903104,)
# (2.6030877077096717,)
# (3.304964061515382,)
# (2.534627558467466,)
# (2.4697149450205536,)
# (2.344837782191844,)
# (1.8959030773060852,)
# (2.5192475334239,)
# (3.5069764929866585,)

配種選擇

錦標賽

deap.tools.selTournament(individuals, k, tournsize, fit_attr = 'fitness')

錦標賽選擇顧名思義,就是模擬錦標賽的方式,首先在族羣中隨機抽取tournsize個個體,然後從中選取具有最佳適應度的個體,將此過程重複k次,獲得育種族羣。tournsize越大,選擇強度(selection intensity)越高,在選擇之後留下的育種族羣的平均適應度也就越高。比較常用的tournsize是2。
假設tournsize是2,就是在原來的種羣中取出來2個,然後再這兩個中選一個最適應的,然後重複k次,我們就可以得到k個最適應的,這個就是育種族羣,用來後面生孩子重組基因的;
在這裏插入圖片描述
如圖,假設這個族羣有5個人,tournsize爲3,就是選出來3個人,然後在3個人中選取一個最好的
錦標賽選擇相比於輪盤賭選擇,通常能夠有更快的收斂速度,在實際場景中應用較多。

輪盤賭選擇

deap.tools.selRoulette(individuals, k, fit_attr = 'fitness')
在輪盤賭選擇中,每個個體a被選中的概率P(a)與他的評價函數f(a)成正比

\[P(a_i) = \frac{f(a_i)}{\sum_j f(a_j)} \]

但是如果評價函數出現負數,就不適用
並且很多文章指出來,輪盤賭選擇的效果並不好

隨機普遍抽樣選擇

deap.tools.selStochasticUniversalSampling(individuals, k, fit_attr = 'fitness')
隨機普遍抽樣選擇是一種有多個指針的輪盤賭選擇,其優點是能夠保存族羣多樣性,而不會像輪盤賭一樣,有較大機率對重複選擇最優個體。

在與前文相同的例子中使用隨機普遍抽樣選擇,設定指針數k爲3,那麼指針間距即爲,如下圖所示:
在這裏插入圖片描述
就是我一選就選3個個體,一選選3個,保證了多樣性

變異

單點交叉

deap.tools.cxOnePoint(ind1, ind2)

  • 最簡單的交叉方式,選擇一個切口,將兩條基因切開之後,交換尾部基因段。儘管該方法非常簡單,但是多篇文章指出,該算法在各種實驗中性能都被其他交叉算法吊打,因此算是一種不建議使用的loser algorithm
    在這裏插入圖片描述

兩點交叉

deap.tools.cxTwoPoint(ind1, ind2)

  • 用兩個點切開基因之後,交換切出來的基因段
    在這裏插入圖片描述

均勻交叉

deap.tools.cxUniform(ind1, ind2, indpb)

  • 指定一個變異機率,兩父代中的每個基因都以該機率交叉。
    在這裏插入圖片描述

部分匹配交叉

deap.tools.cxPartialyMatched(ind1, ind2)

  • 部分匹配交叉主要用於序列編碼的個體
  • 這個太難敘述了,能看懂就看,看不懂就記住在哪裏用就好了,就是上面那句話
    在這裏插入圖片描述

突變

高斯突變

tools.mutGaussian(individual, mu, sigma, indpb)

  • 對個體序列中的每一個基因按概率變異,變異後的值爲按均值爲mu,方差爲sigma的高斯分佈選取的一個隨機數。如果不希望均值發生變化,則應該將設mu爲0。

亂序突變

tools.mutShuffleIndexes(individual, indpb)

  • 將個體序列打亂順序,每個基因位置變動的機率由indpb給出。

位翻轉突變

tools.mutFlipBit(individual, indpb)

對個體中的每一個基因按給定對變異概率取非。

均勻整數突變

tools.mutUniformInt(individual, low, up, indpb)
對序列中的每一位按概率變異,變異後的值爲[low, up]中按均勻分佈隨機選取的一個整數。

環境選擇

完全重插入(Pure reinsertion)

  • 產生與父代個體數量相當的配種個體,直接用配種個體生成新一代族羣。

均勻重插入(Uniform reinsertion)

  • 產生比父代個體少的配種個體,用配種個體隨機均勻地替換父代個體。

精英重插入(Elitist reinsertion)

  • 產生比父代個體少的配種個體,選取配種後代中適應度最好的一些個體,插入父代中,取代適應度較低的父代個體。

精英保留重插入(Fitness-based reinsertion)

  • 產生比父代個體多的配種個體,選取其中適應度最大的配種個體形成新一代族羣。
    通常來說後兩種方式由於精英保留的緣故,收斂速度較快,因此比較推薦。

進化算法的python實現

GEAP 遺傳算法/遺傳編程 genetic programming + python(deap庫)實現

進化算法的優缺點

優點

  • 泛用性強,對連續變量和離散變量都能適用;

  • 不需要導數信息,因此不要求適應度函數的連續和可微性質(或者說不需要問題內在機理的相關信息);

  • 可以在解空間內大範圍並行搜索;

  • 不容易陷入局部最優;

  • 高度並行化,並且容易與其他優化方法整合。

  • 對於凸優化問題,相對基於梯度的優化方法(例如梯度下降法,牛頓/擬牛頓法)收斂速度更慢;

  • 進化算法需要在搜索空間投放大量個體來搜索最優解。對於高維問題,由於搜索空間隨維度指數級膨脹,需要投放的個體數也大幅增長,會導致收斂速度變慢;

  • 設計編碼方式、適應度函數以及變異規則需要大量經驗。
    簡單說最大的缺點就是慢

參考:
GEAP 遺傳算法/遺傳編程 genetic programming + python(deap庫)實現
【遺傳編程/基因規劃】Genetic Programming

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章