模拟退火算法介绍和实例实现

一、模拟退火算法简介
模拟退火算法(SA)来源于固体退火原理,是一种基于概率的算法。将固体加温至充分高的温度,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,分子和原子越不稳定。而徐徐冷却时粒子渐趋有序,能量减少,原子越稳定。在冷却(降温)过程中,固体在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。
模拟退火算法从某一较高初温出发,伴随温度参数的不断下降,结合概率突跳特性在解空间中随机寻找目标函数的全局最优解,即在局部最优解能概率性地跳出并最终趋于全局最优。模拟退火算法是通过赋予搜索过程一种时变且最终趋于零的概率突跳性,从而可有效避免陷入局部极小并最终趋于全局最优的串行结构的优化算法。

二、模拟退火算法原理
模拟退火算法包含两个部分即Metropolis算法和退火过程,分别对应内循环和外循环。外循环就是退火过程,将固体达到较高的温度(初始温度T(0)),然后按照降温系数alpha使温度按照一定的比例下降,当达到终止温度Tf时,冷却结束,即退火过程结束。

Metropolis算法是内循环,即在每次温度下,迭代L次,寻找在该温度下能量的最小值(即最优解)。下图中所示即为在一次温度下,迭代L次,固体能量发生的变化。在该温度下,整个迭代过程中温度不发生变化,能量发生变化,当前一个状态x(n)的能量大于后一个状态x(n+1)的能量时,状态x(n)的解没有状态x(n+1)的解好,所以接受状态x(n+1)。但是如果下一状态的能量比前一个状态的能量高时,该不该接受下一状态呢?在这里设置一个接受概率P,即如果下一状态的能量比前一个状态的能量高,则接受下一状态的概率为P,下面具体讲一下如何接受下一个状态。

Metropolis算法就是如何在局部最优解的情况下让其跳出来(如图中B、C、E为局部最优),是退火的基础。1953年Metropolis提出重要性采样方法,即以概率来接受新状态,而不是使用完全确定的规则,称为Metropolis准则,计算量较低。

假设开始状态在A,多次迭代之后更新到B的局部最优解,这时发现更新到B时,能力比A要低,则说明接近最优解了,因此百分百转移,状态到达B后,发现下一步能量上升了,如果是梯度下降则是不允许继续向前的,而这里会以一定的概率跳出这个坑,这各概率和当前的状态、能量等都有关系。所以说这个概率的设计是很重要的,下面从数学方面进行解释。

假设前一个状态为x(n),系统根据某一指标(梯度下降,上节的能量),状态变为x(n+1),相应的,系统的能量由E(n)变为E(n+1),定义系统由x(n)变为x(n+1)的接受概率P为:


从上式我们可以看到,如果能量减小了,那么这种转移就被接受(概率为1),如果能量增大了,就说明系统偏离全局最优值位置更远了,此时算法不会立刻将其抛弃,而是进行概率操作:首先在区间【0,1】产生一个均匀分布的随机数ϵ,如果ϵ<P,则此种转移接受,否则拒绝转移,进入下一步,往复循环。其中P以能量的变化量和T进行决定概率P的大小,所以这个值是动态的。

用固体退火模拟组合优化问题,将内能E模拟为目标函数值f,温度T演化成控制参数t,即得到解组合优化问题的模拟退火算法:由初始解i和控制参数初值t开始,对当前解重复“产生新解→计算目标函数差→接受或舍弃”的迭代,并逐步衰减t值,算法终止时的当前解即为所得近似最优解,退火过程由冷却进度表(Cooling Schedule)控制,包括控制参数的初值t及其衰减因子Δt、每个t值时的迭代次数L和停止条件Tf。而温度的作用就是来计算转移概率P的。当温度每次下降后,转移概率也发生变化,因此在所有温度下迭代L次的结果也都是不相同的。在每个温度下迭代L次来寻找当前温度下的最优解,然后降低温度继续寻找,直到到达终止温度,即转移概率P接近于0。

接受状态的三条原则:
(1)在固定温度下,接受使目标函数下降的候选解的概率要大于使目标函数上升的候选解概率;
(2)随着温度的下降,接受使目标函数上升的解的概率要逐渐减小;
(3)当温度趋于零时,只能接受目标函数下降的解。

三、退火过程中的参数控制
(1)初始的温度T(0)应选的足够高,使的所有转移状态都被接受。初始温度越高,获得高质量的解的概率越大,耗费的时间越长。

(2)退火速率,即温度下降,最简单的下降方式是指数式下降:
T(n)=αT(n),n =1,2,3,…
其中α是小于1的正数,一般取值为0.8到0.99之间。使得对每一温度,有足够的转移尝试,指数式下降的收敛速度比较慢。

(3)终止温度
如果温度下降到终止温度或者达到用户设定的阈值,则退火完成。

四、算法步骤
1.模拟退火的基本思想:

(1) 初始化:初始温度T(充分大),初始解状态S(是算法迭代的起点),每个T值的迭代次数L;
(2) 对k=1, …, L做第(3)至第6步;
(3) 产生新解S′;
(4) 计算增量ΔT=C(S′)-C(S),其中C(S)为目标函数,C(S)相当于能量;
(5) 若ΔT<0则接受S′作为新的当前解,否则以概率exp(-ΔT/T)接受S′作为新的当前解;
(6) 如果满足终止条件则输出当前解作为最优解,结束程序;
(7) T逐渐减少,且T->0,然后转第2步。


2.模拟退火算法新解的产生和接受可分为如下四个步骤:

第一步是由一个产生函数从当前解产生一个位于解空间的新解;为便于后续的计算和接受,减少算法耗时,通常选择由当前新解经过简单地变换即可产生新解的方法,如对构成新解的全部或部分元素进行置换、互换等,注意到产生新解的变换方法决定了当前新解的邻域结构,因而对冷却进度表的选取有一定的影响。

第二步是计算与新解所对应的目标函数差。因为目标函数差仅由变换部分产生,所以目标函数差的计算最好按增量计算。事实表明,对大多数应用而言,这是计算目标函数差的最快方法。

第三步是判断新解是否被接受,判断的依据是一个接受准则,最常用的接受准则是Metropolis准则: 若ΔT<0则接受S′作为新的当前解S,否则以概率P接受S′作为新的当前解S。

第四步是当新解被确定接受时,用新解代替当前解,这只需将当前解中对应于产生新解时的变换部分予以实现,同时修正目标函数值即可。此时,当前解实现了一次迭代。可在此基础上开始下一轮试验。而当新解被判定为舍弃时,则在原当前解的基础上继续下一轮试验。

五、实例分析和代码实现

在该实例中f(x)为目标函数,即为能量。然后设置控制参数t(温度)。求目标函数f(x)的最小值和最优状态(最小值情况下x1和x2的值),即x1,x2在-5和5之间分别取何值时目标函数f(x)的值最小。在每次迭代中,x1,x2在-5到5之间取任意值。

首先设置初始温度为T0 =100,降温系数为alpha =0.99,终止温度为Tf =0.01,内循环迭代次数iter =100。
下面是完整代码:

import math
from random import random
import matplotlib.pyplot as plt

def func(x, y):                  #函数优化问题
    res= 4*x**2-2.1*x**4+x**6/3+x*y-4*y**2+4*y**4
    return res
#x为公式里的x1,y为公式里面的x2
class SA:
    def __init__(self, func, iter=100, T0=100, Tf=0.01, alpha=0.99):
        self.func = func
        self.iter = iter         #内循环迭代次数,即为L =100
        self.alpha = alpha       #降温系数,alpha=0.99
        self.T0 = T0             #初始温度T0为100
        self.Tf = Tf             #温度终值Tf为0.01
        self.T = T0              #当前温度
        self.x = [random() * 11 -5  for i in range(iter)] #随机生成100个x的值
        self.y = [random() * 11 -5  for i in range(iter)] #随机生成100个y的值
        self.most_best =[]
        """
        random()这个函数取0到1之间的小数
        如果你要取0-10之间的整数(包括0和10)就写成 (int)random()*11就可以了,11乘以零点多的数最大是10点多,最小是0点多
        该实例中x1和x2的绝对值不超过5(包含整数5和-5),(random() * 11 -5)的结果是-6到6之间的任意值(不包括-6和6)
        (random() * 10 -5)的结果是-5到5之间的任意值(不包括-5和5),所有先乘以11,取-6到6之间的值,产生新解过程中,用一个if条件语句把-5到5之间(包括整数5和-5)的筛选出来。
        """
        self.history = {'f': [], 'T': []}

    def generate_new(self, x, y):   #扰动产生新解的过程
        while True:
            x_new = x + self.T * (random() - random())
            y_new = y + self.T * (random() - random())
            if (-5 <= x_new <= 5) & (-5 <= y_new <= 5):  
                break                                  #重复得到新解,直到产生的新解满足约束条件
        return x_new, y_new 

    def Metrospolis(self, f, f_new):   #Metropolis准则
        if f_new <= f:
            return 1
        else:
            p = math.exp((f - f_new) / self.T)
            if random() < p:
                return 1
            else:
                return 0

    def best(self):    #获取最优目标函数值
        f_list = []    #f_list数组保存每次迭代之后的值
        for i in range(self.iter):
            f = self.func(self.x[i], self.y[i])
            f_list.append(f)
        f_best = min(f_list)
        
        idx = f_list.index(f_best)
        return f_best, idx    #f_best,idx分别为在该温度下,迭代L次之后目标函数的最优解和最优解的下标

    def run(self):
        count = 0
        #外循环迭代,当前温度小于终止温度的阈值
        while self.T > self.Tf:       
           
            #内循环迭代100次
            for i in range(self.iter): 
                f = self.func(self.x[i], self.y[i])                    #f为迭代一次后的值
                x_new, y_new = self.generate_new(self.x[i], self.y[i]) #产生新解
                f_new = self.func(x_new, y_new)                        #产生新值
                if self.Metrospolis(f, f_new):                         #判断是否接受新值
                    self.x[i] = x_new             #如果接受新值,则把新值的x,y存入x数组和y数组
                    self.y[i] = y_new
            # 迭代L次记录在该温度下最优解
            ft, _ = self.best()
            self.history['f'].append(ft)
            self.history['T'].append(self.T)
            #温度按照一定的比例下降(冷却)
            self.T = self.T * self.alpha        
            count += 1
            
            # 得到最优解
        f_best, idx = self.best()
        print(f"F={f_best}, x={self.x[idx]}, y={self.y[idx]}")

sa = SA(func)
sa.run()

plt.plot(sa.history['T'], sa.history['f'])
plt.title('SA')
plt.xlabel('T')
plt.ylabel('f')
plt.gca().invert_xaxis()
plt.show()

实验结果:



六、模拟退火算法在信息安全领域的应用

1.安全投资决策

安全投入是指企业为保证生产安全、改善作业环境、处理工伤事故、预防职业危害等而消耗的人力、物力、财力。安全投入包括主动性安全投入与被动性安全投入,主动性安全投入即安全投资,是指为了提高企业的系统安全性、预防各种事故的发生、防止因工伤亡,消除事故隐患、治理尘毒的全部费用。被动性安全投人是指企业为处理事故(灾害)而支付的费用,如职业病诊治费、赔偿费、事故处理费、维修费等,安全投资越大,系统安全性越高,从而可以减少甚至避免被动性安全投人。因此,研究安全投资具有更为积极的现实指导意义。目前,安全投资不足、安全投资缺乏科学的决策等一系列问题已经成为制约一个企业能否保证安全生产的瓶颈,而保证足够的安全投资、制定合理有效的安全投资决策方案是突破这一瓶颈的有效途径。

安全投资决策间题,即如何确定安全投资的最佳组合,使有限的安全投资得到充分的利用,已成为影响企业提高安全生产水平和经济效益的重要因素,也是安全系统工程研究的一个重要课题。该问题可归结为组合优化范畴,对于安全投资项目较少情况容易求解,而对于安全投资项目较多的情况求解难度将随着问题规模增长呈现出”组合爆炸”现象,很难用传统方法求得问题的最优解或满意解智能计算作为一类新颖的计算方法,由于其理论基础不断巩固、应用领域不断扩展、新算法不断出现研究成果层出不穷,已受到学术界的广泛关注,将智能计算中的模拟退火算法引人到安全工程领城中[1],用于求解安全投资决策问题,可以为企业进行安全投资提供科学有效的方法。

2.图像处理

从嵌入载体的形式上分,基于图像的数据隐藏包含空域隐藏算法,变换域隐藏算法以及与编码相结合的隐藏算法。与编码结合的嵌入算法是指在编码过程中或编码后的码流中嵌入数据。JPEG是当前互联网上通用的一种高效的压缩编码方法,它利用图像分块和二维DCT变换并结合编码方法实现图像数据的压缩。因此如何在JPEG的压缩码流中实现高容量高安全性的数据嵌入是十分有意义的研究。

JPEG图像的数据隐藏算法虽取得了一些进展,但在平衡安全性和隐藏容量上仍存在着一些不足。戴跃伟等人[2]提出一种基于可调整量化的嵌入算法,并以嵌入前后AC系数的统计分布的平均相对炼作为优化指标,使用模拟退火算法求解对统计分布破坏最小的调整变量能在保持较大信息容量的同时.取得更高的安全性能。

3.神经网计算机

玻尔兹曼机(Boltzmann机)是一种随机神经网络,借鉴了模拟退火思想。普通玻尔兹曼机是一种递归神经网络,受限玻尔兹曼机则不是。它具有一定的“爬山能力”(跳出局部最优)。

Boltzmann机是一种“基于能量的模型”,其为网络状态定义一个“能量”,当能量最小化时网络达到理想状态。它的特点是:两层结构,显层与隐层,显层即代表输入也代表输出,隐层则被理解为数据的内部表达;神经元是布尔型。

模拟退火算法具有跳出局部最优陷阱的能力。在Boltzmann机中,即使系统落入了局部最优的陷阱,经过一段时间后,它还能再跳出来,系统最终将往全局最优值的方向收敛。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年8月26日
下一篇 2023年8月26日

相关推荐