關於遺傳演算法
遺傳演算法是仿照自然界中生物進化而產生的一類優化演算法。個人感覺遺傳演算法簡單粗暴,適應性廣。關於遺傳演算法的介紹網上有很多了,這裡按照我自己的理解簡單概括一下。
編碼解碼,將待優化的引數編碼為dna序列,最簡單直接的為二進位制編碼(即有兩種鹼基的dna鏈);
生成隨機初代
選擇,適應度(由待優化的模型得到)較好的個體有更大的概率被選擇,應用比較多的方法有輪盤賭和錦標賽;
按照一定概率進行隨機的交叉變異
goto step 2
經過多個世代的迭代之後,將會收斂到最優解。交叉和編譯的作用是產生新個體,避免陷入區域性最優解。
利用python實現
前輩們常說一句話「避免重複造輪子」,其實最直接的還是搜一下別人寫的包。這裡之所以花時間自己搞乙個主要是因為這個演算法比較簡單,邏輯性很明確,比較適合練手,因此才決定自己實現一下,算是敲開python大門的第乙個專案。
編碼解碼
這裡選擇使用二進位制編碼的方式來實現,根據使用者輸入的引數範圍和精度計算出每個引數需要的位數,然後將引數空間均分對映為二進位制編碼。
copy
# encode parameters into dna
def encode(self, parameters):
dna = ''
for i in range(self.ngenes):
genesequencedigit = (parameters[i]-self.parametersrange[i,0])/(self.parametersrange[i,1]-self.parametersrange[i,0])*(2**self.genelength[i]-1)
genesequencedigit = int(round(genesequencedigit))
genesequencebin = self.int2bin(genesequencedigit, self.genelength[i])
dna = dna + genesequencebin
dna = list(dna) # trun string to list
return dna
# decode dna to parameters
def decode(self, dna):
dna = ''.join(dna) # trun list to string
parameters =
for i in range(self.ngenes):
genesequencebin = dna[self.dnaidx[i,0]:self.dnaidx[i,1]+1]
genesequencedigit = self.bin2int(genesequencebin)
parameteri = genesequencedigit/(2**self.genelength[i]-1)*(self.parametersrange[i,1]-self.parametersrange[i,0])+self.parametersrange[i,0]
return parameters
# returns the binary string of integer n, using count number of digits
def int2bin(self, n, count=32):
binstr = "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])
return binstr
# returns digit integer of binary string
def bin2int(self, n):
ret = int(n,2)
return ret
這種方式實現的精度並不是確切的為使用者輸入的精度,而是要高於使用者的輸入精度。
選擇選擇的策略使用了名為錦標賽的方式,同時新增了精英保留機制。錦標賽是指隨機選擇n個(通常n=2)候選個體,再從中選擇最優的個體進入下一代,重複多次,直到子代規模達到要求。精英保留機制是是指保護已經產生的最優個體不被淘汰,不被交叉和變異破壞。
copy
# select individuals
def select(self):
ncandidates = 2
generation =
for i in range(self.popgeneration):
candidates = random.choices(self.generation, k=ncandidates)
fitnesslist = self.fitness(candidates=candidates)
bestfitness = max(fitnesslist)
idx = fitnesslist.index(bestfitness)
self.generation = generation
return
# elitist preservation
def elitistpreservation(self):
bestfitness = max(self.fitnesslist)
if bestfitness > self.bestfitness:
idx = self.fitnesslist.index(bestfitness)
self.bestfitness = bestfitness
self.bestindividual = self.generation[idx].copy()
else:
worstindividual = min(self.fitnesslist)
idx = self.fitnesslist.index(worstindividual)
self.generation[idx] = self.bestindividual.copy()
self.fitnesslist[idx] = self.bestfitness
return
交叉和變異
交叉和編譯比較簡單,利用隨機數的方式來控制發生的概率。這裡值得一提的是,現實中可能會發生多點的變異或者交叉,只不過概率非常低,在遺傳演算法的實現中如果僅僅採用單點的交叉和變異也是可以的。
**和例子
使用例程:
copy
import geneticalgorithm as ga # 匯入geneticalgorithm模組
import math
# 根據具體的優化目標設計適應度函式,par為輸入引數的列表,ret為適應度
def fitness(par):
x = par[0]
ret = x*math.sin(10*math.pi*x)+2
return ret
maxgen = 500 # 迭代次數
popgeneration = 50 # 每個世代的個體數目
pcross = 0.1 # 發生交叉的概率
pmutation = 0.05 # 發生變異的概率
ngenes = 1 # 待優化的引數的個數
parametersrange = [[-1, 2, 0.01]] # 待優化引數的範圍及要求的精度,多個引數寫法:[[-1, 2, 0.01],[-2, 3, 0.1]]
# 建立ga物件
ga = ga.geneticalgorithm(maxgen, popgeneration, pcross, pmutation, ngenes, parametersrange, fitness)
# 顯示物件資訊
ga.info()
# 執行優化
ga.run()
# 顯示最優解
ga.result()
遺傳演算法 python 簡書 遺傳演算法
優化的演算法有很多種,從最基本的梯度下降法到現在的一些啟發式演算法,如遺傳演算法 ga 差分演化演算法 de 粒子群演算法 pso 和人工蜂群演算法 abc 舉乙個例子,遺傳演算法和梯度下降 梯度下降和遺傳演算法都是優化演算法,而梯度下降只是其中最基礎的那乙個,它依靠梯度與方向導數的關係計算出最優值...
遺傳演算法python實現
i 實現功能 求解函式 f x x 10 sin 5 x 7 cos 4 x 在區間 0,9 的最大值 ii 原理 遺傳演算法 genetic algorithm 遵循 適者生存 優勝劣汰 的原則,是一類借鑑生物界自然選擇和自然遺傳機制的隨機化搜尋演算法。遺傳演算法模擬乙個人工種群的進化過程,通過選...
遺傳演算法 python實現
encoding utf 8 import math import random import operator class ga def init self,length,count 染色體長度 self.length length 種群中的染色體數量 self.count count 隨機生成初...