遗传算法原理详细讲解(算法+Python源码)

博主介绍:✌专研于前后端领域优质创作者、本质互联网精神开源贡献答疑解惑、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战,深受全网粉丝喜爱与支持✌有需要可以联系作者我哦!

🍅文末获取源码联系🍅

👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟

目录

一、遗传算法 

二、常见的遗传算法变体

三、遗传算法操作步骤

1. 基因编码(Representation):

2. 初始化种群(Initialization):

3. 适应度评估(Evaluation):

4. 选择(Selection):

5. 交叉(Crossover):

6. 变异(Mutation):

7. 替换(Replacement):

8. 重复迭代(Iteration):

9. 收敛检测:

10. 最优解提取:

 四、算法演示(Python)

五、总结

大家点赞、收藏、关注、评论啦 !

谢谢哦!如果不懂,欢迎大家下方讨论学习哦。

一、遗传算法 

 遗传算法的概念最早由约翰·霍兰德(John Holland)在20世纪60年代提出。霍兰德是一位美国的电气工程师和计算机科学家,他对生物学中的自然选择和遗传机制产生了浓厚兴趣,并试图将这些生物学原理应用于解决优化和搜索问题。霍兰德的观点: 约翰·霍兰德在20世纪60年代初期,通过研究自然选择和遗传机制,提出了一种新颖的优化算法的思想。他认为,自然选择的过程中,通过基因的遗传和变异,使得物种逐渐适应环境,并找到更好的生存策略。他意识到这一思想可以应用于解决工程和计算问题。 霍兰德于1975年出版了一本名为《自然和人工系统中的适应性》(Adaptation in Natural and Artificial Systems)的书,其中详细介绍了他的遗传算法理论。这本书被认为是遗传算法的奠基之作。

基本原理: 遗传算法的基本原理是通过模拟自然选择和遗传机制进行优化。个体(解决方案)被编码为基因型,通过遗传操作(交叉和变异)来生成新的个体。适应度函数用于评估个体的优劣,更适应环境的个体有更高的概率被选中进入下一代。

演化过程: 遗传算法的演化过程模拟了生物进化的过程,包括选择、交叉和变异。适应度高的个体更有可能被选中,同时,基因交叉和变异引入了新的基因组合,增加了搜索空间的多样性。

应用: 随着计算机科学和人工智能的发展,遗传算法被应用于解决各种优化问题,如组合优化、函数优化、机器学习等。它在搜索空间庞大、复杂问题中的全局搜索能力使其受到了广泛关注。

二、常见的遗传算法变体

  1. 标准遗传算法(Standard Genetic Algorithm, SGA):

    主要特点是通用,适用于各种优化问题。
  2. 进化策略(Evolutionary Strategies, ES):

    优点: 强调个体的变异,通过适应性进化来探索搜索空间。在高维、大规模问题中表现较好。
  3. 遗传规划算法(Genetic Programming, GP):

    优点: 用于自动发现计算机程序或表达式,适用于符号回归、符号分类等问题。能够发现复杂的解决方案。
  4. 遗传局部搜索算法(Genetic Local Search, GLS):

    优点: 结合了遗传算法和局部搜索的优点,通过遗传算法进行全局搜索,然后通过局部搜索进行精细调整。在解空间的不同区域都能有效搜索。
  5. 多目标遗传算法(Multi-Objective Genetic Algorithm, MOGA):

    优点: 用于处理多目标优化问题,同时优化多个目标函数。通过 Pareto 最优前沿来表示和保留多个解决方案。
  6. 协同演化(Co-Evolution):

    • 优点: 多种群体之间进行协同演化,每个群体演化出一部分解决方案。适用于解决复杂问题,能够处理多个相互影响的子问题。
  7. 遗传局部优化算法(Genetic Local Optimization, GLO):

    优点: 结合了全局搜索和局部优化的特点,利用全局搜索来探索解空间,再通过局部优化进行细致调整。
  8. 差分进化算法(Differential Evolution, DE):

    优点: 强调差分操作,通过对个体之间的差异进行搜索。在全局优化问题中表现良好,对参数敏感性较小。
  9. 自适应遗传算法(Adaptive Genetic Algorithm):

    优点: 能够动态调整算法参数,适应问题的特性。在问题变化较大或参数选择困难时具有较好的适应性。
  10. 混合遗传算法(Hybrid Genetic Algorithm):

    优点: 结合遗传算法与其他优化方法,如局部搜索、模拟退火等。在不同问题场景中综合利用不同算法的优势。

三、遗传算法操作步骤

1. 开始
2. 初始化种群
3. 评估种群中每个个体的适应度
4. 是否满足停止条件?
   - 是:结束,输出最优解
   - 否:
      5. 选择操作:根据适应度选择父代个体
      6. 交叉操作:对选定的父代进行基因交叉,生成新个体
      7. 变异操作:对新生成的个体进行基因变异
      8. 评估新生成的个体的适应度
      9. 替换操作:将新生成的个体替换掉原种群中适应度较差的个体
      10. 回到步骤4
11. 结束

1. 基因编码(Representation):

  • 个体表示: 解决方案被编码成一个个体,通常称为染色体。染色体由基因组成,而基因则是问题的解决方案的一部分。
  • 编码方式: 基因可以用二进制、实数、整数等方式进行编码,具体取决于问题的性质。

2. 初始化种群(Initialization):

  • 种群生成: 随机生成初始的个体群体,即种群。每个个体代表问题的一个可能解。

3. 适应度评估(Evaluation):

  • 适应度函数: 为每个个体计算适应度值,该值表示个体解决问题的优劣程度。适应度函数是根据问题的特性而定义的。

4. 选择(Selection):

  • 轮盘赌选择: 个体被选择的概率与其适应度成正比。适应度较高的个体更有可能被选中,以模拟自然选择的过程。

5. 交叉(Crossover):

  • 基因交叉: 选定一对父代个体,通过某种方式将它们的基因组合生成新的个体。常见的交叉方式包括单点交叉、多点交叉、均匀交叉等。

6. 变异(Mutation):

  • 基因变异: 对个体的某些基因进行随机变动。变异操作引入了新的基因信息,有助于保持种群的多样性。

7. 替换(Replacement):

  • 新一代形成: 通过选择、交叉和变异生成的新个体替代原来种群中的一部分个体。替换操作保持种群规模不变。

8. 重复迭代(Iteration):

  • 演化过程: 通过反复进行选择、交叉、变异和替代,逐渐进化种群。迭代次数可以根据问题的复杂性和算法性能进行调整。

9. 收敛检测:

  • 停止条件: 当达到预定的停止条件(如迭代次数达到设定值或找到满意的解)时,遗传算法终止。

10. 最优解提取:

  • 解的提取: 在遗传算法运行结束后,从最终的种群中提取具有最佳适应度的个体,即优秀的解决方案。

其核心思想就是通过模拟自然选择、遗传机制,遗传算法能够在搜索空间中自适应地寻找问题的优秀解。主要是通过交叉和变异引入新的组合解。

 四、算法演示(Python)

  1. 问题描述: 该问题涉及通过遗传算法优化四个参数(p1、p2、q1、q2),使得目标函数的值最小化。目标函数用于拟合一些实际数据,其中包括肝、肺、胃内的浓度数据。

  2. 编码和解码:

    • 编码: 每个个体(种群中的一个成员)通过二进制编码表示四个参数。
    • 解码: 通过解码操作将二进制编码转换为实际参数值。
  3. 目标函数设计:

    • 提供了两种不同的目标函数(F和F2)供选择。
    • 目标函数的计算基于实际数据和模型预测值之间的误差。
  4. 适应度函数:

    • 适应度函数根据目标函数的值计算个体的适应度。适应度越高,个体越有可能被选择为父代。
  5. 遗传算法操作:

    • 选择: 根据适应度选择个体,采用轮盘赌选择。
    • 交叉和变异: 采用单点交叉操作,以一定的概率发生交叉,并对基因进行变异。
    • 替换: 将新生成的个体替换掉原种群中适应度较差的个体。
  6. 迭代: 通过多次迭代,不断演化种群,寻找最优解。

  7. 结果输出: 打印最终种群中适应度最好的个体及其对应的参数值。

import numpy as np
import warningswarnings.filterwarnings('ignore')DNA_SIZE = 20  # DNA长度(二进制编码长度)
POP_SIZE = 150  # 初始种群数量
CROSSOVER_RATE = 0.95  # 交叉率
MUTATION_RATE = 0.005  # 变异率 将0.005改为0.01
N_GENERATIONS = 1000  # 进化代数 进化代数在 800—1200 之间比较适合,本文选取进化1000代
p1_BOUND = [0, 1]  # 确定参数的范围
p2_BOUND = [0, 1]
q1_BOUND = [0, 1]
q2_BOUND = [0, 1]dic_liver = {0.167: 0.681, 0.5: 0.436, 1: 0.709, 2: 0.263, 6: 0.12}  # 键表示时间(h),值表示肝内的浓度
dic_lung = {0.167: 1.069, 0.5: 0.689, 1: 0.666, 2: 0.342, 6: 0.162}  # 表示肺内的浓度
dic_stomach = {0.167: 4.827, 0.5: 3.866, 1: 1.67, 2: 1.638, 6: 0.798}  # 表示胃内的浓度的def F(p1, p2, q1, q2):  # 设计目标函数 法一fun = 0for key, value in dic_liver.items():fun = ((p1 * np.exp(-q1 * key) + p2 * np.exp(-q2 * key)) - value) ** 2 + funreturn fundef F2(p1, p2, q1, q2):  # 设计目标函数 法二l1 = list(dic_liver.keys())l2 = list(dic_liver.values())result = [((p1 * np.exp(-q1 * i) + p2 * np.exp(-q2 * i)) - j) ** 2 for i, j in zip(l1, l2)]# result = sum(result)total = 0for i in range(len(result)):total = total + result[i]return total# 求最小值对应的适应度函数
def get_fitness(pop):p1, p2, q1, q2 = translateDNA(pop)pred = F(p1, p2, q1, q2)return -(pred - np.max(pred)) + 1e-3  # 要加上一个很小的正数def translateDNA(pop):  # 解码 pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目 即行数为150行,列数为每个DNA长度*DNA个数,即20*4=80列(150*80)p1_pop = pop[:, :20]p2_pop = pop[:, 20:40]q1_pop = pop[:, 40:60]q2_pop = pop[:, 60:]p1 = p1_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (p1_BOUND[1] - p1_BOUND[0]) + p1_BOUND[0]p2 = p2_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (p2_BOUND[1] - p2_BOUND[0]) + p2_BOUND[0]q1 = q1_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (q1_BOUND[1] - q1_BOUND[0]) + q1_BOUND[0]q2 = q2_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (q2_BOUND[1] - q2_BOUND[0]) + q2_BOUND[0]return p1, p2, q1, q2# 以下函数包含两个功能,交叉和变异
def crossover_and_mutation(pop, CROSSOVER_RATE=0.95):  # 单点交叉new_pop = []for father in pop:  # 遍历种群中的每一个个体,将该个体作为父亲child = father  # 孩子先得到父亲的全部基因(这里我把一串二进制串的那些0,1称为基因)if np.random.rand() < CROSSOVER_RATE:  # 产生子代时不是必然发生交叉,而是以一定的概率发生交叉mother = pop[np.random.randint(POP_SIZE)]  # 再种群中选择另一个个体,并将该个体作为母亲cross_points = np.random.randint(low=0, high=DNA_SIZE * 4)  # 随机产生交叉的点child[cross_points:] = mother[cross_points:]  # 孩子得到位于交叉点后的母亲的基因mutation(child)  # 每个后代有一定的机率发生变异new_pop.append(child)return new_pop# 基本位变异算子
def mutation(child, MUTATION_RATE=0.005):if np.random.rand() < MUTATION_RATE:  # 以MUTATION_RATE的概率进行变异mutate_point = np.random.randint(0, DNA_SIZE * 4)  # 随机产生一个实数,代表要变异基因的位置child[mutate_point] = child[mutate_point] ^ 1  # 将变异点的二进制为反转(异或运算符 1与1为0、1与0为1、0与0为0)def select(pop, fitness):  # 描述了从np.arange(POP_SIZE)里选择每一个元素的概率,概率越高约有可能被选中,最后返回被选中的个体即可idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,p=(fitness) / (fitness.sum()))return pop[idx]# # np.random.choice()函数的用法
# arr = ['pooh', 'rabbit', 'piglet', 'Christopher']
# np.random.choice(aa_milne_arr, size=11, p=[0.5, 0.1, 0.1, 0.3])def print_info(pop):fitness = get_fitness(pop)min_fitness_index = np.argmin(fitness)  # 表示为array的最大值/最小值对应的索引print("min_fitness:", fitness[min_fitness_index])p1, p2, q1, q2 = translateDNA(pop)print("最优的基因型:", pop[min_fitness_index])print("(p1, p2, q1, q2):",(p1[min_fitness_index], p2[min_fitness_index], q1[min_fitness_index], q2[min_fitness_index]))if __name__ == "__main__":pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE * 4))  # matrix (POP_SIZE, DNA_SIZE) POP_SIZE为150,DNA_SIZE为20for _ in range(N_GENERATIONS):  # 迭代N代pop = np.array(crossover_and_mutation(pop, CROSSOVER_RATE))  # 进行交叉和变异fitness = get_fitness(pop)pop = select(pop, fitness)print_info(pop)

 

五、总结

遗传算法通过模拟自然选择和遗传机制,能够在搜索空间中找到较好的解决方案,尤其在复杂问题和大规模搜索空间中表现出色。但是存在最大缺点是需要巨大计算资源,对于及时响应存在不足问题。目前对于遗传算法还有待深入研究,尤其是对于不同实际问题需求,数据特点等,通过引入随机操作等降低算法时间和空间复杂度是一项值得深入的研究方向。

大家点赞、收藏、关注、评论啦 !

谢谢哦!如果不懂,欢迎大家下方讨论学习哦。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

配置ntp时间服务器和ssh免密登录实验

1&#xff1a;配置ntp时间服务器&#xff0c;确保客户端主机能和服务主机同步时间 第一步&#xff0c;将服务器的时间同步对象改为阿里的时间服务器&#xff08;这样比较精准&#xff09; 先启动服务&#xff1a;[rootserver ~]# systemctl start chronyd 进入配置文件&#xf…

dolphinscheduler节点二次开发需要改动的部分

dolphinscheduler节点二次开发需要改动的部分 前端 在dolphinscheduler-ui/public/images/task-icons/目录下新增两个节点的logo图片&#xff0c;一个为激活状态的一个为非激活状态的&#xff0c;如下。 修改文件dolphinscheduler-ui/src/views/projects/task/constants/task…

爬取咚漫漫画

一、数据来源分析1.确定自己的需求&#xff1a;采集哪个网站的上面的数据内容正常的访问流程&#xff1a;1.选中漫画--->目录页面 &#xff08;请求列表页面&#xff0c;获取所有的章节链接&#xff09;2.选择一个漫画内容--->漫画页面 &#xff08;请求章节链接&#xf…

基于TriDet的时序动作检测算法训练自己的slowfast数据

最近一直在研究时序动作识别和检测&#xff0c;也一直关注着目前的最新进展&#xff0c;有好的算法&#xff0c;我都会在我自己的数据集上运行看看&#xff0c;一方面是为自己累积相关算法&#xff0c;另一方面也是想看看&#xff0c;目前最新的算法是否可以应用到一些项目上。…

对话顺网科技创始人华勇:建立坚定的AI信仰,从内而外全面拥抱AI

“ 进军AI智算时代的号角已被吹响” 整理 | 梦婕 编辑 | 欣桐 出品&#xff5c;极新 1月18日&#xff0c;顺网科技以“跃迁向未来”为主题的战略升级暨产品升级发布会在杭州圆满召开。顺网科技公布了新战略——“立足算力&#xff0c;聚焦AI”&#xff0c;并揭晓了全新的品…

arcgis 面要素shp数据处理

面要素是工作中用到最多的&#xff0c;那么面要素是如何形成的呢&#xff0c;主要还是由闭合的线要素转换而成。在面要素数据中常用的有以下几点&#xff1a; 一、 线转面&#xff08;要素转面&#xff09; 通过上一篇得到了点转线的要素&#xff0c;那么根据上节的线要素&am…

系统移植 day2 bootloader->u-boot 移植

一、栈的复习 1、满栈&#xff1a;当堆栈指针SP总是指向最后压入堆栈的数据&#xff0c;称为满栈&#xff1b; 2、空栈&#xff1a;当堆栈指针SP总是指向下一个将要放入数据的空位置&#xff0c;称为空栈&#xff1b; 满栈状态下&#xff0c;先移动指针&#xff0c;后赋值. 空…

Unity中UGUI在Mask剪裁粒子特效的实现

在Unity使用Mask是剪裁不了粒子特效的&#xff0c;之前有想过RenderTexture来实现&#xff0c;不过使用RenderTexture不适合用于很多个特效&#xff0c;因为RenderTexture依赖Camera的照射&#xff0c;如果在背包中每种道具都有不同的特效&#xff0c;那使用RenderTexture则需要…

VPN的基本原理以及配置

实验如上图所示&#xff1a; 首先给各个设备配置IP地址 其次再给r1和r5做pap认证 给r2和r5做chap认证 r5上的配置如下图所示&#xff1a; r3和r5之间用hdlc进行封装&#xff1a; r5: 给r1&#xff0c;r2&#xff0c;r3配置MGRE&#xff1a;使得可以通过VPN技术进行通讯&#…

ESXI 本地和虚拟机之间可以自由复制和粘贴

文章目录 ESXI 本地和虚拟机之间可以自由复制和粘贴 ESXI 本地和虚拟机之间可以自由复制和粘贴 web访问esxi&#xff0c;然后&#xff1a; 1、右击新建的虚拟机&#xff0c;确保是在关机状态下&#xff0c;点击编辑设置 2. 找到 虚拟机选项→高级→常规→配置参数 3、点击添加…

【强化学习】QAC、A2C、A3C学习笔记

强化学习算法&#xff1a;QAC vs A2C vs A3C 引言 经典的REINFORCE算法为我们提供了一种直接优化策略的方式&#xff0c;它通过梯度上升方法来寻找最优策略。然而&#xff0c;REINFORCE算法也有其局限性&#xff0c;采样效率低、高方差、收敛性差、难以处理高维离散空间。 为…

ansible 常用模块

目录 1.ping模块 2.command模块 3. shell模块 4.copy模块 5.file模块 6.fetch模块 7.cron模块 8.yum模块 9.service模块 10.user模块 11.group模块 12.script 模块 13.setup模块 14. get_url模块 15.stat模块 16.unarchive模块 1.ping模块 使用ansible db1 -m pin…