遗传算法求函数最大值_遗传算法与Python图解

本文介绍了遗传算法求函数最值的详细步骤,包括问题定义、编码、解码、适应度函数、选择、交叉和变异。通过Python实现展示了如何应用遗传算法解决背包问题,并探讨了算法中的超参数选择和变异策略。
摘要由CSDN通过智能技术生成
import matplotlib.pyplot as plt
import numpy as np
import random
import pandas as pd

遗传算法求函数最值

遗传算法的特点有无须可导,可优化离散异构数据。

参考:

  • 遗传算法python实现
  • 科学前沿:Genetic Algorithm - 遗传算法究竟怎么回事

问题定义

如下图所示,

equation?tex=f%28x%29+%3D+x+%5Ccdot+sin%2810%5Cpi+%5Ccdot+x%29在区间
[-1, 2]上有很多极大值和极小值,如果要求其最大值或最小值,很多单点优化的方法(梯度下降等)就不适合,这种情况下就可以用遗传算法(Genetic Algorithm)。
def fun(x):
    return x * np.sin(10*np.pi*x) + 2

Xs = np.linspace(-1, 2, 100)
plt.plot(Xs, fun(Xs))

d4e28d491ea3a640c6770211599e06af.png

初始化原始种群

遗传算法的一个特点是同时优化一批解(种群),例如下面在[-1, 2]范围内随机生成

equation?tex=10个点:
np.random.seed(0)

# 初始化原始种群
def ori_popular(num, _min=-1, _max=2):
    return np.random.uniform(_min, _max, num) # 范围[-1, 2)

#__TEST__
population = ori_popular(10)

for pop, fit in zip(population, fun(population)):
    print("x=%5.2f, fit=%.2f"%(pop, fit))

plt.plot(Xs, fun(Xs))
plt.plot(population, fun(population), '*')
plt.show()

>>>
x= 0.65, fit=2.64
x= 1.15, fit=0.87
x= 0.81, fit=2.21
x= 0.63, fit=2.56
x= 0.27, fit=2.21
x= 0.94, fit=1.13
x= 0.31, fit=1.88
x= 1.68, fit=3.17
x= 1.89, fit=2.53
x= 0.15, fit=1.85

820041ab0dc54b7075bc6d6df012cdf3.png

上图显示我们随机选的

equation?tex=10个点离最大值(3.8左右)差距还挺远,下面用GA算法看能否求到最优解。

编码

编码,也就是由表现型到基因型,性征到染色体。

二进制编码的缺点:对于一些连续函数的优化问题,由于其随机性使得其局部搜索能力较差,如对于一些高精度的问题,当解迫近于最优解后,由于其变异后表现型变化很大,不连续,所以会远离最优解,达不到稳定。而格雷码能有效地防止这类现象。

TODO:

  • [ ] 用2**18扩展似乎会损失精度,准备用10000代替

下面分别将1, 10, 0转成二进制编码,注意浮点数0.1无法转换:

print("1:", bin(1))
print("10:", bin(10))
print("0:", bin(0))

try:
    print("0.1:", bin(0.1))
except Exception as E:
    print("Exception: {}".format(type(E).__name__), E)

>>>
1: 0b1
10: 0b1010
0: 0b0
Exception: TypeError 'float' object cannot be interpreted as an integer

为了能编码浮点数,需要扩大倍数转成整数:

X = [1, 0.1, 0.002]

print("2**18 =", 2**18, 'n')
for x in X:
    tx = int(x * 2**18)
    print("%.4f => %6d => %s"%(x, tx, bin(tx)))

2**18 = 262144 

>>>
1.0000 => 262144 => 0b1000000000000000000
0.1000 =>  26214 => 0b110011001100110
0.0020 =>    524 => 0b1000001100
for x in X:
    tx = int(x * 2**18)
    ex = bin(tx)
    dx = int(ex, 2) / 2**18
    print("%25s => %6d => %.4f"%(ex, tx, dx))

>>>
0b1000
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值