用遗传算法(GA)做最优化:找一元及多元函数的最大值

一元函数

对于如下图所示的一元函数求解其在区间[0,7]内的最大值有多种方式。在本文中分享的是用一种启发式算法——遗传算法来完成这项工作。
在这里插入图片描述大家对遗传算法不了解的话可以戳这里看简介。
首先介绍我们的主角,也就是目标函数的形式。其定义如下:

def F(x): return np.sin(5*x)+ np.cos(4*x)  

由于我们在这里要找的是函数的最大值点,那么只需直接使用其函数值的大小作为适应度函数的主体即可。同时不要忘记处理边界问题:减去输入的种群个体适应度序列中的最小值以保证最终结果为非负数,再加上一个很小的值保证适应度为正值。

def Get_Fitness(val): return val - np.min(val) + 1e-6

当然,在遗传算法运行过程中,染色体以二进制序列的形式存在。为了能将他们代入到目标函数中计算对应的函数值以及进行适应度的计算,我们还要做DNA的解码:

def Translate_DNA(pop): return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / (2**DNA_SIZE-1) * X_BOUND[1]

根据目标DNA序列的长度(长度越长,其能表示的真实值的颗粒度也就越精细,结果越精确),将二进制的DNA序列映射到对应的函数自变量上(注意取值范围)。上面代码的基本操作就是二步:
1.将二进制转换为十进制下区间[0,1]间的数。
2.将对应十进制序列的数比照相应的取值范围来缩小或放大。

下面就是遗传算法的主体部分了,首先是自然选择、优胜劣汰的过程:

def Select(pop, fitness):    
    index = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,p=fitness/fitness.sum())
    return pop[index]

这一步可以使用numpy库中的choice函数完成,他会根据一个概率分布来随机返回序列中的值。
适应度高的个体有更高的被选中作为下一代的父辈的可能。

其次是配对,出色的个体们在这一步进行基因重组(染色体交叉联会),在保留亲代一定特性的基础上引入了新的可能性:

def Mating (parent, pop):     
    if np.random.rand() < MATING_RATE:
        index = np.random.randint(0, POP_SIZE, size=1)                            
        cross_points = np.random.randint(0, 2, size=DNA_SIZE)                    
        parent[cross_points] = pop[index, cross_points]                            
    return parent

子代会分别得到来自父母的部分基因,最终成长为一个全新的个体。

在基因重组的过程中,子代基因也有几率发生突变

def Mutation(child):
    for point in range(DNA_SIZE):
        if np.random.rand() < MUTATION_RATE:
            child[point] = 1 if child[point] == 0 else 0
    return child

这一步只需随机地对子代基因上的某些碱基对进行改变即可(0变1或1变0)。

效果

在这里插入图片描述经过若干次的迭代,我们可以看到多数个体集中在了函数的最大值点附近。说明遗传算法确实能够帮助我们解决一元函数的优化问题。不过在测试的时候也会偶尔发生以下这种状况:
在这里插入图片描述可以看到,我们算法生成的个体有往局部最大值收敛的趋势,而这并不是我们想要看到的结果。对于这类在遗传算法中,求解结果很快陷入函数的局部最优解的现象,我们把它叫做早熟现象(prematurity)。由于理论上考虑的遗传算法的选择、变异、交叉等操作过程是绝对精确的,而在实际代码实现过程中会不可避免地产生精度损失。这部分误差最终导致搜索过程逐步偏离期望路径,种群中个体的多样性过早地丧失,算法迭代陷入了局部最优值。有很多相关的文献针对早熟收敛做了研究:[1]提出了可以使部分种群个体的再初始化来防止早熟的方法;[2]使用马尔可夫链来提高GA算法的收敛质量;[3]则对染色体交叉的过程做了改进。

在这里插入图片描述
当我们遇到如上图形式的多元函数并需要对其求最大或最小值时(比如替代梯度下降来对神经网络中的权值进行更新优化),GA算法也同样可以派上用场。只需在上述优化一元函数的代码基础上做一些修改即可得到下图的结果:
在这里插入图片描述
可以看到多次迭代后的种群个体基本集中在了函数图像的最高峰。

本节代码可见这里:github

参考文献
[1] E. S. Nicoară “Mechanisms to Avoid the Premature Convergence of Genetic Algorithms." Petroleum-Gas University of Ploiesti Bulletin, Mathematics-Informatics-Physics Series 61.1 (2009).
[2] L. Ming, Y. Wang, and Y. M. Cheung, “On convergence rate of aclass of genetic algorithms”. In Automation Congress, 2006.WAC’06. World (pp. 1-6). IEEE.
[3] Aldallal A S . Avoiding Premature Convergence of Genetic Algorithm in Informational Retrieval Systems[J]. international journal of intelligent systems & applications in engineering, 2015, 2(4).

  • 3
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
遗传算法(Genetic Algorithm,GA)是一种基于自然进化过程的优化算法,也可以用于求解多元函数最大值问题。 遗传算法的基本思想是将每个潜在解表示为染色体,通过模拟自然进化过程(如选择、交叉、变异等)产生新一代染色体,并通过适应度函数评估染色体的优劣程度,最终最优解。 对于多元函数最大值问题,遗传算法可以通过以下步骤求解: 1. 定义目标函数和限制条件。目标函数是需要最大化的多元函数,限制条件可以是等式限制或不等式限制。 2. 初始化种群。随机生成一定数量的染色体,并将其加入种群中。 3. 计算适应度值。将每个染色体的基因型解码为表现型,代入目标函数中计算适应度值。 4. 选择操作。根据适应度值选择优秀个体,将其复制到下一代种群中。 5. 交叉操作。随机选择两个染色体并进行交叉操作,生成两个后代染色体,并将其加入下一代种群中。 6. 变异操作。对某些染色体进行变异操作,以增加种群的多样性。 7. 判断是否满足停止条件。如果达到停止条件,则输出最优解;否则返回步骤3。 需要注意的是,遗传算法的性能受到许多因素的影响,包括种群大小、交叉率、变异率等等。因此,在实际应用中需要根据具体问题进行调参。此外,遗传算法的收敛速度较慢,需要较长的运行时间才能最优解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值