模擬退火算法

 

引言

在實際日常中,人們會經常遇到如下問題:在某個給定的定義域X內,求函數f(x)對應的最優值。此處以最小值問題舉例(最大值問題可以等價轉化成最小值問題),形式化爲: 

\underset{x\in\chi }{min}f(x)

如果X是離散有限取值,那麼可以通過窮取法獲得問題的最優解;如果X連續,但f(x)是凸的,那可以通過梯度下降等方法獲得最優解;如果X連續且f(x)非凸,雖說根據已有的近似求解法能夠找到問題解,可解是否是最優的還有待考量,很多時候若初始值選擇的不好,非常容易陷入局部最優值。

 

隨着日常業務場景的複雜化,第三種問題經常遇見。如何有效地避免局部最優的困擾?模擬退火算法應運而生。其實模擬退火也算是啓發式算法的一種,具體學習的是冶金學中金屬加熱-冷卻的過程。由S.Kirkpatrick, C.D.Gelatt和M.P.Vecchi在1983年所發明的,V.Čern在1985年也獨立發明此演算法。

不過模擬退火算法到底是如何模擬金屬退火的原理?主要是將熱力學的理論套用到統計學上,將搜尋空間內每一點想像成空氣內的分子;分子的能量,就是它本身的動能;而搜尋空間內的每一點,也像空氣分子一樣帶有“能量”,以表示該點對命題的合適程度。演算法先以搜尋空間內一個任意點作起始:每一步先選擇一個“鄰居”,然後再計算從現有位置到達“鄰居”的概率。若概率大於給定的閾值,則跳轉到“鄰居”;若概率較小,則停留在原位置不動。


一、模擬退火算法基本思想

模擬退火其實也是一種貪心算法,但是它的搜索過程引入了隨機因素。在迭代更新可行解時,以一定的概率來接受一個比當前解要差的解,因此有可能會跳出這個局部的最優解,達到全局的最優解。以下圖爲例,假定初始解爲左邊藍色點A,模擬退火算法會快速搜索到局部最優解B,但在搜索到局部最優解後,不是就此結束,而是會以一定的概率接受到左邊的移動。也許經過幾次這樣的不是局部最優的移動後會到達全局最優點D,於是就跳出了局部最小值。 

根據熱力學的原理,在溫度爲T時,出現能量差爲dE的降溫的概率爲p(dE),表示爲:

 p(dE)=exp(\frac{dE}{kT})

其中k是波爾茲曼常數,值爲k=1.3806488(13)×10−23,exp表示自然指數,且dE<0。因此dE/kT<0,所以p(dE)函數的取值範圍是(0,1)。滿足概率密度函數的定義。其實這條公式更直觀意思就是:溫度越高,出現一次能量差爲p(dE)的降溫的概率就越大;溫度越低,則出現降溫的概率就越小。

在實際問題中,這裏的“一定的概率”的計算參考了金屬冶煉的退火過程。假定當前可行解爲x,迭代更新後的解爲x_new,那麼對應的“能量差”定義爲:

\Delta f=f(x\_new)-f(x)

其對應的“一定概率”爲:

 p(\Delta f)=\left\{\begin{matrix} exp(-\frac{\Delta f}{kT})\quad for\; minimum\; optimization\\ exp(\frac{\Delta f}{kT})\quad for \; maximum\;optimization \end{matrix}\right.

注:在實際問題中,可以設定k=1。因爲kT可以等價於一個參數TT。如設定k=2、T=1000,等於直接設定T=2000的效果。


二、模擬退火算法描述

  1. 初始化:初始溫度T(充分大),溫度下限Tmin(充分小),初始解狀態x(是算法迭代的起點),每個T值的迭代次數L;
  2. 對l=1,2,...,L做第3至第6步;
  3. 產生新解x_new: (x_new=x+Δx);
  4. 利計算增量Δf=f(x_new)−f(x),其中f(x)爲優化目標;
  5. 若Δf<0(若尋找最大值,Δf>0)則接受x_new作爲新的當前解,否則以概率exp⁡(−Δf/(kT))接受x_new作爲新的當前解;
  6. 如果滿足終止條件則輸出當前解作爲最優解,結束程序。(終止條件通常取爲連續若干個新解都沒有被接受時終止算法。);
  7. T逐漸減少,且T>Tmin,然後轉第2步。


三、模擬退火算法的優缺點

模擬退火算法的應用很廣泛,可以高效地求解NP完全問題,如貨郎擔問題(Travelling Salesman Problem,簡記爲TSP)、最大截問題(Max Cut Problem)、0-1揹包問題(Zero One Knapsack Problem)、圖着色問題(Graph Colouring Problem)等等,但其參數難以控制,不能保證一次就收斂到最優值,一般需要多次嘗試才能獲得(大部分情況下還是會陷入局部最優值)。觀察模擬退火算法的過程,發現其主要存在如下三個參數問題:

  (1) 溫度T的初始值設置問題 
  溫度TT的初始值設置是影響模擬退火算法全局搜索性能的重要因素之一、初始溫度高,則搜索到全局最優解的可能性大,但因此要花費大量的計算時間;反之,則可節約計算時間,但全局搜索性能可能受到影響。

  (2) 退火速度問題,即每個TT值的迭代次數 
  模擬退火算法的全局搜索性能也與退火速度密切相關。一般來說,同一溫度下的“充分”搜索是相當必要的,但這也需要計算時間。循環次數增加必定帶來計算開銷的增大。

  (3) 溫度管理問題 
  溫度管理問題也是模擬退火算法難以處理的問題之一。實際應用中,由於必須考慮計算複雜度的切實可行性等問題,常採用如下所示的降溫方式: 

T=\alpha *T\quad \alpha \in(0,1)

注:爲了保證較大的搜索空間,α一般取接近於1的值,如0.95、0.9。


四、模擬退火算法Python實戰

經過上面理論知識的薰陶,相信大家已經對模擬退火算法有了較深入的理解,接下來通過實戰再強化一下大家的認識,此處利用模擬退火算法求解如下優化問題:

min \; f(x)=(x-2)*(x+3)*(x+8)*(x-9) 

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

def inputfun(x):
    return (x-2)*(x+3)*(x+8)*(x-9)

initT = 1000 #初始溫度
minT = 1 #溫度下限
iterL = 1000 #每個T值的迭代次數
delta = 0.95 #溫度衰減係數
k = 1

initx = 10*(2*np.random.rand()-1)
nowt = initT
print "初始解:",initx

xx = np.linspace(-10,10,300)
yy = inputfun(xx)
plt.figure()
plt.plot(xx,yy)
plt.plot(initx,inputfun(initx),'o')

#模擬退火算法尋找最小值過程
while nowt>minT:
    for i in np.arange(1,iterL,1):
        funVal = inputfun(initx)
        xnew = initx+(2*np.random.rand()-1)
        if xnew>=-10 and xnew<=10:
            funnew = inputfun(xnew)
            res = funnew-funVal
            if res<0:
                initx = xnew
            else:
                p = np.exp(-(res)/(k*nowt))
                if np.random.rand()<p:
                    initx = xnew
#            print initx-xnew
#    print initx
#    print nowt
    nowt = nowt*delta

print "最優解:",initx
print "最優值:",inputfun(initx)
plt.plot(initx,inputfun(initx),'*r')
plt.show()

可以看到,即使初始解選取的有風險,模擬退火算法經過迭代,也可以成功跳出局部最優值,最終收斂到問題的全局最優。

 

轉自AI_BigData_WH的博客,僅作爲學習之用,如有侵權,可聯繫[email protected]刪除。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章