laohyx 2020-01-23
遗传算法模仿了生物遗传进化的过程,可以在给定范围内搜索最优解。遗传算法的设计一般包括参数编码、初始群体的设定、适应度函数的设计、遗传操作设计(选择、交叉、变异)、控制参数设定等。
在这里,我们基于python使用遗传算法尝试搜索函数
\(y = -x^2+2x+5\)
在区间\([0,63]\)内的最大值,简便起见只取区间内的整数。
对于本问题,用6个二进制位即可表示0~63的所有整数,其中每组编码可视为一条染色体或个体,具体编码如下:
\([0,0,0,0,0,0,0]\)
...
\([1,1,1,1,1,1,1]\)
在这里假设种群一直维持有4条染色体,随机初始化后如下:
\([0,0,1,0,1,0,0]\)
\([1,0,0,1,0,0,0]\)
\([0,0,1,0,0,0,1]\)
\([0,1,0,0,0,1,0]\)
适应度函数在这里直接取函数的值,即函数值越大其适应度越高。
在这个阶段直接舍弃掉适应度低的两条染色体,选择适应度高的两条染色体来产生新的染色体。
假设上一步选择的两条染色体为:
\([0,0,0,0,0,0,0]\)
\([1,1,1,1,1,1,1]\)
交叉时首先随机选择交叉点,比如为第三个,则交叉后产生的的染色体为:
\([0,0,0,1,1,1,1]\)
\([1,1,1,0,0,0,0]\)
对上一步新产生的染色体,首先以一定的变异率来决定是否变异,然后同样的随机选择变异点,将该位置基因反转。最后再将产生的两条新染色体添加进种群中,这样就完成了一次遗传迭代操作,反复进行迭代就有可能搜索到最优解。
import random class Chromosome(object): def __init__(self, chrom=None): # 随机初始化一个染色体 if chrom == None: self.chrom = [] for _ in range(6): _num = random.randint(0, 1) self.chrom.append(_num) # 直接赋值一个染色体 else: self.chrom = chrom # 适应度函数 def fit_score(self): _str = '' for i in self.chrom: _str += str(i) _num = int(_str, 2) return 5 - _num * _num + _num * 2 # 交叉函数 def cross(self, Chrom, cross_rate): cross_idx = random.randint(0, 5) child_chrom1 = self.chrom[:cross_idx] + Chrom.chrom[cross_idx:] child_chrom2 = Chrom.chrom[:cross_idx] + self.chrom[cross_idx:] return Chromosome(child_chrom1), Chromosome(child_chrom2) # 变异函数 def vary(self, vary_rate): _num = random.randint(1, 10) if _num <= 10*vary_rate: # 模拟变异率 cross_idx = random.randint(0, 5) if self.chrom[cross_idx] == 0: self.chrom[cross_idx] = 1 else: self.chrom[cross_idx] = 0 def one_iter(population, cross_rate=0.8, vary_rate=0.2): # 选择使用排序法 取适应度最高值 # 交叉使用随机单点交叉 cross_rate=交叉率 (暂未开启) # 变异使用随机反转变异 vary_rate=变异率 population.sort(key=lambda x:x.fit_score(), reverse=True) population.pop() population.pop() child_chrom1, child_chrom2 = population[0].cross(population[1], cross_rate) child_chrom1.vary(vary_rate) child_chrom2.vary(vary_rate) population.append(child_chrom1) population.append(child_chrom2) def main(): population = [Chromosome(), Chromosome(), Chromosome(), Chromosome()] for _ in range(50): one_iter(population) population.sort(key=lambda x: x.fit_score(), reverse=True) print(population[0].chrom, population[0].fit_score()) if __name__ == '__main__': main()
上述内容只是对遗传算法最浅显的解释,每种操作都尽可能简化,如需深入了解,还请参考其他内容。