模拟退火法、神经网络、遗传算法

最优化理论的经典算法

模拟退火法、神经网络、遗传算法是数学建模中常用的启发式算法,这里整合一下模版,并进行一些拓展,方便直接使用

原文:http://blog.csdn.net/qq_34861102/article/details/77806124

一些拓展:

基于模拟退火的遗传算法:
http://blog.csdn.net/qq_34861102/article/details/77899555

模拟退火法

  • 伪代码
/* * J(y):在状态y时的评价函数值 * Y(i):表示当前状态 * Y(i+1):表示新的状态 * r: 用于控制降温的快慢 * T: 系统的温度,系统初始应该要处于一个高温的状态 * T_min :温度的下限,若温度T达到T_min,则停止搜索 */
while( T > T_min )
{
  dE = J( Y(i+1) ) - J( Y(i) ) ; 

  if ( dE >=0 ) //表达移动后得到更优解,则总是接受移动
        Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动
  else
  {
// 函数exp( dE/T )的取值范围是(0,1) ,dE/T越大,则exp( dE/T )也
        if ( exp( dE/T ) > random( 0 , 1 ) )
        Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动
  }
  T = r * T ; //降温退火 ,0<r<1 。r越大,降温越慢;r越小,降温越快
  /*   * 若r过大,则搜索到全局最优解的可能会较高,但搜索的过程也就较长。若r过小,则搜索的过程会很快,但最终可能会达到一个局部最优值   */
  i ++ ;
}
  • 实际例子

    • 求解下列非线性规划最优解

       min f(x) = x(1)^2 + x(2)^2 + 8; s.t. x(1)^2 - x(2) >= 0; -x(1) - x(2)^2 + 2 = 0; x(1),x(2) >=0 
    • 实现代码

      %生成初始解 
      x2=1;  
      x1=2-x2^2;  
      tempx1 = x1;   
      bestx1 = x1;  
      tempx2 = x2;   
      bestx2 = x2;  
      tempans = inf;  
      bestans = inf;  
      figure
      rand('state',sum(clock)); %初始化随机数发生器 
      t=90; %初始温度 
      tf=89.9; %结束温度 
      a = 0.99; %温度下降比例 
      
      while t>=tf%(7)结束条件 
          for r=1:1000 %退火次数 
      
              %产生随机扰动(3)新解的产生 
              x2=x2+rand*0.2;  
              x1=2-x2^2;  
      
              %检查是否满足约束 
              if x1^2-x2>=0 && -x1-x2^2+2==0 && x1>=0 &&x2>=0  
              else  
                  x2=rand*2;  
                  x1=2-x2^2;  
                  continue;  
              end  
      
              %退火过程 
              E_new=x1^2+x2^2+8;%(2)目标函数 
              if E_new<tempans%(5)接受准则 
                      tempans=E_new;  
                      tempx1=x1;  
                      tempx2=x2;  
                      if E_new<bestans  
                          %把冷却过程中最好的解保存下来 
                          bestans=E_new;  
                          bestx1=x1;  
                          bestx2=x2;  
                      end  
              else  
                      if rand<exp(-(E_new-tempans)/t)%(4)代价函数差 
                          tempans=E_new;  
                          tempx1=x1;  
                          tempx2=x2;  
                      else  
                          x2=tempx2;  
                          x1=tempx1;  
                      end  
              end  
              plot(r,bestans,'.')  
              hold on  
          end  
          t=t*a;%(6)降温 
      end  
      
      disp('最优解为:')  
      disp(bestx1)  
      disp(bestx1)  
      disp('目标表达式的最小值等于:')  
      disp(bestans)  

神经网络

这里就介绍一下常用的神经网络

  • BP网络

    %输入变量P和目标变量T
    P = -1:0.1:1;
    T = [-0.9602 -0.5770 -0.0729 0.3771 0.6405 0.6600 0.4609 0.1336 -0.2013 -0.4344 -0.5000 -0.3930 -0.1647 0.0988 0.3072 0.3960 0.3449 0.1816 -0.0312 -0.2189 -0.3201];
    %网络设计
    s = 3:8;
    res = 1:6;
    for i = 1:6;
    %net = newff(minmax(P),[s(i),1],{'tansig','logsig'},'traingdx');
    net = newff(P,T,s(i),{'tansig','logsig'},'traingdx');
    net.trainParam.epochs = 2000;
    net.trainParam.goal = 0.001;
    net = train(net,P,T);
    y = sim(net,P);
    error = y - T;
    %向量每个元素分别平方后求和再开方
    res(i) = norm(error)
    end
    %这是一个选择最佳隐层神经元个数的方法
    %自己选择不同的训练算法
    %输入变量P和目标变量T
    P = -1:0.1:1;
    T = [-0.9602 -0.5770 -0.0729 0.3771 0.6405 0.6600 0.4609 0.1336 -0.2013 -0.4344 -0.5000 -0.3930 -0.1647 0.0988 0.3072 0.3960 0.3449 0.1816 -0.0312 -0.2189 -0.3201];
    net = newff(P,T,8,{'tansig','logsig'},'traingdx');
    net.trainParam.epochs = 2000;
    net.trainParam.goal = 0.001;
    net = train(net,P,T);
    y = sim(net,P);
    plot(P,T,'r+');
    hold on
    plot(P,y,'.');
    plot(1:21,y-T);
    %三个图像分开验证
  • 感知器网络

    • 单层感知器网络

      %样本输入向量
      lP=[-0.4 -0.6 0.7; 0.8 0 0.1];
      %目标向量
      T=[1 1 0];
      %新建一个感知器网络
      %newp -- 第一个参数是R组输入向量的最大值和最小值组成 第二个参数是神经元的个数 第三个参数可选,传递函数 第四个参数可选,学习函数
      net=newp([-1 1;-1 1],1);
      %返回画线的句柄,下一次绘制分类线时将旧的删除
      handle=plotpc(net.iw{1},net.b{1});
      %设置训练次数最大为200
      net.trainParam.epochs = 200;
      net=train(net,lP,T);
      %给定的输入向量
      Q=[0.6 0.9 -0.1; -0.1 -0.5 0.5];
      %网络仿真函数
      Y=sim(net,Q);
      %控制窗口的数量
      figure;
      %绘制分类线
      plotpv(Q,Y);
      handle=plotpc(net.iw{1},net.b{1},handle)
      grid
    • 多层感知器网络

      net = network
      %网络的结构属性 %定义了网络的输入向量数,设置为自然数,不是输入层的神经元的个数,是输入源的数目
      net.numInputs = 1;
      %定义了网络的层数
      net.numLayers = 2;
      %定义各个网络层是否具有阈值向量,其值为Nl*1布尔型向量(0或1),Nl为网络层数(net.Layers)。 %可以通过访问net.biasConnect{i}的值,查看第i个网络层是否具有阈值向量
      net.biasConnect = [1;1];
      %定义各网络层是否具有来自个输入向量的连接权,其值为Nl*Ni布尔型向量(0或1),Nl为网络层数(net.numLayers),Ni为网络输入向量数(net.numInputs)。 %可以通过访问net.inputConnect(i,j)的值,来查看第i个网络是否具有来自第j个输入向量的连接权
      net.inputConnect = [1;0];
      %定义一个网络层是否具有来自另外一个网络层的连接权,其值为Nl*Nl的布尔型向量(0或1),Nl为网络层数(net.numLayers)。 %可以通过访问net.layerConnect(i,j)的值,来查看第i个网络层是否具有来自第j个网络层的连接权。
      net.layerConnect = [0 0;1 0];
      %定义各网络层是否作为输出层,其值为1*Nl的布尔型向量(0或1),Nl为网络层数(net.numLayers)。 %可以通过访问net.outputConnect(i)的值来查看第i个网络层是否作为输出层。
      net.outputConnect = [0 1];
      
      
      %各层的属性
      net.inputs{1}.range = [0 1;0 1];
      net.layers{1}.size = 2;
      net.layers{1}.transferFcn = 'hardlim';
      net.layers{1}.initFcn = 'initnw';
      
      net.layers{2}.size = 1;
      net.layers{2}.transferFcn = 'hardlim';
      net.layers{2}.initFcn = 'initnw';
      
      %网络的整体属性
      net.adaptFcn = 'adaptwb';
      net.performFcn = 'mse';
      net.trainFcn= 'trainlm';
      net.initFcn  = 'initlay';
      
      %对网络进行初始化
      net = init(net);
      %设置训练样本P和T
      P = [0 0;0 1;1 0;1 1]';
      T = [0 1 1 0];
      net.trainParam.epochs = 500;
      net = train(net,P,T);
      
      y = sim(net,P)
  • 线性神经网络

    P = [1 1.5 3.0 -1.2];
    T = [0.5 1.1 3.0 -1.0];
    plot(P,T,'+');
    axis([-1.5 3.5 -1.5 3.5]);
    xlabel('training vector P');
    ylabel('target vaector T');
    %创建网络并开始训练
    net = newlin(minmax(P),1,0,0.01);
    net = init(net);
    net.trainParam.epochs = 500;
    net.trainParam.goal = 0.0001;
    net = train(net,P,T);
    y = sim(net,P);
    plot(P,y);
    hold on 
    plot(P,T,'r+');
    
    %很好逼近了P和T的线性关系

遗传算法

以上面模拟退火中非线性规划最优解的模型为例

  • 主函数

    clear
    firstbestfit = 0;
    popsize=20; %群体大小
    chromlength=1; %字符串长度(个体长度)
    pc = 0.6; %交叉概率
    pm = 0.001; %变异概率
    pop = initpop(popsize,chromlength); %随机产生初始群体
    for i=1:20000 %20000为迭代次数
        [objvalue] = calobjvalue(pop); %计算目标函数
        fitvalue = calfitvalue(objvalue); %计算群体中每个个体的适应度
        [newpop] = selection(pop,fitvalue); %复制
        [newpop] = crossover(newpop,pc); %交叉
        [newpop] = mutation(newpop,pm); %变异 
        pop = newpop; 
        [bestindividual,bestfit]=best(pop,fitvalue); %求出群体中适应度值最大的个体及其适应值
        %保留最好的个体
        if bestfit > firstbestfit
            firstbestfit = bestfit;
            aa = bestindividual;
            zz = 1/bestfit + 8;
        end
    end
  • initpop初始函数

    对于初始化而言,尽量要选择解质量较好的初始化群体

    function pop=initpop(popsize,chromlength)
    pop = zeros(popsize,chromlength+1);
    for i = 1:popsize
        pop(i,1) = rand;
        pop(i,2) = 2-pop(i,1)^2;
    end
    end
  • calobjvalue计算目标函数

    根据自己实际例子中定义目标函数

    function [objvalue]=calobjvalue(pop)
    objvalue = zeros(size(pop,1),1);
    for i = 1:size(pop,1)
        x1 = pop(i,2);
        x2 = pop(i,1);
    if x1^2-x2>=0 && -x1-x2^2+2==0 && x1>=0 &&x2>=0
            objvalue(i) = x1^2+x2^2+8;
        else
            objvalue(i) = 1000;
    end
    end
  • calfitvalue计算群体中每个个体的适应度

    对于目标函数可能在不同情况之下和适应度的关系存在其余如反比例的关系

    function fitvalue=calfitvalue(objvalue)
    fitvalue = zeros(size(objvalue,1),1);
    for i = 1:size(objvalue,1)
        fitvalue(i) = 1/(objvalue(i)-8);
    end
    end
  • selection复制过程

    染色体复制的过程

    function [newpop]=selection(pop,fitvalue)
    totalfit=sum(fitvalue); %求适应值之和
    fitvalue=fitvalue/totalfit; %单个个体被选择的概率
    fitvalue=cumsum(fitvalue); %如 fitvalue=[1 2 3 4],则 cumsum(fitvalue)=[1 3 6 10]
    [px,py]=size(pop);
    ms=sort(rand(px,1)); %从小到大排列
    fitin=1;
    newin=1;
    while newin<=px
    if(ms(newin))<fitvalue(fitin)
    newpop(newin,:)=pop(fitin,:);
    newin=newin+1;
    else
    fitin=fitin+1;
    end
    end
  • crossover交叉过程

    染色体交叉的过程

    %交叉
    function [newpop]=crossover(pop,pc)
    [px,py]=size(pop);
    newpop=ones(size(pop));
    for i=1:2:px-1
    if(rand<pc)
    cpoint=round(rand*py);
    newpop(i,:)=[pop(i,1:cpoint),pop(i+1,cpoint+1:py)];
    newpop(i+1,:)=[pop(i+1,1:cpoint),pop(i,cpoint+1:py)];
    else
    newpop(i,:)=pop(i);
    newpop(i+1,:)=pop(i+1);
    end
    end
  • mutation变异过程

    染色体变异的过程

    %变异
    function [newpop1]=mutation(pop,pm)
    [px,py]=size(pop);
    for i=1:px  
    if(rand<pm)
        newpop1(i,1)=sqrt(2) - pop(i,1);
        newpop1(i,2)=2-newpop1(i,1)^2;
    else
        newpop1(i,:)=pop(i,:);
    end
    end
  • best寻找群体中最优个体

    公告牌用于保存迭代过程中的最优解

    %求出群体中适应值最大的值
    function [bestindividual,bestfit]=best(pop,fitvalue)
    [px,py]=size(pop);
    bestindividual=pop(1,:);
    bestfit=fitvalue(1);
    for i=2:px
    if fitvalue(i)>bestfit
    bestindividual=pop(i,:);
    bestfit=fitvalue(i);
    end
    end
    原文作者:遗传算法
    原文地址: https://blog.csdn.net/qq_34861102/article/details/77806124
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞