2024 遗传编程实战(一)基因实战

2024 遗传编程实战(一)基因实战

文章目录

  • 2024 遗传编程实战(一)基因实战
  • 一、遗传编程实战介绍
    • 1、遗传编程简介
    • 2、遗传编程和进化论的关系
    • 3、遗传编程过程解释
  • 二、基于遗传编程的例子
    • 1、实战题目介绍
    • 2、遗传算法的伪代码
    • 3、遗传实战具体代码与详细注释
    • 4、将以上纯python运算实现代码套入DEAP强化学习框架实现

一、遗传编程实战介绍

1、遗传编程简介

什么是遗传编程算法,和传统机器学习算法有什么区别
传统上,我们接触的机器学习算法,都是被设计为解决某一个某一类问题的确定性算法。对于这些机器学习算法来说,唯一的灵活性体现在参数搜索空间上,向算法输入样本,算法借助不同的优化手段,对参数进行调整,以此来得到一个对训练样本和测试样本的最佳适配参数组。

遗传编程算法完全走了另一外一条路,遗传编程算法的目标是编写一个程度,这个程序会尝试自动构造出解决某一问题的最佳程度。从本质上看,遗传编程算法构造的是一个能够构造算法的算法。

另一方面,我们曾经讨论过遗传算法,遗传算法是一种优化技术,就优化技术而言,无论是何种形式的优化,算法或度量都是预先设定好的,而优化算法所做的工作就是尝试为其找到最佳参数。和优化算法一样,遗传编程也需要一种方法来度量题解的优劣程度。但与优化算法不同的是,遗传编程中的题解并不仅仅是一组用于给定算法的参数,相反,在遗传编程中,连同算法本身及其所有参数,都是需要搜索确定的。

从某种程度上来说,遗传编程和遗传算法的区别在于,进化的基本单位不同,

  • 遗传优化:进化的基本单位是模型可变参数
  • 遗传编程:进化的基本单位是新算法以及新算法的参数

2、遗传编程和进化论的关系

遗传算法是受达尔文的进化论的启发,借鉴生物进化过程而提出的一种启发式搜索算法,因此遗传算法 ( GA , Genetic Algorithm ) 也称进化算法 。 因此,在讨论遗传编程的时候,会大量借用进化论中的术语和概念,为了更好地讨论遗传算法,我们先介绍一些基本生物进化概念,

  • 基因 ( Gene ):一个遗传因子,种群中的最基本单元。
  • 染色体 ( Chromosome ):一组的基因。
  • 交叉(Crossover)和变异(Mutation)
    • 交叉:父母染色体将部分基因随机传下一代,并保证子代的基因数与上一代一致。
    • 变异:子代的某一个基因发生随机变异。
  • 个体 ( individual ):单个生物。在遗传算法中,个体一般只包含一条染色体。
  • 种群 ( Population ):由个体组成的群体。生物的进化以种群的形式进化。
  • 适者生存 ( The survival of the fittest ):对环境适应度高的个体参与繁殖的机会比较多,后代就会越来越多。适应度低的个体参与繁殖的机会比较少,后代就会越来越少。

生物所处的环境起到一个提供生存压的作用(反馈),虽然纵观整个地球历史,环境的因素是在不断变化的(有时甚至变化的还很快),但是在某个时间段内(例如5000年内)是基本保持不变的,而物种进化的目的就是通过一代代的繁衍,逐渐适应(拟合)当前的环境,并和其他物种达到最优平衡(纳什均衡)。

3、遗传编程过程解释

遗传编程算法就是模拟了生物进化的过程,简单说来说,

  • 生物进化的环境由一个用户定义的任务(user-defined task)所决定,算法由一组初始的题解(程序)开始展开竞争。这里所谓的任务可以是多种形式,

    • 一种竞赛(game):各个题解(程序)在竞赛中直接展开竞争
    • 个体测试:测出哪个题解(程序)的执行效果更好
  • 遗传算法将基因抽象为题解中最小的随机变量因子(例如模型中的可变参数)

  • 一个问题的解由很多这样的随机变化因子组成,算法将问题的解编码成个体的染色体(染色体是基因的集合)

  • 单个个体包含若干个染色体,个体包含的染色体(题解)越多和越好,则个体的适应度就越好。在实际工程中,为了简化算法,常常假设一个个体只有一条染色体

  • 多个个体组成种群,种群中适应度(Fitness)高的个体获得较高概率的繁殖机会,从而导致适应度高的个体会越来越多,经过N代的自然选择后,保存下来的个体都是适应度很高的

  • 繁殖过程中,算法会评估并挑选出本轮表现最好的一部分题解题解(程序),并对程序的某些部分以**随机(一定概率)**的方式进行修改,包括:

    • 基因交叉(Acrossover):在最优题解之间,挑选部分随机变量因子进行彼此互换。遗传算法交叉比人体内染色体交叉要简单许多。遗传算法的染色体是单倍体,而人体内的真正的染色体是双倍体。下图是遗传算法中两条染色体在中间进行交叉的示意图,

    • 基因突变(Mutation):在最优题解上,直接对某些随机变量因子(基因位)进行随机修改。下图是遗传算法中一条染色体在第二位发生基因变异的示意图,

  • 经过繁殖过程,新的种群(即新的一组解)产生,称为“下一代”,理论上,这些新的题解基于原来的最优程序,但又不同于它们。这些新产生的题解和旧的最优题解会一起进入下一轮自然选择阶段

    • 上述繁殖过程重复多次,直到达到收敛条件,包括,
    • 找到了全局最优解
    • 找到了表现足够好的解
      题解在历经数代之后都没有得到任何改善
    • 繁衍的代数达到了规定的限制
  • 最终,历史上适应度最高个体所包含的解,作为遗传算法的输出

二、基于遗传编程的例子

1、实战题目介绍

在一个长度为n的数组nums中选择10个元素,使得10个元素的和与原数组的所有元素之和的1/10无限接近。

2、遗传算法的伪代码

BEGIN:
        i = 0;          //进化种群的代数
        Initialize P(i) //初始化种群
        While(not Terminate - Condition)//不满足终止条件时继续循环
        {
            Fitness(i)       // 计算适宜度
            GA-Operation P(i)//交叉、变异操作
            Fitness(i)       // 计算适宜度
            Selection(P)     //物竞天择、适者生存。适应度低的死亡
        }
EMD //结束

3、遗传实战具体代码与详细注释

未来的大佬请上座,下面是依据这个伪代码撰写的遗传实战轮子代码

import random
import math
# 定义问题参数
total_numbers = 100   # 种群的基因上下限  (人类基因组)
Generange=1000        # 种群基因的取值范围 (理论上全部物种的基因范围)
selected_numbers = 10 # 一个个体占据的基因 (一个人的全部基因 :20000~25000)
pop_size=100          # 这个种群的个体个数 (一个人群的人数)
terminder=10          # 进化的终点       (进化到什么程度结束)

# 生成初始种群与种群基因组
def generate_population():

    population = []
    HumanGene = random.sample(range(Generange),100) # 从全部基因取值范围里面选取100个做为这个种群的基因取值范围
    for _ in range(pop_size):
        # 从种群的基因取值范围里面选取10个基因做为一个个体的全部基因组成
        individual = random.sample(HumanGene, selected_numbers)
        population.append(individual)
    return population,HumanGene

# 计算个体的适应度
def fitness(individual,HumanGene):
    #
    sum_selected = sum(individual)
    sum_total = sum(HumanGene)
    diff = abs(sum_selected - sum_total / 10)
    return 10 / (diff + 1) # diff越小,权重越大


# 选择优秀个体,将后面的一半淘汰掉
def selection(population, fitness_values):
    selected = random.choices(population, weights=fitness_values, k=total_numbers)
    return selected


# 两个人交配并生两娃的操作
def crossover(parent1, parent2):
    # pivot是染色体杂交的位点
    pivot = random.randint(1, selected_numbers - 1)
    child1 = parent1[:pivot] + parent2[pivot:]
    child2 = parent2[:pivot] + parent1[pivot:]
    return child1, child2

# 个体变异操作
def mutate(individual,HumanGene):
    # 确定那个位置变异
    mutated_index = random.randint(0, selected_numbers - 1)
    individual[mutated_index] =random.sample(HumanGene,1)[0]
    return individual


# 遗传编程主函数
def genetic_algorithm( generations):
    # 生成种群100
    population ,HumanGene= generate_population()

    for _ in range(generations):
        # 适宜度计算
        fitness_values = [fitness(individual,HumanGene) for individual in population]

        # 选择、交配、变异
        new_population = population.copy()
        for _ in range(pop_size//2):
            # 从人群中依据适宜度,做为权重,权重越高选择中的概率就越高
            # 选两个出来交配,生下两娃
            parent1, parent2 = random.choices(population, k=2, weights=fitness_values)
            child1, child2 = crossover(parent1, parent2)

            # 让下一代概率性变异
            if random.random() < 0.1:
                child1 = mutate(child1,HumanGene)
            if random.random() < 0.1:
                child2 = mutate(child2,HumanGene)

            # 将孩子插入到新的种群中
            new_population.extend([child1, child2])

        # 重新计算群体的适宜度,然后再依据适宜度进行淘汰
        fitness_values=[fitness(ind,HumanGene) for ind in new_population] #
        population = selection(new_population, fitness_values)
    # 依据适宜度返回最佳的个体
    best_individual = max(population, key=lambda x:fitness(x,HumanGene))
    return population,HumanGene,best_individual


# 运行遗传编程
population,HumanGene,best_solution = genetic_algorithm(generations=1000)
print('最终的种群:'+str(population))
print('种群的基因组:'+str(HumanGene))

print('基因组的和:'+str(sum(HumanGene)))
print("最佳解决方案:{},解决方案的和:{}".format(str(best_solution),sum(best_solution)))
print("从基因组中抽出的10个值的和,近乎是整个基因组的和的十分之一,差:"+str(abs(sum(HumanGene)//10-sum(best_solution))))

运行结果::

4、将以上纯python运算实现代码套入DEAP强化学习框架实现

DEAP是目前强化学习主流使用的框架,可以看到在这个框架的支持下,结构和代码量都减少了许多,并且也有了更多的可视化过程。
解决问题:在一个长度为n的数组nums中选择10个元素,使得10个元素的和与原数组的所有元素之和的1/10无限接近。
具体代码如下

import random
from deap import base, creator, tools, algorithms

# 定义问题参数
total_numbers = 100   # 种群的基因上下限  (人类基因组)
Generange=1000        # 种群基因的取值范围 (理论上全部物种的基因范围)
selected_numbers = 10 # 一个个体占据的基因 (一个人的全部基因 :20000~25000)
pop_size=100          # 这个种群的个体个数 (一个人群的人数)
terminder=10          # 进化的终点       (进化到什么程度结束)


nums = [random.randint(1, Generange) for _ in range(100)]  # 生成一个长度为100的随机数组
target_sum = sum(nums) / 10  # 目标和为原数组所有元素之和的1/10


# 创建遗传算法所需的工具:个体类、种群类、目标函数、交叉函数、变异函数等
# 一、定义问题,是最小化问题还是最大化
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))  # 目标是最小化目标函数
creator.create("Individual", list, fitness=creator.FitnessMin)

# 二、生成个体
IND_SIZE = 10  # 个体大小,即选择的元素数量
toolbox = base.Toolbox()
toolbox.register("indices", random.sample, range(len(nums)), IND_SIZE)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.indices)
# 三、生成初始种群
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
pop = toolbox.population(n=300)  # 种群大小

# 四、定义遗传算子:评估函数、交叉函数、变异函数、选择函数
def evalSolution(individual):
    """评价函数,计算个体与目标和的差的绝对值"""
    return (abs(sum(nums[i] for i in individual) - target_sum),)

toolbox.register("evaluate", evalSolution)                       # 评价个体的适应度的函数,由于权重是最小化,所以越小适应度越高。
toolbox.register("mate", tools.cxTwoPoint)                       # 使用两点交叉
toolbox.register("mutate", tools.mutShuffleIndexes, indpb=0.05)  # 使用基因位置交换的方式变异
toolbox.register("select", tools.selTournament, tournsize=3)     # 使用锦标赛选择

def main():
    random.seed(64)

    hof = tools.HallOfFame(1)  # 保留最佳个体
    stats = tools.Statistics(lambda ind: ind.fitness.values) # 运行中间输出
    stats.register("avg", lambda x: sum(val[0] for val in x) / len(x))

    stats.register("min", min)
    stats.register("max", max)

    algorithms.eaSimple(pop, toolbox, cxpb=0.5, mutpb=0.2, ngen=50,
                        stats=stats, halloffame=hof, verbose=True)

    return hof[0]

if __name__ == "__main__":
    best = main()
    print("Best individual is:", best)
    print("Sum of selected elements:", sum(nums[i] for i in best))
    print('Sum of Gene:',sum(nums))

运行过程:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无人机机载频谱监测方案助力空中频谱监测与干扰排查

作者介绍 一、方案背景 频谱资源是通信最重要的资产之一&#xff0c;随着宽带无线业务的快速增长&#xff0c;对频率资源的需求大幅增加。未来频率资源的供需矛盾将非常突出&#xff0c;空中频谱环境也会越来越复杂&#xff0c;对于工程师来说&#xff0c;在复杂的电磁环境条件…

视频监控/云存储EasyCVR视频融合平台设备增删改操作不生效是什么原因?

国标GB28181协议EasyCVR安防平台可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力&#xff0c;平台支持7*24小时实时高清视频监控&#xff0c;能同时播放多路监控视频流&#xf…

C++开发基础——类模板

一&#xff0c;基础定义 类模板是用来生成类的蓝图&#xff0c;是一种创建类的方式&#xff0c;同一套类模板可以生成很多种不同的类。 编译器基于类模板生成的每个类被称为类模板的实例。 第一次使用模板类型声明变量时&#xff0c;会创建类模板的一个实例&#xff0c; 以后…

3D Gaussian Splatting for Real-Time Radiance Field Rendering(慢慢啃,还是挺复杂的)

三个关键要素 从相机配准的过程中得到的稀疏点云开始&#xff0c;使用3D Gaussian表示场景; 3D Gaussian: 是连续体积辐射场能够防止不必要的空空间优化。对 3D Gaussion进行交叉优化和密度控制: 优化各向异性血方差对场景精确表示。使用快速可视感知渲染算法来进行快速的训练…

最好用的流程编辑器bpmn-js系列之基本使用

BPMN&#xff08;Business Process Modeling Notation&#xff09;是由业务流程管理倡议组织BPMI&#xff08;The Business Process Management Initiative&#xff09;开发的一套标准的业务流程建模符号规范。其目的是为用户提供一套容易理解的标准符号&#xff0c;这些符号作…

Java代码审计工程师直播第六期

本期直播课程将深入探讨Java代码审计的关键概念和技术。涵盖课题包括安全漏洞分析、代码审查方法、常见漏洞案例分析等。学员将通过实例掌握代码审计实战技能&#xff0c;提升对Java应用程序安全的认知和技能水平。 课程大小&#xff1a;6.1G 课程下载&#xff1a;https://do…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的稻田虫害检测系统详解(深度学习+Python代码+UI界面+训练数据集)

摘要&#xff1a;本篇文章深入探讨了如何利用深度学习技术开发一个用于检测稻田虫害的系统&#xff0c;并且分享了完整的实现过程和资源代码下载。该系统采用了当前的YOLOv8、YOLOv7、YOLOv6、YOLOv5算法&#xff0c;对其进行了性能对比&#xff0c;包括mAP、F1 Score等关键指标…

java中xml概述

1.xml 1.1概述【理解】 万维网联盟(W3C) 万维网联盟(W3C)创建于1994年&#xff0c;又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。 建立者&#xff1a; Tim Berners-Lee (蒂姆伯纳斯李)。 是Web技术领域最具权威和影响力的国际中立性技术标准机构。 到目前为…

Linux认识与学习BASH

Linux认识与学习BASH 认识BASH这个Shellshell是什么系统的合法shell与/etc/shells功能Bash Shell的功能查询命令是否为Bash shell 的内置命令(type)命令的执行与快速编辑按钮 shell的变量功能什么是变量&#xff1f;变量的使用与设置&#xff1a;echo、变量设置规则、unset环境…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Slider)

滑动条组件&#xff0c;通常用于快速调节设置值&#xff0c;如音量调节、亮度调节等应用场景。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Slider(options?: SliderOption…

Linux:时间指令 - cal date

Linux&#xff1a;时间指令 - cal & date date指令cal指令 date指令 date用于以指定格式显示时间 我们先看看直接输入date指令的效果&#xff1a; [hxyiZ2zehtehrgzt3wqccrpyfZ CSDN]$ date Tue Mar 12 21:38:01 CST 2024直接输入date指令&#xff0c;得到了以 星期 月 日…

RANDOMIZE-IN-PLACE随机排列算法

给定一个长度为 n n n的数组&#xff0c;如何构造出一个随机排列呢&#xff1f;《算法导论》给了我们一个名为RANDOMIZE-IN-PLACE的随机算法&#xff0c;该算法在数组原址上进行排序&#xff0c;时间复杂度为 O ( n ) O(n) O(n)。下面本文将介绍RANDOMIZE-IN-PLACE的设计思想及…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的水下目标检测系统(深度学习模型+UI界面+训练数据集)

摘要&#xff1a;本研究详述了一种采用深度学习技术的水下目标检测系统&#xff0c;该系统集成了最新的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等早期算法进行了性能评估对比。该系统能够在各种媒介——包括图像、视频文件、实时视频流及批量文件中——准确地识别水…

HarmonyOS NEXT应用开发之多层嵌套类对象监听

介绍 本示例介绍使用Observed装饰器和ObjectLink装饰器来实现多层嵌套类对象属性变化的监听。 效果图预览 使用说明 加载完成后显示商品列表&#xff0c;点击刷新按钮可以刷新商品图片和价格。 实现思路 创建FistGoodsModel类&#xff0c;类对象是用Observed修饰的类Secon…

Linux运维:磁盘分区与挂载详解

Linux运维&#xff1a;磁盘分区与挂载详解 1、磁盘分区的原理2、查看系统中所有的磁盘设备及其分区信息3、进行磁盘分区&#xff08;对于sdb新磁盘&#xff09;4、格式化分区5、挂载分区&#xff08;临时挂载、永久挂载&#xff09;6、取消挂载分区7、删除分区 &#x1f496;Th…

pytorch激活函数

目录 1.激活函数由来2. 常见激活函数2.1 Sigmoid2.2 Tanh2.3 relu 1.激活函数由来 科学家对青蛙的神经元进行研究的时候发现&#xff0c;只有超过一定的阈值青蛙才会有反应&#xff0c;因此不能将多个输入做简单的加权平均&#xff0c;而需要一个阶梯函数也就是激活函数&#…

软考75-上午题-【面向对象技术3-设计模式】-设计模式的要素

一、题型概括 上午、下午题&#xff08;试题五、试题六&#xff0c;二选一&#xff09; 每一个设计模式都有一个对应的类图。 二、23种设计模式 创建型设计模式&#xff1a;5 结构型设计模式&#xff1a;7 行为设计模式&#xff1a;11 考试考1-2种。 三、设计模式的要素 3…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的烟雾检测系统详解(深度学习模型+UI界面升级版+训练数据集)

摘要&#xff1a;本研究详细介绍了一种集成了最新YOLOv8算法的烟雾检测系统&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等早期算法进行性能评估对比。该系统能够在包括图像、视频文件、实时视频流及批量文件中准确识别烟雾。文章深入探讨了YOLOv8算法的原理&#xff0c;提供了Pyth…

cocos2d-x-3.17 android升级 gradle NDK_DEBUG=0 -o NDK_DEBUG=1 -o cocos2dlua_shared

由于需要升级sdk版本 需要对应升级gradle版本 记录下升级内容 externalNativeBuild { ndkBuild { - //arguments NDK_DEBUG0 -o 修改成下面 arguments NDK_DEBUG0 } } debug { …

抓取Instagram数据:Fizzler库带您进入C#爬虫程序的世界

引言 在当今数字化的世界中&#xff0c;数据是无价之宝。社交媒体平台如Instagram成为了用户分享照片、视频和故事的热门场所。作为开发人员&#xff0c;我们可以利用爬虫技术来抓取这些平台上的数据&#xff0c;进行分析、挖掘和应用。本文将介绍如何使用C#编写一个简单的Ins…
最新文章