一、概述
模拟退火算法是一种通用的优化算法,理论上算法具有概率的全局优化性能,目前已在工程中得到了广泛应用,诸如机器学习、神经网络、信号处理等领域。
二、算法原理
模拟退火算法的思想借鉴于固体的退火原理,当固体的温度很高的时候,内能比较大,固体的内部粒子处于快速无序运动,当温度慢慢降低的过程中,固体的内能减小,粒子的慢慢趋于有序,最终,当固体处于常温时,内能达到最小,此时,粒子最为稳定。模拟退火算法便是基于这样的原理设计而成。
模拟退火算法从某一高温出发,在高温状态下计算初始解,然后以预设的邻域函数产生一个扰动量,从而得到新的状态,即模拟粒子的无序运动,比较新旧状态下的能量,即目标函数的解。如果新状态的能量小于旧状态,则状态发生转化;如果新状态的能量大于旧状态,则以一定的概率准则发生转化。当状态稳定后,便可以看作达到了当前状态的最优解,便可以开始降温,在下一个温度继续迭代,最终达到低温的稳定状态,便得到了模拟退火算法产生的结果。
根据以上描述,可以得出模拟退火算法的计算步骤如下:
- 初始化: 初始温度 T T T (充分大),温度下限 T min T_{\min } Tmin (充分小),初始解状态 x x x (是算法迭代的起点),每个 T T T 值的迭代 次数 L L L;
- 对 l = 1 , 2 , … , L l=1,2, \ldots, L l=1,2,…,L 做第 3 至第 6 步;
- 产生新解 x new. x new = x + Δ x ; Δ x x_{\text {new. }} x_{\text {new }}=x+\Delta x ; \Delta x xnew. xnew =x+Δx;Δx 为 [ d min , d max ] \left[d_{\min }, d_{\max }\right] [dmin,dmax] 之间的随机数;
- 利计算增量 Δ f = f ( x n e w ) − f ( x ) \Delta f=f\left(x_{n e w}\right)-f(x) Δf=f(xnew)−f(x) ,其中 f ( x ) f(x) f(x) 为优化目标;
- 若 Δ f < 0 \Delta f<0 Δf<0 (若寻找最大值, Δ f > 0 \Delta f>0 Δf>0 ) 则接受 x n e w x_{n e w} xnew 作为新的当前解,否则以概率 exp ( − Δ f / ( k T ) ) \exp (-\Delta f /(k T)) exp(−Δf/(kT)) 接受 x n e w x_{n e w} xnew 作为新的 当前解;
- 如果满足终止条件则输出当前解作为最优解,结束程序。(终止条件通常取为连续若干个新解都没有被接受时终止算 法;
- T T T 逐渐减少,且 T > T min T>T_{\min } T>Tmin ,然后转第 2步。
三、python实现
3.1 构建目标函数
import numpy as np
import matplotlib.pyplot as plt
# 构建目标函数
def aimFunc(x):
y = 11 * np.sin(x) + 7*np.cos(5*x)
return y
# 展示目标函数在待求区间的曲线
x = np.arange(-3, 3, 0.01)
y = aimFunc(x)
plt.plot(x, y)
plt.show()
3.2 算法实现
# 构建新位置
def new_x(x, T, x_l, x_h):
# 计算新的位置
_x_new = x + np.random.uniform(-1, 1) * T
# 若新位置超出上、下限,对位置进行重新调整
if(_x_new < x_l):
_x_new = x - np.random.uniform(0, 1)*(x-x_l)
if(_x_new > x_h):
_x_new = x + np.random.uniform(0, 1)*(x_h-x)
return _x_new
# 定义x的范围
x_l = -3
x_h = 3
# 定义初始温度
T = 1000
# 定义内循环次数
N = 20
# 定义初始位置
_x = np.random.uniform(low=x_l, high=x_h)
_y = aimFunc(_x)
# 定义记录仪
_x_track = []
_y_track = []
while T >= 0.001:
for i in range(N):
# 获取新的位置
_x_new = new_x(_x, T, x_l, x_h)
# 计算新位置对应的函数值
_y_new = aimFunc(_x_new)
# 判断是否接受新的位置
flag_1 = _y_new < _y
flag_2 = np.exp(-(_y_new-_y)/T) > np.random.uniform()
if(flag_1 | flag_2):
_x = _x_new
_y = _y_new
_x_track.append(_x)
_y_track.append(_y)
# 更新温度
T = T * 0.8
# 展示计算结果
print(_x)
print(_y)
plt.plot(_x_track)
plt.show()
plt.plot(_y_track)
plt.show()
plt.plot(x, y)
plt.scatter(_x, _y, c='r')
plt.show()
四、Tips
模拟退火算法存在以下三个调参问题:
- 温度T的初始值设置问题
温度T的初始值设置是影响模拟退火算法全局搜索性能的重要因素之一、初始温度高,则搜索到全局最优解的可能性大,但因此要花费大量的计算时间;反之,则可节约计算时间,但全局搜索性能可能受到影响。 - 退火速度问题,即每个T值的迭代次数L
模拟退火算法的全局搜索性能也与退火速度密切相关。一般来说,同一温度下的“充分”搜索是相当必要的,但这也需要计算时间。循环次数增加必定带来计算开销的增大。 - 温度管理问题
温度管理问题也是模拟退火算法难以处理的问题之一。实际应用中,由于必须考虑计算复杂度的切实可行性等问题。