優(yōu)化是機(jī)器學(xué)習(xí)的研究人員最感興趣的領(lǐng)域之一鸣皂。在本文中抓谴,我想從簡(jiǎn)單的函數(shù)優(yōu)化開(kāi)始介紹,然后討論找到只能找到局部最小值或難以找到最小值的較為復(fù)雜的函數(shù)寞缝,約束優(yōu)化和幾何優(yōu)化問(wèn)題癌压。我也希望使用完全不同的方法進(jìn)行優(yōu)化:從基于梯度的方法開(kāi)始,并結(jié)合進(jìn)化算法和其他深度學(xué)習(xí)的最新方法荆陆。當(dāng)然滩届,我們要使用機(jī)器學(xué)習(xí)應(yīng)用程序來(lái)展示它們,而我目的是展示數(shù)值優(yōu)化中的問(wèn)題和算法被啼,并讓你理解AdamOptimizer()的原理帜消。
我專注于將不同的算法行為可視化棠枉,以理解其背后的數(shù)學(xué)和代碼的直覺(jué),因此在這一系列文章中會(huì)有很多的GIF圖泡挺。如零階方法辈讶,在SciPy中的一階方法贱除,Tensorflow中的一階方法月幌,二階方法扯躺。
源代碼:https://github.com/Rachnog/Optimization-Cookbook/tree/master/chapter1
優(yōu)化函數(shù)
首先缅帘,我們來(lái)定義數(shù)據(jù)集钦无。我決定從最簡(jiǎn)單的那個(gè)開(kāi)始失暂,它應(yīng)該很容易優(yōu)化弟塞,并用不同的工具顯示一般的演練决记。你可以訪問(wèn)下方鏈接獲取的函數(shù)和公式的完整列表,在這里我只選取一部分建车。
完整列表:https://www.sfu.ca/~ssurjano/optimization.html
可視化教程:http://tiao.io/notes/visualizing-and-animating-optimization-algorithms-with-matplotlib/
BOWL函數(shù)(呈碗狀的函數(shù))
Bohachevsky函數(shù)和Trid函數(shù)
def bohachevsky(x潮罪,y):
? ? return x ** 2 + 2 * y ** 2 -0.3 * np.cos(3 * 3.14 * x)-0.4 * np.cos(4 * 3.14 * y)+0.7
def trid(x嫉到,y):
? ? return(x-1)** 2 +(y-1)** 2? -? x * y
PLATE函數(shù)(呈板狀)
Booth描睦、Matyas和Zakharov函數(shù)
def booth(x忱叭,y):
? ? return(x + 2 * y? -? 7)** 2 +(2 * x + y? -? 5)** 2
def matyas(x韵丑,y):
? ? return 0.26 *(x ** 2 + y ** 2) -? 0.48 * x * y
def zakharov(x撵彻,y):
? ? return(x ** 2 + y ** 2)+(0.5 * x + y)** 2 +(0.5 * x + y)** 4
VALLEY函數(shù)(呈谷狀)
Rozenbrock碗短,Beale和Six Hump Camel函數(shù)
def rozenbrock(x偎谁,y):
? ? return(1-x)** 2 + 100 *(y? -? x ** 2)** 2
def beale(x,y):
? ? return(1.5? -? x + x * y)** 2 +(2.25? -? x + x * y ** 2)** 2 +(2.65? -? x + x * y ** 3) ** 2
def six_hump(x铐望,y):
? ? return(4-2.1 * x ** 2 + x ** 4/3)* x ** 2 + x * y +(-4 + 4 * y ** 2)* y * * 2
算法
在這里,我們簡(jiǎn)單看一下SciPy和Tensorflow中優(yōu)化的基本算法溶推。
無(wú)梯度優(yōu)化
通常我們的代價(jià)函數(shù)是嘈雜的或不可微分的虱痕,因此我們不能在這種情況下應(yīng)用使用梯度的方法部翘。在本教程中新思,我們比較了Nelder-Mead和Powell算法夹囚,它們不計(jì)算梯度荸哟。第一種方法構(gòu)建(n + 1)維的單純型(simplex)鞍历,并在其上找到最小值劣砍,依次更新它秆剪。Powell方法在空間的每個(gè)基向量上進(jìn)行一維搜索仅讽。使用SciPy實(shí)現(xiàn)如下:
minimize(fun 洁灵,x0 徽千,method ='Nelder-Mead' 双抽,tol = None 牍汹,callback = make_minimize_cb )
callback用于保存中間結(jié)果(取自上方鏈接的可視化教程)。
一階算法
你可能會(huì)從Tensorflow等機(jī)器學(xué)習(xí)框架中了解到這種算法嫁蛇。它們朝著反梯度的方向發(fā)展睬棚,得出函數(shù)的最小化抑党。但這些算法移動(dòng)到最小值的細(xì)節(jié)差別很大新荤。我們使用Tensorflow來(lái)實(shí)現(xiàn):梯度下降(有和沒(méi)有)苛骨,Adam和RMSProp痒芝。(完整代碼在github中可以找到):
x = tf.Variable(8., trainable=True)
y = tf.Variable(8., trainable=True)
f = tf.add_n([
? ? tf.add(tf.square(x), tf.square(y)),
? ? tf.square(tf.add(tf.multiply(0.5, x), y)),
? ? tf.pow(tf.multiply(0.5, x), 4.)?
])
并按以下方式進(jìn)行優(yōu)化:
opt = tf.train.GradientDescentOptimizer(0.01)
grads_and_vars = opt.compute_gradients(f, [x, y])
clipped_grads_and_vars = [(tf.clip_by_value(g, xmin, xmax), v) for g, v in grads_and_vars]
train = opt.apply_gradients(clipped_grads_and_vars)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
points_tf = []
for i in range(100):
? ? points_tf.append(sess.run([x, y]))
? ? sess.run(train)
在SciPy中我們使用共軛梯度法,牛頓共軛梯度法请琳,截?cái)嗯nD法俄精,序貫最小二乘設(shè)計(jì)法竖慧。你可以閱讀更多關(guān)于這些算法的更多信息可以閱讀Boyd and Vandenberghe寫(xiě)的凸優(yōu)化圾旨。
SciPy接口或多或少與零階方法相同砍的。
二階算法
我們還將碰到一些使用二階導(dǎo)數(shù)加速收斂的算法:dog-leg信賴域, nearly exact信賴域挨约。這些算法順序地解決搜索區(qū)域(通常是球狀)被發(fā)現(xiàn)的局部最優(yōu)問(wèn)題诫惭。我們知道夕土,這些算法需要Hessian(或它的近似)怨绣,所以我們使用numdifftools庫(kù)來(lái)計(jì)算它們并傳入SciPy優(yōu)化器:
from numdifftools import Jacobian, Hessian
def fun(x):
? ? return (x[0]**2 + x[1]**2) + (0.5*x[0] + x[1])**2 + (0.5*x[0] + x[1])**4
def fun_der(x):
? ? return Jacobian(lambda x: fun(x))(x).ravel()
def fun_hess(x):
? ? return Hessian(lambda x: fun(x))(x)
minimize(fun, x0, method='dogleg', jac=fun_der, hess=fun_hess)
無(wú)梯度優(yōu)化
在本文中篮撑,我希望優(yōu)先從視覺(jué)角度評(píng)估結(jié)果,我認(rèn)為用你的眼睛軌跡來(lái)觀察是非常重要驮吱,這樣公式會(huì)更加清晰左冬。
以下是部分可視化(完整https://imgur.com/a/pFPyx)拇砰。
Jacobian優(yōu)化
在這里你可以看到使用SciPy和Tensorflow的基于梯度方法的比較皂岔。其中一些算法可能看起來(lái)很“慢”躁垛,??但這很大程度上取決于超參數(shù)的選擇教馆。
完整gif(imgur.com/a/cqN0Z土铺,imgur.com/a/SWFwQ)
Hessian優(yōu)化
使用二階導(dǎo)數(shù)幾乎立刻就能使我們得到很好的二次函數(shù)的最小值抄腔,但對(duì)于其他函數(shù)來(lái)說(shuō)不像那樣簡(jiǎn)單赫蛇。例如對(duì)于Bohachevsky函數(shù)它接近最小值雾叭,但不精確织狐。
其他函數(shù)的更多例子:https://imgur.com/a/PmyBq
超參數(shù)
學(xué)習(xí)率
首先鹰服,我想你已經(jīng)注意到悲酷,像Adam和RMSprop這樣流行的自適應(yīng)算法與比SGD慢的多设易。但它們不是應(yīng)該被設(shè)計(jì)成速度更快嗎顿肺?這是因?yàn)檫@些損失曲面的學(xué)習(xí)率太低渣蜗。參數(shù)必須分別針對(duì)每個(gè)問(wèn)題進(jìn)行調(diào)整耕拷。在下面的圖片中骚烧,你可以看到如果將它的值增加到1會(huì)發(fā)生什么。
起始點(diǎn)
通常我們從一個(gè)隨機(jī)點(diǎn)開(kāi)始尋找最小值(或者像神經(jīng)網(wǎng)絡(luò)中的一些智能初始化塊)羡榴,但通常這不是正確的策略炕矮。在下面的例子中,我們可以看到档痪,如果從錯(cuò)誤的點(diǎn)開(kāi)始腐螟,二階方法甚至?xí)l(fā)生偏移乐纸。在純粹的優(yōu)化問(wèn)題中克服這個(gè)問(wèn)題的方法之一是:使用全局搜索算法估計(jì)全局最小值的區(qū)域汽绢。
機(jī)器學(xué)習(xí)
現(xiàn)在你可能想要嘗試使用SciPy中的算法來(lái)在Tensorflow中訓(xùn)練機(jī)器學(xué)習(xí)模型跌宛。你甚至無(wú)需構(gòu)建自定義優(yōu)化器疆拘,因?yàn)?b>tf.contrib.opt已經(jīng)為你準(zhǔn)備好了寂曹!它允許使用相同的算法以及參數(shù):
vector = tf.Variable([7., 7.], 'vector')
# Make vector norm as small as possible.
loss = tf.reduce_sum(tf.square(vector))
optimizer = ScipyOptimizerInterface(loss, options={'maxiter': 100}, method='SLSQP')
with tf.Session() as session:
? optimizer.minimize(session)
結(jié)論
本文只是對(duì)優(yōu)化領(lǐng)域的介紹漱挚,但從這些結(jié)果我們可以看出匾灶,這并不容易。使用二階或自適應(yīng)速率算法并不能保證我們收斂到最小值〖彰樱現(xiàn)在你有一些直覺(jué),了解所有這些算法的工作原理业筏。
原文網(wǎng)址:http://www.atyun.com/17210_機(jī)器學(xué)習(xí)優(yōu)化函數(shù)的直觀介紹&=3.html
關(guān)于人工智能,如果想了解更多台谢,可關(guān)注微信公眾號(hào):atyun_com或者網(wǎng)站AiTechYun(?http://www.atyun.com/)岁经,最快獲得第一手信息缀壤。