老饼讲解:一步一步上手学习
好了,上节我们已经用模拟退火来优化TSP问题了,这节我们来看看模拟退火怎么用来优化函数。
好了,就让我们开始玩玩模拟退火,看它怎么优化函数吧。
作为学习我们就以下面的简单函数来作为问题:
求 为何值时, 取得最小值。
容易知道,y的最小值在处取得最小值0,下面我们使用模拟退火算法来进行求解,看看它能不能找到这个最优值。
用模拟退火解决该问题时,主要需要确定以下两点:
1. 能量函数是什么
在这里我们将目标函数作为能量函数就可以
2. 邻域中获得新解的方式
这里我们在解的邻域随机选择就可以
使用模拟退火解决问题时,都需要确定以上两点,不同的方案就会有不同的结果,所以模拟退火是一种半开放式的算法,需要自己定义能量函数和新解的获得方式。
好了,就按上面的方案,用模拟退火算法来优化目标函数,闲话少说,直接上代码,如下:
% 本代码展示模拟退火算法求解函数极小值问题,目标函数为:y = (x1-2)^2+(x2-3)^2
% 本代码来自《老饼讲解神经网络》www.bbblearn.com ,matlab版本:2018a
setdemorandstream(888); % 为方便复现结果,设定随机种子
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 % 迭代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
fprintf('第%d轮:x=[%.4f,%.4f],E=%.5f,teamp:%.5f\n',t,x(1),x(2),E,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]的差异极小,可见,模拟退火算法已经取得了较好的效果。
模拟退火用于函数优化是很简单的,在获取新解时,只需随便在领域取一个值就行了,实现起来非常方便!而且即使是不同的目标函数,也可以换汤不换药,照抄过去就行了,这就是为什么我最喜欢这个算法了,简单有效易实现。
评论