莫烦python之进化策略(1+1)-ES
莫神视频:https://mofanpy.com/tutorials/machine-learning/evolutionary-algorithm/evolution-strategy-1plus1-ES/
第一部分比较容易理解,就是字面上代码的意思
""" (1+1)-ES with 1/5th success rule with visualization. Visit my tutorial website for more: https://mofanpy.com/tutorials/ 统一来说都是 (μ/ρ +, λ)-ES, (1+1)-ES 只是一种特殊形式. 这里的 μ 是 population 的数量, ρ 是从 population 中选取的个数, 用来生成宝宝的. λ 是生成的宝宝数, 如果采用的是 + 形式的, 就是使用将 ρ + λ 混合起来进行适者生存, 如果是 , 形式, 那么就是只使用 λ 进行适者生存. """ # 形式多种多样有些头疼. 不过在这一节中, 我们考虑的只是一个爸爸, 生成一个宝宝, # 然后在爸爸和宝宝中进行适者生存的游戏, 选择爸爸和宝宝中比较好的那个当做下一代的爸爸. (1+1)-ES 总结如下: # 有一个爸爸; # 根据爸爸变异出一个宝宝; # 在爸爸和宝宝中选好的那个变成下一代爸爸. import numpy as np import matplotlib.pyplot as plt DNA_SIZE = 1 # DNA (real number) DNA_BOUND = [0, 5] # solution upper and lower bounds N_GENERATIONS = 200 MUT_STRENGTH = 5. # initial step size (dynamic mutation strength) def F(x): return np.sin(10*x)*x + np.cos(2*x)*x # to find the maximum of this function # find non-zero fitness for selection def get_fitness(pred): return pred.flatten()
make_kid这部分是相当重要的。为什么此时代码简便了这么多? 最主要的原因是此算法不需要父辈进行杂交培育后代
那他是怎么进行的呢?
举个例子:
红点是父辈,当我比子代优秀的时候,我就一直在,子代受不了就自杀,当子代优于父辈的时候,父辈觉得很欣慰,便自己消失了,循环往复,直到某一代达到武林巅峰,在这个过程中,是什么决定了子代?实际上只有变异,因为我们的DNA实际上也只有横坐标。
def make_kid(parent): # no crossover, only mutation # 不用选父辈,因此简化了,只有变异 k = parent + MUT_STRENGTH * np.random.randn(DNA_SIZE) # 限制在(0,5) k = np.clip(k, *DNA_BOUND) return k
kill_bad,莫神就已经说得很明白了
def kill_bad(parent, kid): global MUT_STRENGTH # 参考文献:Rechenberg, I. 1973. Evolutionsstrategie – Optimierung technischer Systeme nach Prinzipien # der biologischen Evolution, Frommann-Holzboog. # 计算父亲和孩子的fitness fp = get_fitness(F(parent))[0] fk = get_fitness(F(kid))[0] # 网上有个课件Tutorial: CMA-ES — Evolution Strategies and Covariance Matrix Adaptation里面一张图, 让你秒懂这个1/5的意思. p_target = 1/5 if fp < fk: # kid better than parent parent = kid ps = 1. # kid win -> ps = 1 (successful offspring) else: ps = 0. # adjust global mutation strength MUT_STRENGTH *= np.exp(1/np.sqrt(DNA_SIZE+1) * (ps - p_target)/(1 - p_target)) return parent parent = 5 * np.random.rand(DNA_SIZE) # parent DNA plt.ion() # something about plotting x = np.linspace(*DNA_BOUND, 200) for _ in range(N_GENERATIONS): # ES part kid = make_kid(parent) py, ky = F(parent), F(kid) # for later plot parent = kill_bad(parent, kid) # something about plotting plt.cla() plt.scatter(parent, py, s=200, lw=0, c=red, alpha=0.5,) plt.scatter(kid, ky, s=200, lw=0, c=blue, alpha=0.5) plt.text(0, -7, Mutation strength=%.2f % MUT_STRENGTH) plt.plot(x, F(x)) plt.pause(0.05) plt.ioff() plt.show()
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
Java调用Redis的Lua脚本功能