遗传算法 - 函数最优解计算

news2025/1/12 0:48:47

遗传算法

遗传算法概念

遗传算法的概念是在 1975 年由密切根大学的 J.Holland 提出的,这是一种通过模拟自然进化过程寻找最优解的方法。它遵循达尔文的物竞天择,适者生存的进化准则。基本思想:

初始一个种群,选择种群中适应度高的个体进行交叉变异。然后再将适应度低的个体淘汰,留下适应度高的个体进行繁殖,这样不断的进化,最终留下的都是优秀的个体。

基因和染色体

在遗传算法中,我们首先需要将要解决的问题映射成一个数学问题,也就是所谓的数学建模,那么这个问题的一个可行解即被称为一条染色体或个体。如:

3x+4y+5z<100

[1,2,3],[2,3,4],[3,2,1]均为这个函数的可行解,这些可行解在遗传算法中均被称为染色体,每一个元素就被称为染色体上的一个基因。

染色体编码与解码

遗传算法的运算对象是表示染色体的符号串,所以必须把变量 x,y,z 编码为一种符号串。常见的编码方式如用无符号二进制整数来表示。解码即将二进制整数转换回最初的表现型。

编码: 5 --> 0101。

解码: 0101 --> 5。

初始群体的产生

遗传算法是对群体进行的进化操作,需要给其准备一些表示起始搜索点的初始群体数据。假如群体规模的大小取为 4,即群体由 4 个染色体组成,每个染色体可通过随机方法产生。

如: 011101 , 101011 , 011100 , 111001。

物竞天择

适应度函数:遗传算法中以染色体适应度的大小来评定各个染色体的优劣程度,从而决定其遗传机会的大小。

选择函数:自然界中,越适应的个体就越有可能繁殖后代。但是也不能说适应度越高的就肯定后代越多,只能是从概率上来说更多。常用的选择方法有轮盘赌选择法。

f_i表示每个染色体的适应度,则每个个体遗传下来的概率为:

p(i)=\frac{f_i}{\sum_i{f_i}}

由公式可以看出,适应度越高,则遗传下来的概率就越大,好比赌轮盘,轮盘上所占面积越大,则被小球滚到的概率就越大。

交叉与变异

交叉是遗传算法中产生新的个体的主要操作过程,以一定的概率决定个体间是否进行交叉操作。

如上图为父辈染色体进过交叉后产生新的染色体的过程。

变异为另一种产生新个体的操作,它可以为种群带来多样性:

也就是将我的染色体中的基因,随机的由0变成1,或1变成0。

遗传算法流程

初始化种群
计算适应度
选择适应度高的个体
通过交叉变异选择新的染色体
终止进化

使用python实现遗传算法。

本关任务是使用遗传算法求解目标函数最大值,首先需要随机产生很多个解,即初始化种群,代码如下:

#初始化种群
pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE)) 
# Size函数需要传入两个参数 POP_SIZE为解的个数,即染色体个数。DNA_SIZE为染色体长度

其中POP_SIZE为解的个数,即染色体个数。DNA_SIZE为染色体长度。

由于染色体为二进制编码,所以还需要将二进制转换为浮点数的解码方法:

#解码
def translateDNA(pop): 
    return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]

上述代码中: pop.dot(2 ** np.arange(DNA_SIZE)[ : : -1])已经转换成十进制但是需要归一化到 0~5 ,如有 1111 这么长的 DNA,要产生的十进制数范围是 [0, 15] ,而所需范围是 [-1, 1] ,就将 [0,15] 缩放到 [-1,1] 这个范围。

a[ : : -1]相当于a[-1:-len(a)-1:-1],也就是从最后一个元素到第一个元素复制一遍。所以你看到一个倒序,np.arange(DNA_SIZE)[ : : -1]得到 10,9,8,...,0 。

如将 10101 转换到 0 到 5 之间:

x=\frac{2^4+2^2+2+0}{2^5-1}\times 5

然后计算每个染色体的适应度,由于是求解最大值,函数值越大则越应该被选择,所以,将每个染色体对应的函数值减去最小值作为适应度:

#获取染色体适应度
def get_fitness(pred): 
    return pred + 1e-3 - np.min(pred)

再选择适应度高的染色体:

#选择适应度高的染色体
def select(pop, fitness):    
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
                           p=fitness/fitness.sum())
    return pop[idx]

再对染色体进行交叉变异操作:

#交叉
def crossover(parent, pop):     
    if np.random.rand() < CROSS_RATE:
        i_ = np.random.randint(0, POP_SIZE, size=1)                             
        cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)   
        parent[cross_points] = pop[i_, cross_points]                            
    return parent
#变异
def mutate(child):
    for point in range(DNA_SIZE):
        if np.random.rand() < MUTATION_RATE:
            child[point] = 1 if child[point] == 0 else 0
    return child

总流程如下:

def F(x): return np.sin(10*x)*x + np.cos(2*x)*x
def ga(F):
    '''
    F:需要求解的函数
    '''
    #初始化种群
    pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE))
    #开始进化
    for _ in range(N_GENERATIONS):
        #计算函数值
        F_values = F(translateDNA(pop))
        #计算适应度
        fitness = get_fitness(F_values)
        #选择适应度高的个体
        pop = select(pop, fitness)
        pop_copy = pop.copy()
        #通过交叉变异选择新的染色体
        for parent in pop:
            #交叉产生子代
            child = crossover(parent, pop_copy)
            #变异产生子代
            child = mutate(child)
            #子代代替父代
            parent[:] = child
    #获取最优解
    x = translateDNA(pop)[-1]
    return x

其中:

N_GENERATIONS为进化轮数。
CROSS_RATE为交叉概率。
MUTATION_RATE 为变异概率。
X_BOUND 为函数定义域。

具体例子

实现遗传算法。并求解函数f(x)在区间 [0,5] 上的最大值:

f(x)=xsin(10x)+xcos(2x)

函数图像如下:

#encoding=utf8
import numpy as np
DNA_SIZE = 10   
POP_SIZE = 100         
CROSS_RATE = 0.8         
MUTATION_RATE = 0.003    
N_GENERATIONS = 500
X_BOUND = [0, 5] 
#获取染色体适应度
def get_fitness(pred): 
    return pred + 1e-3 - np.min(pred)
#解码
def translateDNA(pop): 
    return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]
#选择适应度高的染色体
def select(pop, fitness):    
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
                           p=fitness/fitness.sum())
    return pop[idx]
#交叉
def crossover(parent, pop):     
    if np.random.rand() < CROSS_RATE:
        i_ = np.random.randint(0, POP_SIZE, size=1)                             
        cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)   
        parent[cross_points] = pop[i_, cross_points]                            
    return parent
#变异
def mutate(child):
    for point in range(DNA_SIZE):
        if np.random.rand() < MUTATION_RATE:
            child[point] = 1 if child[point] == 0 else 0
    return child
def ga(F):
    '''
    F:需要求解的函数
    x:最优解
    '''
    #初始化种群
     # 初始化种群(随机生成二进制染色体)
    pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE))
    #开始进化
    for _ in range(N_GENERATIONS):
        #计算函数值
        F_values = F(translateDNA(pop))
        #计算适应度
        fitness = get_fitness(F_values)
        #选择适应度高的个体
        pop = select(pop, fitness)
        pop_copy = pop.copy()
        #通过交叉变异选择新的染色体
        for parent in pop:
            #交叉产生子代
            child = crossover(parent, pop_copy)
            #变异产生子代
            child = mutate(child)
            #子代代替父代
            parent[:] = child
    #获取最优解
    x = translateDNA(pop)[-1]
    return x

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1531392.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Transformer位置编码(Position Embedding)理解

本文主要介绍4种位置编码&#xff0c;分别是NLP发源的transformer、ViT、Sw-Transformer、MAE的Position Embedding 一、NLP transformer 使用的是1d的绝对位置编码&#xff0c;使用sincos将每个token编码为一个向量【硬编码】 Attention Is All You Need 在语言中&#xff0…

Java基础---反射

什么是反射&#xff1f; 反射允许对成员变量&#xff0c;成员方法和构造方法的信息进行编程访问。 这么说可能比较抽象&#xff0c;可以简单理解为&#xff1a;反射就是一个人&#xff0c;可以把类里面的成员变量&#xff0c;成员方法&#xff0c;构造方法都获取出来。 并且可…

用友NC Cloud runScript SQL注入漏洞复现

0x01 产品简介 用友 NC Cloud 是一种商业级的企业资源规划云平台,为企业提供全面的管理解决方案,包括财务管理、采购管理、销售管理、人力资源管理等功能,基于云原生架构,深度应用新一代数字技术,打造开放、 互联、融合、智能的一体化云平台,支持公有云、混合云、专属云…

jmeter打开文件报异常无法打开

1、问题现象&#xff1a; 报错部分内容&#xff1a; java.desktop does not export sun.awt.shell to unnamed module 0x78047b92 [in thread "AWT-EventQueue-0"] 报错部分内容&#xff1a; kg.apc.jmeter.reporters.LoadosophiaUploaderGui java.lang.reflect.Invo…

华为ENSP的VLAN原理和配置命令

CSDN 成就一亿技术人&#xff01; 作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; CSDN 成就一亿技术人&#xff01; ————前言———— VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网&#xff09;是一种在物理网络基…

Transformer的前世今生 day05(Self-Attention、

Self-Attention 前情提要 注意力机制&#xff1a;我们在看一幅图的时候&#xff0c;不会去看它的所有信息&#xff0c;相反我们倾向于看一些重点&#xff0c;并把我们的焦点放到这些重要信息上&#xff0c;过程如下&#xff1a; 首先&#xff1a;Q、K相乘求相似度&#xff0c…

dB、dBm、dBw是什么

1、dB&#xff0c;3dB 3 dB&#xff0c;表示功率增加为2倍&#xff1b;10 dB&#xff0c;表示功率增加为10倍。 -3 dB&#xff0c;表示功率减小为1/2&#xff1b;-10 dB&#xff0c;表示功率减小为1/10。 dB的使命就是把很大的数&#xff0c;用很小的数简短地表示出来&#x…

【二分查找】算法例题

目录 十八、二分查找 114. 搜索插入位置 ① √- 115. 搜索二维矩阵 ② 116. 寻找峰值 ② √- 117. 搜索旋转排序数组 ② 118. 在排序数组中查找元素的第一个和最后一个位置 ② √ 119. 寻找寻钻排序数组中的最小值 ② 120. 寻找两个正序数组的中位数 ③ 136. 直线上最多…

【Linux】Linux安装软件---软件包管理器 yum

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.Linux中安装软件 1.1 源代码安装 1.2 rpm包安装 1.3 yum安装 1.3.1 举例 1.3.2 图示yum下载安装 2.Linux系统的生态 如何选…

西瓜书机器学习AUC与ℓ-rank(loss)的联系理解以及证明(通俗易懂)

前言 在学习到这部分时&#xff0c;对 ℓ-rank 以及AUC的关系难以理解透彻&#xff0c;在网上看到其他博主也并未弄明白&#xff0c;大家大多写自己的理解&#xff0c;我希望您在看完这篇文章时能够深刻理解这二者的关系&#xff0c;如果我的理解有误&#xff0c;希望您在评论…

为什么共享单车泊车点可以识别得如此精准?

共享单车解决了民众最后一公里的出行问题,方便快捷&#xff0c;低碳环保&#xff0c;缓解了交通拥堵。然而&#xff0c;乱停乱放成为这一新兴事物发展过程中需要解决的迫在眉睫的问题。这真是个伤脑筋的问题&#xff0c;虽然很多城市已经推出共享单车电子围栏&#xff0c;由于G…

Linux入门-常见指令及权限理解

目录 1、Linux背景 1.1、发展历史 1.2、开源 1.3Linux企业应用现状 2、Linux下的基本命令 2.1、ls 指令 2.2、pwd 命令 2.3、cd 命令 2.4、touch命令 2.5、mkdir 命令 2.6、rmdir 指令和 rm指令 2.7 man 指令 2.8、cp指令 2.9、mv 指令 2.10 cat 2.11 more 2…

LLM如何处理长上下文:Lost in the middle

论文地址&#xff1a;Lost in the Middle: How Language Models Use Long Contexts 论文总结&#xff1a;写prompt的时候&#xff0c;需要注意内容的顺序&#xff0c;把重要的信息放在最前面或者最后面。 大型语言模型大有用处&#xff0c;在设计 prompt 方面&#xff0c;人们…

Elasticsearch实战:索引阻塞 —— 数据保护的终极武器

文章目录 1、索引阻塞的种类2、什么时候使用阻塞&#xff1f;场景1&#xff1a;进行系统维护场景。场景2&#xff1a;保护数据不被随意更改场景。场景3&#xff1a;优化资源使用的场景。场景4&#xff1a;遵守安全规则场景。 3、添加索引阻塞API4、解除设置 API5、小结6、参考 …

【无标题】【数据结构】受限制的线性表——队列

&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;个人主页&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388; &#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;数据结构专栏&#x1f388;&#x1f388;&#x1f388;&…

springboot企业级抽奖项目-系统设计

数据设计 E-R图 数据主体是活动&#xff08;game&#xff09;&#xff0c;内置活动策略&#xff08;game_rules&#xff09;&#xff0c;通过关联表&#xff08;game_product&#xff09;和奖品&#xff08;product&#xff09;联动&#xff0c;和用户&#xff08;user&#x…

算法打卡day21|回溯法篇01|理论知识,Leetcode 77.组合

回溯法理论知识 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。回溯是递归的副产品&#xff0c;只要有递归就会有回溯。所以回溯函数也就是递归函数&#xff0c;指的都是一个函数。 回溯法的效率 回溯法并不是什么高效的算法。因为回溯的本质是穷举&#xff0c;…

演讲嘉宾公布 | 智能家居与会议系统专题论坛将于3月28日举办

一、智能家居与会议系统专题论坛 智能家居通过集成先进的技术和设备&#xff0c;为人们提供了更安全、舒适、高效、便捷且多彩的生活体验。智能会议系统它通过先进的技术手段&#xff0c;提高了会议效率&#xff0c;降低了沟通成本&#xff0c;提升了参会者的会议体验。对于现代…

内网渗透学习-环境搭建

1、环境搭建测试 虚拟机网络环境配置&#xff0c;模拟外网和内网 主机操作系统网络内网ip外网ip物理主机window10vmnet8192.168.70.1攻击机kali Linuxvmnet8192.168.70.134域控主机win server 2008 r2vmnet0192.168.52.138域成员主机win server 2k3vmnet0192.168.52.141服务器…

【Windows Defender 排除指定 文件夹、文件夹以提升性能】

使用webStorm时候提醒排出程序和目录提升性能, 于是我就把我的代码目录和常用程序全部排出, 不过不知道能不能提升多少性能, 先加上再说 一.使用UI配置排出项 隐私与安全性安全中心 病毒与威胁防护 添加或删除排出项 配置 二.使用命令配置 使用 PowerShell开启自动排除列表…