对遗传算法思想的理解与实例详解

目录

一、概述

二、实例详解

1)问题描述与分析

2)初始化种群

3)计算种群适应度

4)遗传操作

5)基因交叉操作

6)变异操作

三、计算结果

四、总结 


一、概述

       遗传算法在求解最优解的问题中最为常用,不论是在线性还是非线性问题中都得到广泛运用。本文主要介绍对遗传算法思想的个人理解,并结合一个简单实例进行说明,以便在后续实际问题中能够借助遗传算法思想解决问题。首先需要明白的是,遗传算法只是一种求解最优近似解的算法之一,它不是用于求解精确解的方法。当然,如果我们能得到精确解,自然也没必要去研究最优近似解。

       从遗传算法的名字我们也可知道,这个算法的思想借助了生物学上生物进化与基因遗传的思想。生物个体在进化过程中,基因代代相传,并在传递过程中出现基因混合、突变等现象,然后适应环境的基因被保存下来,不适应环境的基因被淘汰出局,如此生物基因逐步达到与环境的最佳适配。遗传算法的迭代过程正式基于生物进化过程来构建,并用相应的数学概念来对应生物进化过程的个体、基因、遗传、混合(杂交)、淘汰等,其过程完全按照生物进化过程进行迭代演进。

       我们知道,生物进化中基因传递、自然淘汰等都是不可预测的概率事件。因此,遗传算法迭代过程也充满了不可预测性。虽然总体趋势是向最优方向发展,但是我们并不能准确给出何时算法能得到我们认为的最优近似结果。也或许在某些问题中,我们根本不知道得到的结果是否就是最好的解。

二、实例详解

1)问题描述与分析

      使用遗传算法计算函数result = x + 10 * sin(4*x) + 7 * cos(3*x)在自变量[0,10]以内的最大值。这是一个非常简单的求极值问题,我们通过解析法也可以得到精确解,但是此处我们需要借助这个问题来详细说明遗传算法的实现。通过前面的概述,我们可以知道遗传算法的实现应该依次有以下步骤:创建一个初始种群—>计算种群的适应度—>种群遗传—>新种群杂交—>新种群变异—>计算新种群适应度,如此循环进行上述操作,直到我们得到合适的结果或迭代步数完成为止。下面借助MATLAB逐一说明每一步的实现过程。

2)初始化种群

       从生物学角度来讲,一个种群包含若干个体,一个个体包含若干基因。因此,初始化种群前我们需要确定这个种群的个体数量和每个个体包含多少基因。在实际操作中,种群的大小和基因数量都应根据实际问题来分析设置,因为它们直接影响算法的收敛速度和求解精度。在此问题中,我们可以选择种群数量为50个个体,这个值尽量大一点,在计算机性能允许的条件下。每个个体的基因数量设置为20。

       此处作进一步说明,个体其实就是我们预设的一组方程x的解,这里我们随机预设了50个解,当然我们并不知道其中是否包含了最优解,这50个解我们将使用程序自动随机生成。个体的基因其实就是对每个解使用二进制编码时需要使用的二进制位数,这个位数越长,解的精度越高,当然对计算机性能的要求也越高,如果实际问题对求解精度要求很高,需要编码长度越长。在遗传算法中,使用二进制对个体(解)进行编码是最常用,且最直观的方式,因此此处就直接采用二进制编码形式。初始化种群的具体实现如下段MATLAB代码所示。

        此段代码已逐行解释,核心是initial_group = randi([0,1],NP, L),randi函数实现了一个随机初始化种群,并将该种群放入矩阵initial_group中。randi函数的作用是生成一个NP行,L列的整数矩阵,该矩阵中的元素在0和1之间随机取值。由此我们可以知道,initial_group矩阵中,每一行表示一个个体,共有50个,每个个体包含20个基因,而基因是由0和1组成的。至于每个个体和解的对应关系,后面详述。

NP = 50;%种群个体数量
L = 20;%个体编码长度
PC = 0.8;%交叉概率
PB = 0.1;%变异概率
G = 100;%最大迭代次数
up = 10;%上限
down = 0;%下限
initial_group = randi([0,1],NP, L);%初始化种群

3)计算种群适应度

        计算种群适应度,就是要得到在当代的种群中,每个个体对环境的适应度,环境适应度高的个体我们保留并遗传至下一代,适应度低的个体我们就淘汰。在此问题中我们要做的就是得到每个个体接近最大值的程度,因此我们要分析如何来设计这个适应度函数。从某种程度上说,适应度函数的设计是影响遗传算法解决实际问题效果的核心环节。某些地方也将适应度函数称为评价函数,即用于评价群体中个体的优劣。适应度函数也是实际问题与遗传算法相关联的关键数学模型,在此问题中,我们直接给出了一个数学模型,分析时比较简单,但在许多实际问题中需要我们自己去建立一个合理的数学模型,这也是用遗传算法解决实际问题的难点所在。

       在本问题中,我们的目的是求函数的最大值(x,y),并给出了函数公式,因此我们可以直接采用原函数作为适应度函数,将个体带入函数中,得到的值越大,说明个体适应度越高,简单且直观。

function result = fitnessFun(x)
result = x + 10 * sin(4*x) + 7 * cos(3*x);
end

       而我们在具体实现时还需要做一些处理。 首先是将群体中的个体转换为适应度函数的输入值,我们初始化得到的群体是一群使用二进制编码的个体,并不是直观的函数输入值,所以我们首先需要将二进制编码的个体转换为十进制数,并将这群个体限制在给定的求值范围内,这样就得到了适应度函数可用的输入值,具体代码如下:

U = initial_group(i,:);
value = 0;
for j = 1:Lvalue = U(j)*2^(j-1) + value;
end
x(i) = down + value * (up - down)/(2^L - 1);%将编码转换为函数输入值

       然后,我们将转换后的个体带入适应度函数中,就可以得到每个个体的适应度值。此处对适应度值进行了归一化处理,将适应度控制在0到1之间,便于后续处理。

 Fit = fitnessFun(x);maxFit = max(Fit);%最大适应度值minFit = min(Fit);%最小适应度值inde_maxFit = find(Fit == maxFit);%适应度最大的个体所在位置,可能有多个值best_unit = initial_group(inde_maxFit(1,1),:);%当代中最优个体best_unitV = x(inde_maxFit(1,1));%该最优个体对应的值Fit = (Fit - minFit)/(maxFit - minFit);%归一化适应度值,限制在0到1之间

4)遗传操作

       以下开始进行进化操作,首先是进行遗传,即根据当代种群的适应度值选择哪些个体可以被遗传到下一代。常用的遗传操作方法是轮盘赌方式,具体实现代码如下所示。轮盘赌方式就是将个体的概率按大小成比例按顺序分布在圆盘上,圆盘扇形区域的大小反映了个体概率大小。当转动轮盘时,指针最后指向的区域对应个体就是选中的个体。由此可知,个体概率越大,被选中的概率就越大。

       下述代码中,前两行是将适应度值转化为概率值。cumsum函数将概率值进行逐项连续累加,作为轮盘赌的概率值。while循环中执行了轮盘赌操作,总共执行了NP(50)次。采用轮盘赌操作后,适应度高的个体被遗传到下一代的概率大,且同一个个体存在被多次遗传到下一代的可能。通过遗传操作后,新的种群数量与上一代个体数量保持一致。

sum_fit = sum(Fit);
fitvalue = Fit./sum_fit;
fitvalue = cumsum(fitvalue);%对向量fitvalue进行逐项累加,返回一个向量如:1 2 3,返回1 3 6
ms = sort(rand(NP,1));%生成一组随机向量,并按从小到大排序
inde_fit = 1;
inde_newUnit = 1;
while inde_newUnit <= NP%执行轮盘赌操作,上一代中同一个个体存在被多次遗传至下一代的可能if(ms(inde_newUnit)) < fitvalue(inde_fit)new_group(inde_newUnit,:) = initial_group(inde_fit,:);%复制个体,直接遗传至下一代inde_newUnit = inde_newUnit + 1;elseinde_fit = inde_fit +1;end
end

5)基因交叉操作

       交叉操作是指在上述新产生的子代群体中,选择两个个体,对这两个个体对应位置的基因进行交换。具体实现代码如下,我们直接依次选取相邻两个个体进行交叉操作。p是随机生成的一个随机数,通过与PC比较用于判断是否要执行交叉操作。q是随机生成的一个长度为L的0和1的向量。这个向量的作用是用于实现随机选择需要交叉的位置。此处我们将元素1对应的位置进行交叉。向量q保证了我们执行交叉时,交叉的位置和基因数量的随机性。

    for i = 1:2:NP%在相邻两个个体之间执行交叉操作p = rand;%产生一个随机数if p < PCq = randi([0,1],1,L);for j = 1:Lif q(j) == 1temp = new_group(i+1, j);new_group(i+1, j) = new_group(i, j);new_group(i, j) = temp;endendendend

6)变异操作

        变异就是将一个个体中某些位置的基因进行修改,对于二进制编码的个体而言,就是将部分位置的编码元素取反。具体实现如下,while循环表征了执行变异次数的随机性,inde_varUnit表征了执行变异个体的随机性,for循环表征了执行变异基因的位置和数量的随机性。

    i = 1;while i <= round(NP*PB)inde_varUnit = randi([1,NP]);%随机指定需要变异的个体for j = 1:round(L*PB)inde_varD = randi([1,L]);%随机指定需要变异的基因位置new_group(inde_varUnit, inde_varD) = ~new_group(inde_varUnit, inde_varD);%取反即可endi= i + 1;end

三、计算结果

在本实例中,函数的实际图像如下,函数的最大值约为(8.28,24.8935)。

采用遗传算法求解过程如下,得到的最优解为(8.28822,24.9005),相差很小。 参考源代码实现。

四、总结 

        本文详细讲述了经典遗传算法的思想和典型案例实现思路。遗传算法从一群初始解中去寻找最优解,并在迭代过程中不断优化这个解群,其优化方法是大概率继承前一代中最优的解,并对新的解群进行交叉、变异操作,以产生出新的解。在此过程中有两个关键环节,一是解的适应度函数模型,这个是连接遗传算法和实际问题的纽带,是我们分析实际问题是否适用遗传算法的关键;二是解的优化,从上述过程中我们可知,解的优化在交叉和变异,只有这两步才会在原有解的基础上产生出新的解,而这两步操作充满了随机性。其中交叉的概率我们设置得比较大,因为交叉后产生的新解大概率不会与原解存在较大的差异,避免新的解呈现大幅度杂乱无序的变化。而变异操作我们设置的概率很小,且在执行次数、变异位置和数量上都引入了变异概率。这是因为变异操作针对单个个体,一个编码位置的突变可能会导致出现一个异常偏离群体的个体,我们自然不能允许这样的个体在群体中大量出现,但是我们又不能杜绝这样的个体出现,因为没有异常偏离群体的个体,我们可能会丢失可能存在的其他最优解,而陷入局部最优中,变异操作在一定程度上可以避免这样的情况。

        从本文实例中我们还可知,遗传算法的初始解群体对算法收敛影响很大。本例中,我们限定了所有解的范围,算法收敛速度很快,如果我们不限定范围,或者我们将初始解群体限制在[0,5],可想而知我们可能得不到最优解,或陷入局部最优中。遗传算法提供的是一种求解最优解的思想,而不是一种固定的模式方法,套用模式只会限制它的应用。因此具体问题要具体分析,我们要尽可能在初始化群体时确保最优解在群体囊括的包络内,轮盘赌的遗传方式是否合适,是否需要继承一些适应度小的个体,变异的概率是否需要大一些,以确保群体的多样性等,这些都是在分析实际问题时需要考虑的。通常情况下,如果我们无法限定解的范围,也无法确定适应度函数的趋势,那么使用遗传算法求解也是不合适的。比如在此例中,不限定解的范围,在整个实数域我们是无法求解的。

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

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

相关文章

计算机图形学编程(使用OpenGL和C++)(第2版) 学习笔记 07.光照

1. 光照 1.1. 光源 光源类型特点优点缺点环境光整个场景均匀受光&#xff0c;无方向和位置。模拟全局光照&#xff0c;避免完全黑暗的区域。缺乏方向性和真实感&#xff0c;无法产生阴影。平行光光线方向平行&#xff0c;无位置&#xff0c;仅有方向。计算简单&#xff0c;适…

Python在大数据机器学习模型的多模态融合:深入探索与实践指南

一、多模态融合的全面概述 1.1 多模态融合的核心概念 多模态融合(Multimodal Fusion)是指将来自不同传感器或数据源(如图像、文本、音频、视频、传感器数据等)的信息进行有效整合,以提升机器学习模型的性能和鲁棒性。在大数据环境下,多模态融合面临着独特的挑战和机遇: 数…

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】6.4 时间序列分析(窗口函数处理时间数据)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 PostgreSQL时间序列分析&#xff1a;窗口函数处理时间数据实战一、时间序列分析核心场景与窗口函数优势1.1 业务场景需求1.2 窗口函数核心优势 二、窗口函数基础&#xff1a…

window 显示驱动开发-配置内存段类型

视频内存管理器&#xff08;VidMm&#xff09;和显示硬件仅支持某些类型的内存段。 因此&#xff0c;内核模式显示微型端口驱动程序&#xff08;KMD&#xff09;只能配置这些类型的段。 KMD 可以配置内存空间段和光圈空间段&#xff0c;其中不同&#xff1a; 内存空间段由保存…

笔记,麦克风的灵敏度

麦克风的“灵敏度&#xff08;Sensitivity&#xff09;”决定了它捕捉声音细节的能力。想象麦克风是一只有耳朵的生物。高灵敏度麦克风像长着“超级顺风耳”的精灵&#xff0c;能听见花瓣飘落的声音、远处树叶的沙沙声&#xff0c;甚至你心跳的微弱震动。适合录音棚里捕捉歌手的…

lvm详细笔记

LVM简介 逻辑卷管理器&#xff0c;是Linux 系统中用于管理磁盘储存的关键技术。 LVM 则打破了磁盘分区一旦确定&#xff0c;其大小调整往往较为复杂&#xff0c;且难以灵活应对业务变化这种限制&#xff0c;它允许用户将多个物理分区组合卷组。例如&#xff0c;系统中的多个物…

rust-candle学习笔记10-使用Embedding

参考&#xff1a;about-pytorch candle-nn提供embedding()初始化Embedding方法: pub fn embedding(in_size: usize, out_size: usize, vb: crate::VarBuilder) -> Result<Embedding> {let embeddings vb.get_with_hints((in_size, out_size),"weight",cr…

Python小酷库系列:Munch,用对象的访问方式访问dict

Munch&#xff0c;用对象的访问方式访问dict 基本使用1、创建一个 Munch 对象2、使用字典初始化3、访问不存在的字段4、嵌套结构支持5、合并操作6、应用场景说明 进阶功能1、嵌套写入&#xff1a;创建不存在的子对象2、序列化&#xff08;转回 dict&#xff09;3、深度拷贝结构…

对称加密以及非对称加密

对称加密和非对称加密是两种不同的加密方式&#xff0c;它们在加密原理、密钥管理、安全性和性能等方面存在区别&#xff0c;以下是具体分析&#xff1a; 加密原理 对称加密&#xff1a;通信双方使用同一把密钥进行加密和解密。就像两个人共用一把钥匙&#xff0c;用这把钥匙锁…

[JAVAEE]HTTP协议(2.0)

响应报文格式 响应报文格式由首行&#xff0c;响应头&#xff08;header&#xff09;&#xff0c;空行&#xff0c;正文&#xff08;body&#xff09; 组成 响应报文首行包括 1.版本号 如HTTP/1.1 2.状态码(如200) 描述了请求的结果 3.状态码描述(如OK) 首行——状态码…

Spring Boot 之MCP Server开发全介绍

Spring AI 的 MCP(模型上下文协议,Model Context Protocol)服务器启动器为在 Spring Boot 应用程序中设置 MCP 服务器提供了自动配置功能。它使得 MCP 服务器功能能够与 Spring Boot 的自动配置系统实现无缝集成。 MCP 服务器启动器具备以下特性: MCP 服务器组件的自动配置…

YOLOv8 对象检测任务的标注、训练和部署过程

YOLOv8 对象检测任务的标注、训练和部署过程 在计算机视觉领域&#xff0c;对象检测是一项基础且重要的任务&#xff0c;YOLOv8 作为当前先进的实时对象检测模型&#xff0c;以其高效性和准确性受到广泛关注。从数据准备到最终模型部署&#xff0c;整个流程包含多个关键环节&a…

电池热管理CFD解决方案,为新能源汽车筑安全防线

在全球能源结构加速转型的大背景下&#xff0c;新能源汽车产业异军突起&#xff0c;成为可持续发展的重要驱动力。而作为新能源汽车 “心脏” 的电池系统&#xff0c;其热管理技术的优劣&#xff0c;直接决定了车辆的安全性、续航里程和使用寿命。电池在充放电过程中会产生大量…

Redis 数据类型:掌握 NoSQL 的基石

Redis (Remote Dictionary Server) 是一种开源的、内存中的数据结构存储系统&#xff0c;通常用作数据库、缓存和消息代理。 它的高性能和丰富的数据类型使其成为现代应用程序开发中不可或缺的一部分。 本文将深入探讨 Redis 的核心数据类型&#xff0c;帮助你更好地理解和利用…

MLX-Audio:高效音频合成的新时代利器

MLX-Audio&#xff1a;高效音频合成的新时代利器 现代社会的快节奏生活中&#xff0c;对语音技术的需求越来越高。无论是个性化语音助手&#xff0c;还是内容创作者所需的高效音频生成工具&#xff0c;语音技术都发挥着不可或缺的作用。今天&#xff0c;我们将介绍一个创新的开…

Kafka单机版安装部署

目录 1.1、概述1.2、系统环境1.3、ZooKeeper的作用1.4、部署流程1.4.1、下载安装包1.4.2、解压文件1.4.3、创建日志目录1.4.4、配置Kafka1.4.5、启动Kafka服务1.4.6、启动成功验证 1.5、创建Topic测试1.6、消息生产与消费测试1.6.1、启动生产者1.6.2、启动消费者 1.1、概述 Kaf…

【C++设计模式之Observer观察者模式】

Observer观察者模式 模式定义动机(Motivation)结构(Structure)应用场景一&#xff08;气象站&#xff09;实现步骤1.定义观察者接口2.定义被观察者(主题)接口3.实现具体被观察者对象(气象站)4.实现具体观察者(例如&#xff1a;显示屏)5.main.cpp中使用示例6.输出结果7. 关键点 …

资产月报怎么填?资产月报填报指南

资产月报是企业对固定资产进行定期检查和管理的重要工具&#xff0c;它能够帮助管理者了解资产的使用情况、维护状况和财务状况&#xff0c;从而为资产的优化配置和决策提供依据。填写资产月报时&#xff0c;除了填报内容外&#xff0c;还需要注意格式的规范性和数据的准确性。…

UG471 之 SelectIO 逻辑资源

背景 《ug471》介绍了Xilinx 7 系列 SelectIO 的输入/输出特性及逻辑资源的相关内容。 第 1 章《SelectIO Resources》介绍了输出驱动器和输入接收器的电气特性&#xff0c;并通过大量实例解析了各类标准接口的实现。 第 2 章《SelectIO Logic Resources》介绍了输入输出数据…

C++ 内存泄漏相关

ASAN 参考链接 https://blog.csdn.net/wonengguwozai/article/details/129593186https://www.cnblogs.com/greatsql/p/16256926.htmlhttps://zhuanlan.zhihu.com/p/700505587小demo // leak.c #include <stdio.h> #include <stdlib.h> #include <string.h>…