我發現這篇舊的 stackoverflow 文章本質上正是我想要的。
比試錯法更有效地優化多個變數的演算法
不幸的是,我的更高級的數學有點欠缺,我對 ElKamina 的回答有一些疑問,如果有人可以看看這些基本的數學概念并提出建議,希望它會幫助我。
我所指的答案如下:
def simAnneal( w, seed_x, numSteps=100000, sigma=0.01 ):
optimal_x = [i for i in seed_x]
optimal_w = w(optimal_x)
cur_w = w(seed_x)
for i in range(numSteps):
new_x = [i random.gauss(0, sigma) for i in seed_x]
new_w = w(new_x)
if (new_w > cur_w) or (random.random() > new_w / cur_w) :
cur_x = new_x
cur_w = new_w
if cur_w > optimal_w:
optimal_w = cur_w
optimal_x = cur_x
return optimal_x
我不熟悉seed_x、sigma 和gaussian 分布,所以我不確定他們是如何提出new_x 的。
我正在嘗試根據許多變數(> 10)求解一個值,并且試圖優化而不是隨機猜測,因為它會花費很長時間。
謝謝!
uj5u.com熱心網友回復:
模擬退火 TLDR:我們試圖找到一組引數,通過向引數添加隨機噪聲來最大化函式。如果改變導致改進,則接受改變;偶爾我們會接受負面變化,但這種可能性會隨著時間的推移和變化的嚴重程度而降低。
在上面的代碼片段中,該函式實際上使用了多個引數,但將它們作為串列接受:
w是引數優化的函式seed_x是引數的初始猜測 - 可以隨機選擇,但明智的猜測會更好- 高斯只是噪聲的“形狀”,因此較小的值更常見。
random.random()*sigma(所有值都同樣可能)在那里也能正常作業。 sigma是要注入的噪聲的幅度。它不應超過典型引數值的百分之幾。如果 param 值的大小相差很大,請考慮使用特定于每個引數的 sigma 串列。- 缺少:溫度的概念,這實際上會使它模擬退火
用溫度、更具描述性的名稱和更明確的方式重寫它:
def simAnneal(utility_func, initial_params, numSteps=100000,
noise_magnitude=0.01, cooling_rate=0.999):
optimal_params = initial_params
params = initial_params.copy() # lists are mutable, so .copy()
best_utility = utility = utility_func(*initial_params)
temperature = 1.0
for i in range(numSteps):
temperature *= cooling_rate
# consider using numpy/scipy for params and noise
new_params = [param random.gauss(0, noise_magnitude)
for param in params]
# explicitly passing multiple parameters
new_utility = utility_func(*new_params)
if (new_utility > best_utility
or random.random()*temperature > new_utility / best_utility):
params, utility = new_params, new_utility
if new_utility > best_utility:
optimal_params, best_utility = params, utility
return optimal_params
最后但并非最不重要的 - 除非問題非常非凸,否則我敢打賭SGD會表現得更好。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/377849.html
下一篇:C 中的奇怪錯誤而不停止程式
