基于遗传算法的多参数优化问题

一、前言

遗传算法是一种群优化算法,我在各个网站上找到的遗传算法相关的文章大多是对一个参数的优化,本文将使用遗传算法解决多个参数的优化问题(以两个参数为例),本文以应用为主,不会去详细讲解原理,因为CSDN、知乎上已经有许多讲的非常好的文章了。

二、优化问题

求解多峰函数Ackley函数的全局最小
f ( x , y ) = − 20 e − 0.2 0.5 ( x 2 + y 2 ) − e 0.5 ( cos ⁡ 2 π x + cos ⁡ 2 π y ) + e + 20 − 5 ≤ x , y ≤ 5 f\left( x,y \right) =-20\text{e}^{-0.2\sqrt{0.5\left( x^2+y^2 \right)}}-\text{e}^{0.5\left( \cos 2\pi x+\cos 2\pi y \right)}+\text{e}+20\\ -5 \leq x,y \leq 5 f(x,y)=20e0.20.5(x2+y2) e0.5(cos2πx+cos2πy)+e+205x,y5

函数图像:
在这里插入图片描述

易知,函数的全局极小值为:
f ( 0 , 0 ) = 0 f(0,0)=0 f(0,0)=0

三、编程思路

  1. 首先要明确使用遗传算法进行优化时的几个要素:

    (1)待优化参数个数。在这个问题中,自变量 x 、 y x、y xy就是待优化参数。

    (2)参数的取值范围。

    (3)目标函数。即优化参数与优化目标之间的函数关系。

    (4)适应度函数。这里需要区分一下适应度函数和目标函数的区别,如果优化目的是求目标函数的最大值,则适应度函数和目标函数可以等同看待;如果是求最小值,则需要对目标函数进行转换,最常见的方式是对目标函数取反或者取倒数。因为在进行优化时,我们设计的算法往往是求最大值的。

  2. 求二元函数的极小值问题可以理解成含有两个参数的优化问题,目标函数是 f ( x , y ) f(x,y) f(x,y)。优化参数的取值范围为-5到5。

  3. 编码: 使用二进制编码。设精度为0.001,即将优化参数、优化结果值保留到小数点后三位。因此二进制的编码需要编码的数目为:
    M = [ 5 − ( − 5 ) ] ⋅ 1 0.001 = 10000 M=[5-(-5)]· \frac{1}{0.001}=10000 M=[5(5)]0.0011=10000
    由于
    2 13 ≤ M ≤ 2 14 2^{13} \leq M \leq 2^{14} 213M214
    因此,对于每一个优化参数,取编码长度为14,则编码精度为
    L = 10000 2 14 L=\frac{10000}{2^{14}} L=21410000

  4. 上面的每一个14个二进制数组成的一个编码就是一个不完整的染色体,为什么说是不完整呢?因为对于多参数优化,一个完整的染色体应该是将各个不完整的编码串联到一起,组合成一个完整的编码,才能成为一个完整的染色体。所以在这个题中,一个染色体应该包含28个二进制数,在进行解码时将前十四个、后十四个分别解码即可。

  5. 适应度函数: 由于原函数是求极小值,所以将目标函数取倒数作为适应度函数,适应度函数最大时,目标函数取得最小值。

  6. 其他步骤不再详细讲解。

四、注意

  1. 本题中 x 、 y x、y xy的取值范围相同,所以解码时划分染色体是均匀划分的,如果取值范围不同,代码需要稍作修改,这个有时间了再做,想尝试的话可以在源码的第四部分中对变量DevidePoint入手。
  2. 如果你有其他方法非常非常欢迎交流,因为我总觉得这个方法对于参数特别多的情况不太友好。
  3. 如果发现本文有错误的地方欢迎交流指正。
  4. 本文内容包括代码在内均为原创,如果转载需要标明出处。
  5. 如果对代码内容有任何疑问可以私信或者留言,看到就会第一时间回复。
  6. 祝在看的你学业有成!!!

五、源码

  1. 绘图
   clear;clc;close all;
   x = -5:0.01:5;
   y = -5:0.01:5;
   [X,Y] = meshgrid(x,y);
   f = -20*exp(-0.2*sqrt(0.5*(X.^2+Y.^2)))-...
           exp(0.5*(cos(2*pi*X)+cos(2*pi*Y)))+exp(1)+20;
   mesh(X,Y,f);
   xlabel('x');
   ylabel('y');
   zlabel('z');
   title('f(x,y)函数图像')
   hold on
  1. 主函数
   clear;clc;close all;
   %%%%%%%%% 运行前设定 %%%%%%%%%
   UnknowNum = 2;  % 待优化参数数量
   popsize = 20;   % 种群大小
   N = 1000;      % 最大迭代次数(遗传代数)
   CrossRate = 0.6;     % 交叉概率
   MutateRate = 0.01;   % 变异概率
   LowBound = -5;  % 待优化参数下界
   UpBound = 5;  % 待优化参数上界
   Precision = 0.001;  % 优化精度,保留到小数点后三位
   Individual = cell(1,N); %最优个体、最优适应度值计算
   BestFit = zeros(1,N);
   %%%%%%%%%%%%%%%%%%% 初始化处理 %%%%%%%%%%%%%%%%%%%
   ChromLen = CodeLength(LowBound,UpBound,Precision);% 一个参数对应的染色体长
   ChromTotal = UnknowNum*ChromLen;  % 染色体总长
   Population = round(rand(popsize,ChromTotal));   % 种群初始化
   IntialFitVal = FitFunction(Population,UnknowNum,LowBound,UpBound);    % 初始适应度计算
   %%%%%%%%%%%%%%%%%%% 遗传 %%%%%%%%%%%%%%%%%%%
   for i = 1:N
       if i==1
           FitVal = IntialFitVal;
       else
           Population = MutatePop;
       end
       SelectPop = Selection(Population,FitVal);
       CrossPop = CrossOver(SelectPop,CrossRate,UnknowNum);
       MutatePop = Mulation(CrossPop,MutateRate,UnknowNum);
       FitVal = FitFunction(MutatePop,UnknowNum,LowBound,UpBound);    % 新一代适应度
       [BestFit(i),Index] = max(FitVal);
       value = 1/BestFit(i);
       Individual0 = MutatePop(Index,:);
       Individual1 = BinToDec(Individual0,UnknowNum,LowBound,UpBound);
       Individual{i} = Individual1;
   end
   %%%%%%%%%%%%%%%%%%% 对适应度值处理 %%%%%%%%%%%%%%%%%%%
   [MaxFit,Index] = max(BestFit);
   MinVal = 1/MaxFit;
   BestIndividual = cell2mat(Individual(Index));
   disp('函数极小值为:')
   disp(MinVal);
   disp('x、y的取值分别为:')
   disp(BestIndividual);
   % 验证
   f = -20*exp(-0.2*sqrt(0.5*(BestIndividual(:,1).^2+BestIndividual(:,2).^2)))-...
           exp(0.5*(cos(2*pi*BestIndividual(:,1))+cos(2*pi*BestIndividual(:,2))))+exp(1)+20;
  1. 编码长度计算
   % 编码长度即单个染色体长度
   function Len = CodeLength(lb,ub,p)
       % lb:参数下界
       % ub:参数上界
       % p:参数精度
       Scope = (ub-lb)/p;   % 对取值范围的表示
       Len = log2(Scope);
       Len = ceil(Len);    % 向上取整函数
   end
  1. 二进制转为十进制(解码)
   % Population: 种群
   % UnknowNum: 优化参数数量
   function Val = BinToDec(Population,UnknowNum,lb,ub)
       [m,n] = size(Population);
       DevidePoint = n/UnknowNum;	% 分割点:分割不同参数
       NewPop = zeros(m,UnknowNum);
       for j=1:UnknowNum
           for i=1+(j-1)*DevidePoint:j*DevidePoint
           	Population(:,i) = Population(:,i)*2^(i-1-(j-1)*DevidePoint);
           end
           NewPop(:,j) = sum(Population(:,1+(j-1)*DevidePoint:j*DevidePoint),2);  % 解码为十进制
       end
       deta = (ub-lb)/(2^(n/UnknowNum)-1);
       %%%%%%%%%%%%%%%%%%% 根据自变量范围修改 %%%%%%%%%%%%%%%%%%%
       NewPop = NewPop*deta-5;   % 解码为十进制
       Val = NewPop;
   end
  1. 适应度函数
   % 若是优化求最大值,返回值即为目标函数值;
   % 若是优化求最小值,返回值为目标函数值取倒数或取反
   % Population:初始化后的种群,本质是二进制矩阵
   % UnknowNum:待优化参数数量
   function FitVal = FitFunction(Population,UnknowNum,lb,ub)
       NewPop = BinToDec(Population,UnknowNum,lb,ub);
       f = -20*exp(-0.2*sqrt(0.5*(NewPop(:,1).^2+NewPop(:,2).^2)))-...
           exp(0.5*(cos(2*pi*NewPop(:,1))+cos(2*pi*NewPop(:,2))))+exp(1)+20;
       FitVal = 1./f;
   end
  1. 选择
function NewPop = Selection(Population,FitVal)
    [m,n] = size(Population);
    NewPop = zeros(m,n);    % 初始化新种群
    FitTotal = sum(FitVal);
    SelectedP = FitVal/FitTotal;    % 单个个体被选中的概率
    SelectedP = cumsum(SelectedP);  % 概率求和排序
    RandP = sort(rand(m,1));  % 随机概率排序,轮盘赌法
    fitIndex = 1;
    newIndex = 1;
    while newIndex <= m
        if RandP(newIndex)<SelectedP(fitIndex)
            NewPop(newIndex,:) = Population(fitIndex,:);
            newIndex = newIndex+1;
        else
            fitIndex=fitIndex+1;
        end
    end
end
  1. 交叉
   % 交叉
   % 生成随机概率,小于交叉概率时进行交叉,相邻两个个体交叉
   % Population: 种群
   % CrossRate: 交叉概率
   function Newpop = CrossOver(Population,CrossRate,UnknowNum)
       [m,n] = size(Population);
       Newpop = zeros(m,n);
       DevidePoint = n/UnknowNum;
       for j = 1:UnknowNum
           StartPoint = (j-1)*DevidePoint+1;
           EndPoint = j*DevidePoint;
           for i = 1:2:m-1
               P = rand;   
               if P<CrossRate
                   CrossPoint = StartPoint+round(rand*(DevidePoint-1)); % 交叉点
                   Newpop(i,StartPoint:EndPoint) = [Population(i,StartPoint:CrossPoint),...
                                                    Population(i+1,CrossPoint+1:EndPoint)];
                   Newpop(i+1,StartPoint:EndPoint) = [Population(i+1,StartPoint:CrossPoint),...
                                                      Population(i,CrossPoint+1:EndPoint)];
               else
                   Newpop(i,StartPoint:EndPoint) = Population(i,StartPoint:EndPoint);
                   Newpop(i+1,StartPoint:EndPoint) = Population(i+1,StartPoint:EndPoint);
               end
           end
       end
   end
  1. 变异
   % 变异
   % 将其中一个某一个染色位取反
   % Population: 种群
   % CrossRate: 交叉概率
   function NewPop = Mulation(Population,MutateRate,UnknowNum)
       [m,n] = size(Population);
       NewPop = zeros(m,n);
       DevidePoint = n/UnknowNum;
       for j = 1:UnknowNum
           StartPoint = (j-1)*DevidePoint+1;
           EndPoint = j*DevidePoint;
           for i = 1:m
               P = rand;
               if P<MutateRate
                   MPoint = StartPoint+round(rand*(DevidePoint-1));    % 变异点
                   NewPop(i,StartPoint:EndPoint) = Population(i,StartPoint:EndPoint);
                   NewPop(i,MPoint) = ~NewPop(i,MPoint);
               else
                   NewPop(i,StartPoint:EndPoint) = Population(i,StartPoint:EndPoint);
               end
           end
       end
   end
遗传算法是一种基于进化论的优化算法,常用于解决多参数优化问题。下面是在 MATLAB 中实现遗传算法的多参数优化的步骤: 1. 确定优化问题的目标函数参数范围。目标函数是需要优化函数参数范围是指参数的取值范围。 2. 初始化种群。根据参数范围,随机生成一定数量的个体作为初始种群。 3. 评估个体适应度。将每个个体代入目标函数中计算适应度。 4. 选择操作。选择适应度高的个体作为下一代种群的父母。 5. 交叉操作。将父母个体的某些基因相互交换,生成新的个体。 6. 变异操作。在新生成的个体中,随机改变某些基因的值。 7. 评估新个体适应度。 8. 选择新一代种群。将新生成的个体与上一代种群进行竞争,选取适应度高的个体作为下一代种群。 9. 判断是否满足停止条件。如果满足停止条件,则返回最优解;否则,返回步骤 4。 以下是一个简单的 MATLAB 代码示例: ```matlab % 目标函数 fun = @(x)[x(1)^2+x(2)^2-1, (x(1)-1)^2+x(2)^2-1]; % 参数范围 lb = [-2,-2]; ub = [2,2]; % 种群数量 popSize = 50; % 迭代次数 maxGen = 100; % 交叉率 crossRate = 0.9; % 变异率 mutationRate = 0.1; % 初始化种群 pop = rand(popSize,2).*(ub-lb)+lb; % 迭代 for i = 1:maxGen % 评估适应度 fitness = zeros(popSize,2); for j = 1:popSize fitness(j,:) = fun(pop(j,:)); end % 选择操作 [~,index] = sort(fitness(:,1)); parents = pop(index(1:popSize/2),:); % 交叉操作 offsprings = zeros(popSize/2,2); for j = 1:popSize/2 if rand < crossRate parent1 = parents(randi(popSize/2),:); parent2 = parents(randi(popSize/2),:); offsprings(j,:) = [parent1(1),parent2(2)]; else offsprings(j,:) = parents(randi(popSize/2),:); end end % 变异操作 for j = 1:popSize/2 if rand < mutationRate offsprings(j,:) = rand(1,2).*(ub-lb)+lb; end end % 合并新一代种群 pop = [parents;offsprings]; end % 返回最优解 [~,index] = min(fitness(:,1)); x = pop(index,:); ``` 上述代码用遗传算法优化了一个有两个变量的目标函数,该目标函数的最优解是在单位圆和以 (1,1) 为中心的半径为 1 的圆上。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值