遗传算法的应用——求解一元函数的极值

news2024/11/18 3:34:05

遗传算法的应用——求解一元函数的极值

  • 1 基本概念
  • 2 预备知识
    • 3.1 模拟二进制转化为十进制的方法
    • 3.2 轮盘赌选择算法
  • 3 问题
  • 4 Matlab代码
  • 5 运行效果
  • 6 总结

1 基本概念

  • 遗传算法(Genetic Algorithm,GA)是模拟生物在自然环境中遗传和进化过程从而形成的随机全局搜索和优化方法,它是一种并行的、高效的、具有自适应能力的全局搜索算法,它充分体现了适者生存的生物进化思想,能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最优解。
  • 遗传算法能有效求解NP问题和非线性、多峰函数优化及多目标优化问题。
  • 遗传算法的三个最重要操作选择(复制) -> 交叉 -> 变异
  • 遗传算法:
    • 以决策变量的编码作为运算对象
    • 直接以目标函数值作为搜索信息
    • 同时使用多个搜索点的搜索信息
    • 是一种基于概率的搜索方法
    • 求解最大值问题(最小值问题理论上添一个负号就是最大值问题,还有其他方法可以转换问题的导向)
  • 遗传算法在进化搜索中基本不用外部信息,仅以适应度函数为依据
  • 但是基本遗传算法的局部搜索能力较差,有“早熟”缺陷,不能保证算法收敛
  • 下边对遗传算法中用到的几个重要的参数进行一个简单的说明:
    • 群体规模:群体规模太小时,算法的搜索效果通常较差,容易陷入局部最优;群体规模太大时,算法的计算复杂度将会变大。一般取值为[10,200];
    • 交叉概率:在基本遗传算法中,将交叉算子作为遗传算法最重要的操作。较大的交叉概率可以增强算法开辟新的搜索区域的能力,但高性能的模式,也就是二进制组合遭到破坏的可能性增大;交叉概率太低可能会导致算法陷入迟钝状态。一般取值为[0.4,0.99];
    • 变异概率:变异算法的主要目的是保持群体的多样性。低的变异概率可以防止群体中重要基因的丢失;变异概率太大时,算法就变成了纯粹的随机搜索算法。一般取值为[0.0001,0.1];

2 预备知识

3.1 模拟二进制转化为十进制的方法

      在遗传算法中,通常会涉及到二进制到十进制的转换,所以需要掌握这个方法,那么为什么说是模拟二进制转为十进制的方法呢,因为我们在代码中通常不是真正的一串二进制数字,而是由一个向量,其中存放许多0101这样的数字,如a=[0 1 0 1],这样就模拟了一个二进制数,那么它对应的十进制就是5,在matlab中有两个方法,这两种方法对于大量的数据其转换速度有较大差异,请合理选择,如果有其他方法,请各位朋友留言。

%% 法一 通过循环实现
a = [1 0 0 1 1 0 0 1];
deca = 0;
for i = 1:length(a)
	deca = a(i)*2^(i-1) + a;
end

%% 法二 通过强制转换实现(调用库函数)
a = [1 0 0 1 1 0 0 1];
deca = bin2dec(char('0'+ a));

3.2 轮盘赌选择算法

       轮盘赌选择算法是遗传算法中,进行复制操作的一种常用算法,在该方法中,各个个体的选择概率和其适应度值成比例,适应度越大,选中概率也越大。但实际在进行轮盘赌选择时个体的选择往往不是依据个体的选择概率,而是根据“累积概率”来进行选择。我将通过一个抽奖的例子进行一个简单地介绍(参考文章:轮盘赌选择算法):

等级一等奖二等奖三等奖
选择概率0.20.50.3
累计概率0.20.71.0

可以从概论论的角度出发,先简单地将选择概率理解为概率密度函数,设xi(i=1,2,3)表示获奖等级,则f(xi)表示该等级对应的适应度,则xi被选中的概率Pxi可以被表示为:
在这里插入图片描述

将累计概率Qxi理解为概率分布函数,则Qxi可以表示为从xi开始往前的所有的概率的累加和:
在这里插入图片描述

  1. 计算个体的被选择概率(概率密度函数)
  2. 计算各个部分的累计概率(概率分布函数–离散型)
  3. 生成一个[0,1]区间内均匀分布的随机实数,代表此时轮盘的旋转位置(这里就可以理解为什么用累计概率了)
  4. 找到累计概率中第一个大于或等于第3步产生的随机数的索引,这个索引就是轮盘赌算法选择的那个个体(不理解可以先看代码)

以一个抽奖问题为导引的轮盘赌算法实例Matlab代码如下:

clc
clear

% 定义奖项及其中奖概率
awards = {'一等奖', '二等奖', '三等奖', '四等奖', '五等奖'};
P = [0.1, 0.2, 0.3, 0.2, 0.2]; % 中奖概率
cumP = cumsum(P);    % 累计概率

% 模拟抽奖过程
N = 1000; % 模拟次数
results = zeros(1, N); % 存储每次抽奖的结果
for i = 1:N
    % 生成一个随机数,代表轮盘的旋转位置
    pos = rand();
    % 根据轮盘赌算法确定中奖等级
    level = find(cumP >= pos, 1);
    % 存储结果
    results(i) = level;
end

% 统计中奖次数
winCounts = histcounts(results, 1:(length(awards) + 1));

% 显示结果
disp('中奖统计:');
for i = 1:length(awards)
    fprintf('%s:%d次\n', awards{i}, winCounts(i));
end

上述代码中,有两行代码需要自己好好理解一下:

% 根据轮盘赌算法确定中奖等级
level = find(cumP >= pos, 1);

% 统计中奖次数
winCounts = histcounts(results, 1:(length(awards) + 1));

第一个地方不明白可以自己手动推一下,第二个地方是因为用到了直方图 bin 计数函数,因为results里边全部是存放的等级,用这个函数就可以很快的统计出每个等级在results中出现的次数。
一次统计的结果如下:
在这里插入图片描述

3 问题

在这里插入图片描述

4 Matlab代码

clear
close all
clc

T1 = cputime;
%% 初始化参数
NP = 50;    % 种群数量(染色体数目,一个染色体就相当于是一个个体)
L = 20;     % 二进制位串长度
Pc = 0.8;   % 交叉概率
Pm = 0.05;  % 变异概率
G = 100;    % 最大遗传次数
Xs = 10;    % 搜索上限
Xx = 0;     % 搜索下限(这个是随自变量的取值范围确定的,我们已经知道了函数的取值范围)
f = randi([0,1],NP,L);  % 随机获得初始种群(种群里有NP个个体,每个个体的基因位数为L,用0,1模拟二进制)
trace = zeros(1,G); % 历代最优适应度
%% 遗传算法主体
for k = 1:G
    Fit = zeros(1,NP);  % 种群中每个个体的适应度
    x = zeros(1,NP);    % 存放二进制数对应的十进制数,我把它定义为虚表现型(注意这个并不是真正的解集,还需要做一个映射)

    %%% 将二进制解码为定义域内的十进制(让二进制和十进制一一对应起来)
    for i = 1:NP
        U = f(i,:); % (基因型)U存放的就是一个个体的基因(一串二进制位,这里是用01模拟的)
        m = 0;      % (伪表现型)这是U对应的十进制
        % m = bin2dec(char('0'+ U)); 可以用这句话直接实现进制的转换
        for j = 1:L
            m = U(j)*2^(j-1) + m;
        end
        % (实表现型)将十进制转换为对应的表现型(x)
        % 这段代码的实际含义是将通过随机0,1序列转换而来的十进制数,与定义域内的数一一对应起来,
        % 否则通过随机0,1序列转换而来的十进制数根本没有实际含义,无法和定义域里联系起来
        % 但是这个定义的法则是通过这个公式确定的,有什么具体其他规范吗?或者其他的定义法则
        x(i) = Xx + m*(Xs-Xx)/(2^L - 1);   % 将二进制对应的十进制数映射到定义域中(请记住这种映射的方法)
        Fit(i) = GetFit(x(i));  % 计算这个个体的适应度
    end
    maxFit = max(Fit);  % 找到最大的适应度值
    minFit = min(Fit);  % 找到最小的适应度值
    rr = find(Fit == max(Fit));  % 找到最大适应度值对应的个体编号
    % 最优个体的基因
    % 因为最大适应度值可能不止一个,可能有多个最大值,因此用rr(1)取第一个最大值对应的个体
    fBest = f(rr(1),:);   % 最优个体的基因型
    xBest = x(rr(1));     % 最优个体的实表现型
    Fit = (Fit-minFit)/(maxFit-minFit); % 将适应度做归一化处理(请记住这种归一化的方法)

    %%% 基于轮盘赌的复制操作
    sumFit = sum(Fit);
    fitValue = Fit./sumFit;         % 求每个个体的适应度值占总的适应度值的百分比
    fitvalue = cumsum(fitValue);    % 适应度值的累加和
    ms = sort(rand(NP,1));
    fiti = 1;   % 记录当前适应度的索引(在轮盘赌选择的过程中,fiti 用于追踪当前适应度的位置)
    newi = 1;   % 记录新个体的索引(轮盘赌选择的过程中,newi 用于确定新种群中的位置,即确定新个体的存放位置。)
    while newi <= NP
        if(ms(newi) < fitvalue(fiti))
            nf(newi,:) = f(fiti,:);
            newi = newi + 1;
        else
            fiti = fiti + 1;
        end
    end
    %%% 基于概率的交叉操作(不懂请画图理解)
    for i = 1:2:NP % i是奇数号染色体
        if rand < Pc
            q = randi([0,1],1,L); % 随机生成一个交换flag(为1的位置对应的基因型之间进行交换)
            for j = 1:L
                if q(j) == 1
                    % 交换等位基因
                    temp = nf(i+1,j);
                    nf(i+1,j) = nf(i,j);
                    nf(i,j) = temp;
                end
            end
        end
    end
    %%% 基于概率的变异操作
    i = 1;
    while i <= round(NP*Pm)
        h = randi([1,NP],1,1);   % 在种群中随机选一个染色体来变异
        for j = 1:round(L*Pm)
            g = randi([1,L],1,1);% 随机选取一个需要变异的基因数
            nf(h,g) = ~nf(h,g);  % 将染色体nf中第h个个体的第g个基因取反,就是变异了
        end
        i = i + 1;
    end
    f = nf; 
    f(1,:) = fBest;    % 保留最优个体在新种群中
    trace(k) = maxFit; % 历代最优适应度
end

T2 = cputime;
timeConsume = T2 -T1;
%% 适应度进化曲线
figure(Color=[1 1 1])
plot(trace,LineWidth=2,Color=[0.56 0 0.56]);
xlabel("迭代次数",FontName="黑体",FontWeight="bold",FontSize=15);
ylabel("目标函数值",FontName="黑体",FontWeight="bold",FontSize=15);
title("适应度进化曲线","CPU时间消耗: "+timeConsume + 's',FontName="黑体",FontWeight="bold",FontSize=12);

%% 做出原始图像
x = 0:0.01:10;
y = x + 10*sin(5*x) + 7*cos(4*x);
figure(Color=[1 1 1])
plot(x,y,lineWidth=2);
ylim([min(y)-1,max(y)+1]);
xlabel("x",FontName="Times new Roman"...
    ,FontAngle="italic",FontWeight="bold",FontSize=15);
ylabel("f(x)",FontName="Times new Roman"...
    ,FontAngle="italic",FontWeight="bold",FontSize=15);
title("f(x)=x+10sin(5x)+7cos(4x)",FontName="Times new Roman"...
    ,FontAngle="italic",FontWeight="bold",FontSize=15);
hold on
z = abs(y - max(trace));
x = x(z == min(z));
plot(x(1),max(trace),'r*');

%% 适应度函数
function result = GetFit(x)
    % 这里选择的适应度函数就是目标函数(实际上适应度函数要求为一个非负的函数)
    result = x + 10*sin(5*x) + 7*cos(4*x);
end

5 运行效果

在这里插入图片描述
在这里插入图片描述

6 总结

之前本科的时候也做过一些关于遗传算法的实际应用,但是很多是复用别人的代码,简单地修修改改,不过后边很长时间都没有再用了,导致很多知识已经忘记了,所以写算法还是要常加联系。上述代码可能还有许多错误和很多值得优化的地方,恳请各位老师留言,批评指教。

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

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

相关文章

C#与php自定义数据流传输

C#与php自定义数据流传输 介绍一、客户端与服务器数据传输流程图客户端发送数据给服务器&#xff1a;服务器返回数据给客户端&#xff1a; 二、自定义数据流C#版本数据流PHP版本数据流 三、数据传输测试1.在Unity中创建一个C#脚本NetWorkManager.cs2.服务器www目录创建StreamTe…

Docker 创建容器

1、创建MySQL5.7 拉取镜像&#xff1a;docker pull mysql:5.7创建容器&#xff1a;docker run -d --name mysql57001 -p 3306:3306 -v D:\DockerImage\QhData\MySql57:/var/lib/mysql -e MYSQL_ROOT_PASSWORD123456 mysql:5.7进入容器&#xff1a;docker exec -it mysql57001 …

检测如下MHA运行条件【踩坑记录】

【masterha_check_ssh --conf/etc/mha/app1.cnf&#xff1a;SSH免密登录】 【错误信息1】 [error][/usr/share/perl5/vendor_perl/MHA/SSHCheck.pm, ln111] SSH connection from root10.0.0.53(10.0.0.53:22) to root10.0.0.51(10.0.0.51:22) failed! 【错误反馈】就是服务器…

2024 软件测试面试题(800道)【附带答案】持续更新...

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

什么是数据分析思维

参考 一文学会如何做电商数据分析&#xff08;附运营分析指标框架&#xff09; 电子商务该如何做数据分析&#xff1f;如何数据分析入门&#xff08;从各项指标表象进入&#xff09; https://www.processon.com/outline/6589838c3129f1550cc69950 数据分析步骤 什么是数据分析…

HackTheBox - Medium - Linux - OnlyForYou

OnlyForYou OnlyForYou 是一台中等难度的 Linux 计算机&#xff0c;其特点是 Web 应用程序容易受到本地文件包含 &#xff08;LFI&#xff09; 的影响&#xff0c;该应用程序用于访问源代码&#xff0c;从而揭示盲目命令注入漏洞&#xff0c;从而导致目标系统上的 shell。该计…

k8s的二进制部署1

k8s的二进制部署&#xff1a;源码包部署 k8smaster01&#xff1a;192.168.176.61 kube-apiserver kube-controller-manager kube-scheduler etcd k8smaster01&#xff1a;192.168.176.62 kube-apiserver kube-controller-manager kube-scheduler node节点01&#xff1a;192.…

华清远见嵌入式学习——ARM——作业4

作业要求&#xff1a; 代码运行效果图&#xff1a; 代码&#xff1a; do_irq.c: #include "key_it.h" extern void printf(const char *fmt, ...); unsigned int i 0;//延时函数 void delay(int ms) {int i,j;for(i0;i<ms;i){for(j0;j<2000;j);} }void do_i…

VScode安装Remix.js开发环境

目录 1 Remix.js介绍 2 远程连接方法 3 安装remix环境 4 设置根路由 5 编译运行 6 自己的helloworld 7 总结 书接上回&#xff0c;我们已经完成了vue的基本开发环境配置&#xff0c;并成功跑了第一个vue程序。下面我们要尝试安装remix.js的开发环境。 1 Remix.js介绍 …

00-Git 应用

Git 应用 一、Git概述 1.1 什么是Git git 是一个代码协同管理工具&#xff0c;也称之为代码版本控制工具&#xff0c;代码版本控制或管理的工具用的最多的&#xff1a; svn、 git。 SVN 是采用的 同步机制&#xff0c;即本地的代码版本和服务器的版本保持一致&#xff08;提…

Java中实现百度浏览器搜索功能

要在Java中实现百度浏览器搜索功能&#xff0c;你可以使用Selenium WebDriver。Selenium是一个用于自动化浏览器的工具&#xff0c;WebDriver是Selenium的一个子项目&#xff0c;它提供了一套API&#xff0c;可以直接与浏览器交互。 依赖: <dependencies><dependency…

【http】HTTP/1.0、HTTP/1.1和HTTP/2.0

✨ 专栏介绍 在当今互联网时代&#xff0c;计算机网络已经成为了人们生活和工作中不可或缺的一部分。而要实现计算机之间的通信和数据传输&#xff0c;就需要依靠各种网络协议来进行规范和约束。无论是浏览网页、发送电子邮件还是进行在线交流&#xff0c;都离不开各种各样的网…

【PTA】L1-016 验证身份(C++)

题目链接 &#xff1a; 题目要求&#xff1a; 一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下&#xff1a; 首先对前17位数字加权求和&#xff0c;权重分配为&#xff1a;{7&#xff0c;9&#xff0c;10&#xff0c;5&#xff0…

手机无人直播:解放直播的新方式

现如今&#xff0c;随着科技的迅猛发展&#xff0c;手机已经成为我们生活中不可或缺的一部分。除了通讯、娱乐等功能外&#xff0c;手机还能够通过直播功能将我们的生活实时分享给他人。而针对传统的直播方式&#xff0c;使用手机进行无人直播成为了一种全新的选择。 手机无人…

H.264宏块(Macroblock)概念(运动估计、变换编码、环路滤波)

参考文章&#xff1a;音视频高手课系列5-h264编码基础(宏块原理) 参考文章&#xff1a;切片slice与宏块&#xff0c;运动矢量 文章目录 使用videoEye分析视频宏块示例H.264宏块概念1. 宏块的定义2. 运动估计3. 变换编码4. 环路滤波5. 注意&#xff1a;宏块的概念既适用于帧内编…

【halcon深度学习】dev_display_dl_data 移植到C# 上篇

效果展示 前言 在研究halcon深度学习的时候,会发现halcon的例程里面用到了大量的二次封装库函数。这些库函数内部也是由基础的算子组成。我们在halcon的开发环境里面用的很爽,但是一旦要在C#中使用,就会报错。 一开始,我想避开这个移植过程,直接使用halcon引擎(HDevEngi…

043、循环神经网络

之——RNN基础 杂谈 第一个对于序列模型的网络&#xff0c;RNN。 正文 1.潜变量自回归模型 潜变量总结过去的信息&#xff0c;再和当前信息一起结合出新的信息。 2.RNN 循环神经网络将观察作为x&#xff0c;与前层隐变量结合得到输出 其中Whh蕴含了整个模型的时序信息&#xf…

2024 年 11 款最佳 Android 数据恢复软件应用

Android 设备上的数据丢失可能是一种令人痛苦的经历&#xff0c;通常会导致不可替代的信息瞬间消失。 意外删除、系统崩溃或格式错误都可能发生&#xff0c;重要数据的丢失可能会扰乱日常工作并影响您的工作效率。 幸运的是&#xff0c;技术进步带来了多种恢复解决方案&…

代码编辑器,代码(JSON,js,Markdown,html,css,java,sql)格式化 fei-editor

效果展示 官方文档&#xff1a; https://ymf930.gitee.io/fei-editor/#/ npm 安装 npm i fei-editor -S # or yarn add fei-editor想要运行下面的示例&#xff0c;除此之外还要安装f-ui-one、brace 引入 在 main.js 中写入以下内容&#xff1a; import { createApp } fr…

Unity AssetBundle学习笔记

目录 基础介绍 动态资源加载 更新和添加内容 打包策略 资源分组 频繁更新的资源 资源压缩 Unload&#xff08;true&#xff09;和Unload&#xff08;false&#xff09; Unload(false) Unload(true) 确定何时卸载 引用计数 场景和状态管理 资源使用频率 内存预算…