演算法理解-模擬退火
阿新 • • 發佈:2019-01-29
求解函式
以求解以下這麼一個函式為例子,實現程式碼為R語言
其函式影象為:
求解流程與概念
初始解的產生
又稱做狀態產生函式,通常由兩部分組成:
1)第一次產生候選解的分佈函式。
2)第一次產生候選解不滿足條件的情況下,再次產生解的分佈函式。
下面採用的是標準差為2的正態分佈、標準差為3的正態分佈。其中要注意的是狀態產生函式(領域函式)的出發點應該是儘可能保證產生的候選解遍佈全部的解空間。
劣解接受概率(Metropolis準則)
又稱做狀態接受函式,這裡是模擬退火法這個名字的來源,模仿固體退火原理,隨著溫度(迭代次數上升)的下降,能量逐漸穩定。即劣解的接受概率
從公式中可以看出這是求最小值時的分佈,因為當新的解小於舊解時百分百接受。又可以看出當
關於初始溫度,初溫越大,獲得高質量解的機率越大,但花費較多的計算時間,原理可以從上面的圖中或者結合下面溫度隨時間變化進行理解、解釋,溫度越高對於劣解的接受能力越大(搜尋範圍越大),下降速度越慢(求解速度下降)。
關於初始解如何設定一般有以下方法:
(1)按照某一概率分佈抽樣一組K個解,以K個解的目標值的方差為初溫(下面使用的時正態分佈);。
(2)隨機產生一組K個狀態,確定兩兩狀態間的最大目標差值,根據差值,利用一定的函式確定初溫。
(3)利用經驗公式。
溫度更新
溫度更新函式:
溫度可以看出不管初始溫度如何,都有一個先加熱後散熱的過程。即先提高搜尋範圍,再慢慢的減少搜尋範圍。至於為什麼會在差不多時刻大家都把溫度降低,我是這麼進行理解的,他們只是在不斷的接近,而不會重疊,同一時刻初始溫度越大,其當前時刻溫度也越大,都接近在同一刻收斂是因為他們總是在以一個倍數在進行減少。
程式碼
演算法流程圖:
程式碼:
# 定義目標函式
sloveFun <- function(x){
(x*sin(10*pi * x) + 2)
}
limitX <- c(-1, 2)
#1. 初始化以及引數調整
stmp <- runif(100 , limitX[1], limitX[2]) # 用於求初始溫度設定
t0 <- var(sloveFun(stmp)) # 初始溫度
s0 <- runif(1, limitX[1], limitX[2]) # 初始解
iters <- 1000 # 迭代次數
ccnt <- 200 # 終止條件,連續ccnt個新解都沒有接受時終止演算法
hisBest <- limitX[2] # 預設取上界
ccntVc <- NULL
#2.迭代
for (i in 1:iters) {
#2.1 在s0附近產生新解,但又能包含定義內所有值
s1 <- rnorm(1, mean = s0, sd = 2)
while (s1 < limitX[1] || s1 > limitX[2]){
s1 <- rnorm(1, mean = s0, sd=3)
}
#2.2 計算能量增量
delta_t <- sloveFun(s0) - sloveFun(s1)
#2.3 根據增量判斷是否接受解
if (delta_t > 0) { # 接受更好解
s0 <- s1
ccntVc <- c(ccntVc, 1)
}else{ # 較差的解以一定概率接受
p <- exp(delta_t / t0)
p1 <- sample(x = c(0, 1), size = 1, prob = c(1-p, p)) # 以一定概率生成 0,1:0 不接受劣解,1 接受劣解
if( p1 == 1 ) {
s0 <- s1
ccntVc <- c(ccntVc, 1)
} else {
ccntVc <- c(ccntVc, 0)
}
}
#2.4 更新最優值
hisBest <- ifelse(sloveFun(s1) < sloveFun(hisBest), s1, hisBest)
hisBest <- ifelse(sloveFun(s0) < sloveFun(hisBest), s0, hisBest)
#2.5 更新溫度
t0 <- t0/log(1 + i) # 溫度隨時間的推移而下降
#2.6 檢查終止條件
ccntVcLen <- length(ccntVc)
if (ccntVcLen > ccnt && # 模擬次數大於ccnt
sum(ccntVc[(ccntVcLen - ccnt +1):ccntVcLen]) == 0) { # 連續ccnt次沒有接受新解,ccntVc末尾200個全為0
cat("連續", ccnt, "次沒有接受新解,演算法終止!","\n")
cat("迭代次數為:", i, "\n")
cat("最優解為:", hisBest, "\n")
break()
}
}
# 連續 200 次沒有接受新解,演算法終止!
# 迭代次數為: 257
# 最優解為: 1.848313
在看了遊皓麟一書的某些程式碼塊後,越發感覺利用R語言學習演算法的效率之高,程式碼簡短,感覺就像可以執行的流程圖。是一個學習的快速工具。