老饼讲解-神经网络 机器学习 神经网络 深度学习
启发式寻解

【代码】模拟退火-求解函数最小值问题

作者 : 老饼 发表日期 : 2023-03-30 06:04:15 更新日期 : 2023-11-11 13:27:23
本站原创文章,转载请说明来自《老饼讲解-BP神经网络》www.bbbdata.com



本节展示一个使用模拟退火求解函数最小值的问题的代码示例,

通过本文可以更具体地了解模拟退火中的用途以及实现方式




  01. 模拟退火求解函数最小值 



本节展示如何使用模拟退火算法来解决函数最小值问题



  问题  


求 为何值时,
 取得最小值。
( 易知道,y的最小值在处取得,为0.)



    代码实现    


用模拟退火解决该问题时,主要需要确定以下两点:
1.能量函数是什么:在这里我们将目标函数作为能量函数就可以 
2.邻域中获得新解的方式:这里我们在解的邻域随机选择就可以      
下面是具体的实现代码
%------代码说明:展示模拟退火算法求解函数极小值问题 -----------------
% 目标函数为:y = (x1-2)^2+(x2-3)^2,求解x1,x2取何值时y最小
% 来自《老饼讲解神经网络》www.bbbdata.com ,matlab版本:2018a   
%-------------------------------------------------------------------%
setdemorandstream(88);                          % 老饼为了每次运行的结果一致,在此指定随机种子,实际中可以去掉
%变量初始化                                     
x     = [0,0];                                  % 初始化x 
E     = calE(x);                                % 初始化能量
teamp = 100;                                    % 设置初始温度

% -------温度初始化可用此方法(取N次邻域能量差均值的10倍)--------
try_cn = 20;                                    % 尝试20次
En   = zeros(1,try_cn);                         % 初始化邻域能量
for i = 1:try_cn                                
    new_x = x+ 0.1*(rand(size(x))-0.5);         % 在邻域中随机取一个解作为新解
    En(i)= calE(new_x);                         % 记录本次邻域解的能量
end                                             
teamp = mean(abs(En-E))*10 ;                    % 初始化温度


% -------------外循环------------
for t =1:10000
    minE = E;                                   % 初始化本次温度下的最小能量为当前能量
    maxE = E;                                   % 初始化本次温度下的最大能量为当前能量
    % --------内循环-------------
    for i=1:100
        new_x = x+ 0.05*(rand(size(x))-0.5);    % 在邻域中随机取一个解作为新解
        new_E = calE(new_x);                    % 计算新解的能量
        % 按概率接受新解
        if(exp((E-new_E)/teamp)>rand())         % 如果接受新解
            x = new_x;                          % 更新解
            E = new_E;                          % 更新当前能量
            minE = min(E,minE);                 % 更新本次温度下的最小能量
            maxE = max(E,maxE);                 % 更新本次温度下的最大能量
        end
    end
    disp(['第',num2str(t),'轮:x=[',num2str(x),'],E=',num2str(E),',teamp:',num2str(teamp)])
    % -----------降温,并检查是否退出循环------------    
    teamp = teamp*0.5;
    if( (maxE-minE)/maxE<0.01 )                 % 如果最大最小能量没什么区别
        break                                   % 则终止迭代
    end
end

%定义能量计算函数(目标函数)
function y = calE(x)
    y = (x(1)-2).^2+(x(2)-3).^2;
end



   代码运行结果    


运行结果如下:
 
最终的解为x = [2.004,2.9999],与我们预期的[2,3]的差异极小
可见,模拟退火算法已经取得了较好的效果











 End 







联系老饼