遗传算法------微生物进化算法(MGA)

news2024/11/27 8:41:07

前言

该文章写在GA算法之后:GA算法

遗传算法 (GA)的问题在于没有有效保留好的父母 (Elitism), 让好的父母不会消失掉. Microbial GA (后面统称 MGA) 就是一个很好的保留 Elitism 的算法.

一句话来概括: 在袋子里抽两个球, 对比两个球, 把球大的放回袋子里, 把球小的变一下再放回袋子里, 这样在这次选着中,
大球不会被改变任何东西, 就被放回了袋子, 当作下一代的一部分.

算法思想

在这里插入图片描述
每次在进化的时候, 我们会从这个 pop 中随机抽 2 个 DNA 出来, 然后对比一下他们的 fitness, 我们将 fitness 高的定义成 winner, 反之是 loser. 我们不会去动任何 winner 的 DNA, 我们只对 loser, 比如对 loser 的DNA进行修改,进行 crossovermutate. 之后将 winnerloser 一同放回 pop 中.

通过这样的流程, 我们就不用担心有时候变异着变异着, 那些原本好的 pop 流失掉了, 有了这个 MGA 算法, winner 总是会被保留下来的. GA 中的 Elitism 问题通过这种方法巧妙解决了.

示例

我们以曲线寻找最大值为例子
在这里插入图片描述

本算法与GA算法的区别在于交叉时,我们将选择的两个个体,一个winner一个loser,我们将winner的部分DNA复制给loser
代码如下:

 def crossover(self, loser_winner):  # mating process (genes crossover)
        """
        交叉配对
        :param parent:
        :param pop:
        :return:
        """
        # 生成一个长度DNA_size的布尔类型的数组  布尔值来选择相应的交叉点进行交叉操
        cross_idx = np.empty((self.DNA_size,)).astype(np.bool_)
        for i in range(self.DNA_size):
            cross_idx[i] = True if np.random.rand() < self.cross_rate else False
        # 将winner的DNA和loser的DNA交叉,重新赋值给loser
        loser_winner[0, cross_idx] = loser_winner[1, cross_idx]
        return loser_winner

其次是变异操作,我们进行交叉操作之后,我们对loser的DNA进行变异操作
代码如下:

 def mutate(self, loser_winner):
        """
        变异操作
        :param loser_winner:
        :return:
        """
        # 生成要变异的结点
        mutation_idx = np.empty((self.DNA_size,)).astype(np.bool_)
        for i in range(self.DNA_size):
            mutation_idx[i] = True if np.random.rand() < self.mutate_rate else False  # mutation index
        # 进行变异
        loser_winner[0, mutation_idx] = ~loser_winner[0, mutation_idx].astype(np.bool_)
        return loser_winner

最后就是算法核心,GA算法是对种群进行select,而我们的MGA算法就是选择多次的loserwinner,这样适应度好的个体会一直保留在种群当中,而不会被替代
代码如下:

    def evolve(self, n):
        """
        微生物进化算法
        :param n:
        :return:
        """
        # 从种群中取n次的 loser_winner
        for _ in range(n):
            # 获取两个个体的下标
            sub_pop_idx = np.random.choice(np.arange(0, self.pop_size), size=2, replace=False)
            # 得到两个个体
            sub_pop = self.pop[sub_pop_idx]
            # 获取适应度
            product = F(self.translateDNA(sub_pop))
            fitness = self.get_fitness(product)
            # 根据适应度对两个个体进行排序,适应度低的在第一个即loser
            loser_winner_idx = np.argsort(fitness)   #返回排序后的索引
            loser_winner = sub_pop[loser_winner_idx]  # the first is loser and second is winner
            loser_winner = self.crossover(loser_winner)
            loser_winner = self.mutate(loser_winner)
            self.pop[sub_pop_idx] = loser_winner

        DNA_prod = self.translateDNA(self.pop) # y轴
        pred = F(DNA_prod)   # x轴
        return DNA_prod, pred

完整代码如下

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
import time

import numpy as np
import matplotlib.pyplot as plt

DNA_SIZE = 10            # DNA length  DNA长度
POP_SIZE = 20           # population size  种群大小
CROSS_RATE = 0.6         # mating probability (DNA crossover)  交叉配对的概率
MUTATION_RATE = 0.01    # mutation probability  编译的概率
N_GENERATIONS = 200     #   代数
X_BOUND = [0, 5]         # x upper and lower bounds   x轴范围

def F(x):
    """
    定义一个函数,就是图像中的线条
    :param x:
    :return:
    """
    return np.sin(10*x)*x + np.cos(2*x)*x     # to find the maximum of this function

class MGA():
    def __init__(self, DNA_size, DNA_bound, cross_rate, mutation_rate, pop_size):
        self.DNA_size = DNA_size
        DNA_bound[1] += 1
        self.DNA_bound = DNA_bound
        self.cross_rate = cross_rate
        self.mutate_rate = mutation_rate
        self.pop_size = pop_size

        # initialize the pop DNA   s生成0-1的POP_SIZE行 DNA_SIZE列的种群
        self.pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE))


    def get_fitness(self,pred):
            """
            获取个体的适用度
            :param pred:
            :return:
            """
            return pred + 1e-3 - np.min(pred)  # 防止适应度为负数

    def translateDNA(self,pop):
        """
        将0 1 DNA序列翻译成范围在(0, 5)的数字
        :param pop:
        :return:
        """
        return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * X_BOUND[1]


    def crossover(self, loser_winner):  # mating process (genes crossover)
        """
        交叉配对
        :param parent:
        :param pop:
        :return:
        """
        # 生成一个长度DNA_size的布尔类型的数组  布尔值来选择相应的交叉点进行交叉操
        cross_idx = np.empty((self.DNA_size,)).astype(np.bool_)
        for i in range(self.DNA_size):
            cross_idx[i] = True if np.random.rand() < self.cross_rate else False
        # 将winner的DNA和loser的DNA交叉,重新赋值给loser
        loser_winner[0, cross_idx] = loser_winner[1, cross_idx]
        return loser_winner

    def mutate(self, loser_winner):
        """
        变异操作
        :param loser_winner:
        :return:
        """
        # 生成要变异的结点
        mutation_idx = np.empty((self.DNA_size,)).astype(np.bool_)
        for i in range(self.DNA_size):
            mutation_idx[i] = True if np.random.rand() < self.mutate_rate else False  # mutation index
        # 进行变异
        loser_winner[0, mutation_idx] = ~loser_winner[0, mutation_idx].astype(np.bool_)
        return loser_winner

    def evolve(self, n):
        """
        微生物进化算法
        :param n:
        :return:
        """
        # 从种群中取n次的 loser_winner
        for _ in range(n):
            # 获取两个个体的下标
            sub_pop_idx = np.random.choice(np.arange(0, self.pop_size), size=2, replace=False)
            # 得到两个个体
            sub_pop = self.pop[sub_pop_idx]
            # 获取适应度
            product = F(self.translateDNA(sub_pop))
            fitness = self.get_fitness(product)
            # 根据适应度对两个个体进行排序,适应度低的在第一个即loser
            loser_winner_idx = np.argsort(fitness)   #返回排序后的索引
            loser_winner = sub_pop[loser_winner_idx]  # the first is loser and second is winner
            loser_winner = self.crossover(loser_winner)
            loser_winner = self.mutate(loser_winner)
            self.pop[sub_pop_idx] = loser_winner

        DNA_prod = self.translateDNA(self.pop) # y轴
        pred = F(DNA_prod)   # x轴
        return DNA_prod, pred



if __name__ == '__main__':

    plt.ion()  # something about plotting
    # x轴
    x = np.linspace(*X_BOUND, 200)
    plt.plot(x, F(x))

    # 初始化算法
    ga = MGA(DNA_size=DNA_SIZE, DNA_bound=[0, 1], cross_rate=CROSS_RATE, mutation_rate=MUTATION_RATE, pop_size=POP_SIZE)

    # 迭代N_GENERATIONS次
    for _ in range(N_GENERATIONS):
        # 进行进化算法
        DNA_prod, pred = ga.evolve(5)
        # 得到图像上的y值
        F_values = F(ga.translateDNA(ga.pop))
        # 获取每一个个体的适应度
        fitness = ga.get_fitness(F_values)

        # 获取最好适用度的个体下标
        i = np.argmax(fitness)
        print("最优DNA", ga.pop[i, :])

        # something about plotting
        if 'sca' in globals(): sca.remove()
        sca = plt.scatter(DNA_prod, pred, s=200, lw=0, c='red', alpha=0.5);
        plt.pause(0.05)

    plt.ioff()
    plt.show()

总结

MGA算法与GA算法的本质区别在于,MGA算法对适应度较好的个体进行了保留,并将适应度较好的个体的DNA复制给较差的DNA个体并进行变异操作

参考

莫烦Python

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

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

相关文章

Qt中各个功能模块遵循的协议

Qt 中各个模块的协议&#xff0c;是在变化的&#xff0c;并不是一成不变 不同版本&#xff0c;协议有可能会变。同一版本&#xff0c;在不同时间期间&#xff0c;协议也可能会变 具体以官网为准

搜索引擎站群霸屏排名源码系统+关键词排名 前后端完整的搭建教程

开发搜索引擎站群霸屏排名系统是一项重要的策略&#xff0c;通过在搜索引擎中获得多个高排名站点&#xff0c;可以大大提高企业的品牌知名度&#xff0c;从而吸引更多的潜在客户和消费者。而且当潜在客户在搜索结果中看到多个与您的品牌相关的站点时&#xff0c;他们可能会认为…

EtherCAT报文-BRD(广播读)抓包分析

0.工具准备 1.EtherCAT主站 2.EtherCAT从站&#xff08;本文使用步进电机驱动器&#xff09; 3.Wireshark1.EtherCAT报文帧结构 EtherCAT使用标准的IEEE802.3 Ethernet帧结构&#xff0c;帧类型为0x88A4。EtherCAT数据包括2个字节的数据头和44-1498字节的数据。数据区由一个或…

ST-SSL:基于自监督学习的交通流预测模型

文章信息 文章题为“Spatio-Temporal Self-Supervised Learning for Traffic Flow Prediction”&#xff0c;是一篇发表于The Thirty-Seventh AAAI Conference on Artificial Intelligence (AAAI-23)的一篇论文。该论文主要针对交通流预测任务&#xff0c;结合自监督学习&#…

EtherCAT报文-BWR(广播写)抓包分析

0.工具准备 1.EtherCAT主站 2.EtherCAT从站&#xff08;本文使用步进电机驱动器&#xff09; 3.Wireshark1.EtherCAT报文帧结构 EtherCAT使用标准的IEEE802.3 Ethernet帧结构&#xff0c;帧类型为0x88A4。EtherCAT数据包括2个字节的数据头和44-1498字节的数据。数据区由一个或…

【2023研电赛】全国技术竞赛一等奖:基于FPGA的超低时延激光多媒体终端

该作品参与极术社区组织的研电赛作品征集活动&#xff0c;欢迎同学们投稿&#xff0c;获取作品传播推广&#xff0c;并有丰富礼品哦~ 基于FPGA的超低时延激光多媒体终端 参赛单位&#xff1a;华东师范大学 指导老师&#xff1a;刁盛锡 参赛队员&#xff1a;王泽宇 谢祖炜 秦子淇…

解读 | 自动驾驶系统中的多视点三维目标检测网络

原创 | 文 BFT机器人 01 背景 多视角三维物体检测网络&#xff0c;用于实现自动驾驶场景高精度三维目标检测&#xff0c;该网络使用激光雷达点云和RGB图像进行感知融合&#xff0c;以预测定向的三维边界框&#xff0c;相比于现有技术&#xff0c;取得了显著的精度提升。同时现…

【重要!合规政策更新】英国,儿童玩具相关产品卖家,请及时关注!EN71

合规政策更新&#xff01; 尊敬的卖家&#xff1a; 您好&#xff01; 我们此次联系您是因为您正在销售需要审批流程的商品。为此&#xff0c;亚马逊正在实施审批流程&#xff0c;以确认我们网站上提供的商品类型须符合指定的认证标准。要在亚马逊商城销售这些商品&#xff0c;您…

第六篇Android--ImageView、Bitmap

ImageView&#xff0c;和前面介绍的TextView、EditText&#xff0c;都继承自View都是View的子类。 ImageView 是用于呈现图片的视图。View可以理解为一个视图或控件。 1.简单使用 在drawable-xxhdpi文件夹下放一张图片&#xff1a; xml中把这张图片设置给ImageView&#xff0…

MySQL单表查询基础综合练习

一、单表查询 素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker ( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL, 工资 float(8,2) NOT NULL, 政治面貌 v…

三勾知识付费(PHP+vue3)微信小程序平台+SAAS+前后端源码

项目介绍 三勾小程序商城基于thinkphp8element-plusuniapp打造的面向开发的小程序商城&#xff0c;方便二次开发或直接使用&#xff0c;可发布到多端&#xff0c;包括微信小程序、微信公众号、QQ小程序、支付宝小程序、字节跳动小程序、百度小程序、android端、ios端。 软件架…

BUUCTF学习(二):一起来撸猫

1、介绍 2、解题 &#xff08;1&#xff09;查看网页源代码 &#xff08;2&#xff09;解读代码内容 &#xff08;3&#xff09;得出结论 网址&#xff1a;一起来撸猫http://df4c147d-c7f4-4aac-a9d6-fdce2606ee18.node4.buuoj.cn:81/?catdog 第二题结束

PyTorch入门教学——在虚拟环境中安装Jupyter

1、简介 Jupyter Notebook是一个开源的web应用程序&#xff0c;可以使用它来创建和共享包含实时代码、方程、可视化和文本的文档。Jupyter Notebook是一个交互式笔记本&#xff0c;可以当作python编译器来使用。 2、安装 在安装Anaconda时是自带了Jupyter Notebook的&#x…

Unity第一人称移动和观察

创建一个可以自由移动的第一人称视角 人物通过WSAD进行前后左右移动&#xff0c;通过鼠标右键进行旋转 Step1:创建一个Player玩家&#xff0c;在节点下加两个子物体&#xff0c;一个摄像头和一个Capsule充当身体 Step2:创建一个脚本挂载在Player节点下&#xff0c;再在这个Pl…

ThreeJS-3D教学十-有宽度的line

webgl中线是没有宽度的&#xff0c;现实的应用中一般做法都是将线拓宽成面来绘制。默认threejs的线宽是无法调节的&#xff0c;需要用有厚度的线 THREE.Line2。 先看效果图&#xff1a; 看下代码&#xff1a; <!DOCTYPE html> <html lang"en"> <he…

2022年03月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 关于Python中的列表&#xff0c;下列描述错误的是?&#xff08; …

BUUCTF在线评测简介

1、网站 BUUCTF在线评测简介 BUUCTF在线评测 BUUCTF在线评测BUUCTF 是一个 CTF 竞赛和训练平台&#xff0c;为各位 CTF 选手提供真实赛题在线复现等服务。https://buuoj.cn/challenges 2、介绍 3、学习步骤 学习从这里开始&#xff01;

深入剖析 深度学习中 __init()__函数和forward()函数

目录 前言1. __init()__函数2. forward()函数3. 两者关系 前言 再看代码时&#xff0c;发现init函数和forward函数都有参数&#xff0c;具体是怎么传参的呢&#xff1f; 为了更方便的讲解&#xff0c;会举简单的代码例子结合讲解。 forward() 和 __init__() 是神经网络模型类…

甘特图:如何制定一个有效的项目计划?需要考虑这些方面

一个清晰、可行的计划能够为团队提供明确的方向&#xff0c;确保项目顺利执行&#xff0c;缺乏明确的计划可能导致项目偏离轨道。 甘特图是一种通过条状图形来表示项目和进度的工具&#xff0c;由于其具有视觉化的优点&#xff0c;使得管理者能够更容易地掌握项目进展情况。因…

安捷伦N8485A射频传感器26.5GHz

安捷伦N8485A射频传感器 N8485A 是 Agilent 使用的 26.5 GHz 0.1 瓦射频传感器。电子测试设备传感器测量波形的功率&#xff0c;例如多音和调制射频 (RF) 波形。传感器使用二极管检测器收集高度精确的调制测量值。 用于存储校准系数的 EEPROM 消除了手动输入 10 MHz 至 26.5 GH…