莫烦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这部分是相当重要的。为什么此时代码简便了这么多?
最主要的原因是此算法不需要父辈进行杂交培育后代

那他是怎么进行的呢?

举个例子:

3-2-0.gif

红点是父辈,当我比子代优秀的时候,我就一直在,子代受不了就自杀,当子代优于父辈的时候,父辈觉得很欣慰,便自己消失了,循环往复,直到某一代达到武林巅峰,在这个过程中,是什么决定了子代?实际上只有变异,因为我们的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,莫神就已经说得很明白了
image-20210628165434783

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()
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值