进化策略( µ , λ ) -ES附上python代码实现

ES算法模型

  • 个体表示
  • 适应度评价
  • 变异
  • 交叉
  • 选择

个体的表示方法

  • 个体是一个2n维向量,由实数解 x 和标准差sigma组成:
    X = { x, sigma }
    其中:x = [ x1, x2, ···,xn]表示个体特征,即基因。

  • 向量x是搜索空间中的一个点,即实数解;向量sigma是正态分布的标准差,它用于变异进化。

适应度评价

  • 取目标函数 f (x) 为适应度函数 F (x):

                          f ( x ) = F ( x )
    
  • 目标函数 f (x) 取值可取值为正或负,对其值只进行大小比较,决定优劣。适应度评价只和选择操作相关,其结果用于某种选择操作。

变异
对sigma进行变异:

sigma_temp = theta * sigma[:, pos[0]] + (1 - theta) * sigma[:, pos[1]]

再对Xi个体进行变异:

son_temp = out + sigma_temp * np.random.normal([2, 1])

选择
可以选择以下列出的方法:

  • ( 1+1 ) — ES:爬山法
  • ( 1, 1 ) — ES:随机搜索法
  • ( µ + 1 ) — ES:邻接搜索法
  • ( µ , 1 ) — ES:邻接搜索法
  • ( µ + λ ) — ES:保留最优个体的多点搜索法
  • ( µ , λ ) — ES:多点搜索法

本文使用了 ( µ , λ )

  • 先从父代  个个体中产生子代  个个体。

  • 再从子代  个个体中选出  个适应度最好的个体,作为新的父代个体。

  • ( µ , λ )选择只在λ个子代个体中进行,则父代中某个个体的适应度即使大大高于其他个体,也不能存活到下一代作为子代,造成搜索可能发散,因此只用于适应值函数是时变的情形和多处理机并行计算。

结果
计算多峰值函数的最大值:

import numpy as np

"""
ES-进化策略
(μ,λ) - ES算法从子代λ个个体中选择μ个个体作为新的父代
计算多峰值函数的最大值
"""

# ratio
ratio = 7
# 迭代代数
step = 0
# 期望最大值
E_MAX = 38.80
# 种群规模
N = 80
# x1、x2
res_x_y = []
# 范围
bound_x1 = [-0.3, 12.1]
bound_x2 = [4.1, 5.8]
# 初始化x1、x2
# 计算sigma 初始化种群
# 初始化可以修改为先生成[2,N]的正态分布 再给每一个计算具体的值
X = np.random.random([2, N])  # 生成初始种群矩阵,一列表示一个可行解
X[0] = (bound_x1[1] - bound_x1[0]) * X[0] + bound_x1[0]
X[1] = (bound_x2[1] - bound_x2[0]) * X[1] + bound_x2[0]
# 最大的适应度值
MAX_FITNESS = 0
# 迭代的代数 作为程序终止的条件
GEN = 200
# sigma
sigma = np.random.randn(2, N)
# theta
theta = 0.5
# out
out = np.zeros([2])
# son
son = np.zeros([2, ratio * N])
# fits
fits = np.zeros(son.shape[1])


# 计算适应度的函数
def F(x1, x2):
    return 21.5 + x1 * np.sin(4 * np.pi * x1) + x2 * np.sin(20 * np.pi * x2)


if __name__ == '__main__':
    while True:
        lamda = 1
        while lamda < ratio * N:
            # 随机生成两个位置 即找X中的两个种子进行变异
            pos = np.random.randint(0, N - 1, [1, 2])[0]
            # 找出两个种子
            index1 = X[:, pos[0]]
            index2 = X[:, pos[1]]
            # 再度随机交叉
            # random 0-1
            if np.random.random() < 0.5:
                out[0] = index1[0]
            else:
                out[0] = index2[0]
            if np.random.random() < 0.5:
                out[1] = index1[1]
            else:
                out[1] = index2[1]

            # 对sigma矩阵中对应列的变异强度进行加权平均
            sigma_temp = theta * sigma[:, pos[0]] + (1 - theta) * sigma[:, pos[1]]
            # 对被选中的种子对应的sigma变异

            # 生成一个子代
            son_temp = out + sigma_temp * np.random.normal([2, 1])
            # 判断越界
            if bound_x1[0] <= son_temp[0] <= bound_x1[1] and bound_x2[0] <= son_temp[1] <= bound_x2[1]:
                # 保存子代
                son[:, lamda] = son_temp
                lamda += 1
        # 进行选择
        for j in range(son.shape[1]):
            x1 = son[:, j][0]
            x2 = son[:, j][1]
            fits[j] = F(x1, x2)
        # 排序 返回由小到大的索引 即下标
        arg = np.argsort(fits)
        # 找出最大fitness的N个种子 作为下一次的父代
        X = son[:, arg[(ratio - 1) * N:ratio * N]]
        # 最大适应值对应的x、y
        res_x_y = X[:, -1]
        MAX_FITNESS_TEMP = F(res_x_y[0], res_x_y[1])
        # 更新最大值
        if MAX_FITNESS < MAX_FITNESS_TEMP:
            MAX_FITNESS = MAX_FITNESS_TEMP
            if MAX_FITNESS > E_MAX:
                break
            print(MAX_FITNESS)
        step += 1
    print("结果:")
    print("step:" + str(step))
    print("x:" + str(res_x_y[0]))
    print("y:" + str(res_x_y[1]))
    print(MAX_FITNESS)

有问题希望可以提出,多多交流~
已经更新其他相关的进化算法(GA、ES、CMA-ES、EP等)~

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读