模拟退火算法(Simulated Annealing)

模拟退火算法

说说什么是算法?有人理解是输入数据经过一些步骤的处理,最后输出。在我理解来看就是一种优化问题或者说是数值分析,无论机器学习中的算法还是深度学习的算法,寻找最优模型都是解最小损失的函数。最后计算得到的模型都是对常用的模型的套用,得到具体模型前,关键还是求解损失函数,具体化模型参数。模拟退火不是模型,是一种算法,用于求解最优值。

背景

摘自维基百科模拟退火: 模拟退火来自冶金学的专有名词退火。退火是将材料加热后再经特定速率冷却,目的是增大晶粒的体积,并且减少晶格中的缺陷。材料中的原子原来会停留在使内能有局部最小值的位置,加热使能量变大,原子会离开原来位置,而随机在其他位置中移动。退火冷却时速度较慢,使得原子有较多可能可以找到内能比原先更低的位置。 模拟退火的原理也和金属退火的原理近似:我们将热力学的理论套用到统计学上,将搜寻空间内每一点想像成空气内的分子;分子的能量,就是它本身的动能;而搜寻空间内的每一点,也像空气分子一样带有“能量”,以表示该点对命题的合适程度。算法先以搜寻空间内一个任意点作起始:每一步先选择一个“邻居”,然后再计算从现有位置到达“邻居”的概率。 可以证明,模拟退火算法所得解依概率收敛到全局最优解。
不知到你什么感受,反正我开始看这段内容,然后理解算法有十万八千里的感觉。一句话,没有毛用。

公式

先介绍这个式子, T T T表示温度, k k k玻尔兹曼常量, Δ E \Delta E ΔE表示变化前后的能量的差值
在这里插入图片描述
上面这个公式 T T T是温度,退火表示温度的变低的过程,所以温度应用随时间变化。于是, T T T从某一高温状态T向低温状态冷却时的降温函数
在这里插入图片描述
T T T0表示初始温度, t t t表示时间。言归正传,将上面的公式利用起来总结为以下概率公式, d E dE dE表示新值减旧值得到的状态差,假定温度 T T T短时间不变化(不重要)
在这里插入图片描述
摆脱掉温度的干扰,找最优解的公式中,上面公式理解为:若函数上的y值变化为新的y值后变小了,则以概率为1的可能性,朝这个方向走,反之,可以一种随机概率其他方向走,就好比周志华《机器学习》中摇臂机问题要以 ϵ \epsilon ϵ的概率探索一样向其他方向走。
特别说明:重要的是思想,公式并不重要,上面的概率函数完全可以改用其他函数,温度衰减过程也可以用其他方式代替。

代码流程

代码由于是采用的是2维函数,方向单一所以比较简单:

import numpy as np
import matplotlib.pyplot as plt
#1、假设一个多项式为误差函数,需要找最优点
def Y(x):
    return (x - 2) * (x - 4) *(x+7)* (x + 11) * (x - 9)
    
#2、[-12,10]选随机选一个点做起始点
X=np.random.uniform(-12,10)
#-------下面注释由于最后跟温度没有关系,只需要最终的点,所以不需要两个循环
T=1000#表示初始温度
#Tend=1#表示最后温度,温度越低降温速率越低
# while T>Tend:
#     for i in range(20):
#         print(X)
#         oldY=Y(X)
#         preX=X+np.random.uniform(-1,1)
#         if preX>-12 and preX<10:
#           if Y(preX)<oldY:
#                X=preX
#           else:
#                if np.random.rand()>np.exp(-(Y(preX)-oldY)/T):
#                   X=preX
    # t+=1
    # T=1000/t
#--------------------------------------------------------------------------------
for i in range(200):
    oldY=Y(X)#记录旧点
    preX=X+np.random.uniform(-1,1)#随机选择邻域
    if preX>-12 and preX<10:#验证可能的新点在区间
      if Y(preX)<oldY:#按Metropolis准则
           X=preX
      else:
           if np.random.rand()>np.exp(-(Y(preX)-oldY)/T):#这个过程表示以一定的概率选择其他方向
              X=preX
              T+=0.95*T#衰减不一定按上面的函数来
print(X)
print(Y(X))
#!!!完
#下面是绘图,看效果,明显可以看到最优值,不是每次都能选到最优值
x=np.linspace(-12,10,100)
y=[Y(x) for x in x]
#图的操作
plt.plot(x,y,color='b')
gc=plt.gca()
gc.spines['top'].set_color(None)
gc.spines['right'].set_color(None)
gc.spines['left'].set_position(('data',0))
gc.spines['bottom'].set_position(('data',0))
plt.plot(X,Y(X),'or')
plt.show()

注意:不是每次都能选到最优值,所以需要取多次结果,取最小值,找最大值,把条件反过来写即可
在这里插入图片描述
[1]:https://www.cnblogs.com/ECJTUACM-873284962/p/8468831.html
[2]:https://blog.csdn.net/weixin_40562999/article/details/80853418
[3]:https://www.imooc.com/article/details/id/30160

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值