授權(quán)轉(zhuǎn)載自計算廣告(Comp_Ad) 作者 | 北冥乘海生 不論是產(chǎn)品經(jīng)理、在校生、運營還是工程師,都經(jīng)常提一個問題:現(xiàn)在是人工智能時代,我也很感興趣,該怎么做呢? 想成為一個二手的人工智能科學(xué)家,既不是報個Python培訓(xùn)班,也不是買塊GPU跑起來,更不是在Kaggle比賽數(shù)據(jù)上湊個答案。最重要的基礎(chǔ)技能,是不管扔給你一個什么樣的模型,都得能把它的最優(yōu)參數(shù)找出來,這個就叫最優(yōu)化,說色唐綱叫做Optimization。掌握了這門手藝,你才能在設(shè)計和選擇模型時進(jìn)入自由王國,而不是只會拿開源工具跑個結(jié)果。 最優(yōu)化的任務(wù),是找一個函數(shù)的最大值,通俗地說就是爬山:把你扔在一片山地里,看你怎么能最快地爬上最高峰。登山也分這么兩種:一種是無場地邊界限制的登野山,這對應(yīng)于無約束優(yōu)化問題;還有一種是有場地限制的登山,這叫做有約束優(yōu)化問題。顯然,前者是后者的一個特例,解決起來也簡單一些。 注意,本文用登山問題來比喻最優(yōu)化,是為了方便大家理解。不過實際數(shù)學(xué)上描述的最優(yōu)化問題,習(xí)慣上是求最小值,也就是“探谷”而非“登山”,因此在提到“某某下降法”這樣的術(shù)語時,大家能領(lǐng)會其精神就好了。 有約束優(yōu)化問題,可以通過拉格朗日乘數(shù)法轉(zhuǎn)化成無約束的方程組優(yōu)化問題,你可以這么理解,把登山賽場的圍欄去掉,轉(zhuǎn)而變成指定一條賽道,通過求解賽道上的公里數(shù)來求最高峰的位置——當(dāng)然,這條賽道是在高維空間里的曲折蜿蜒的。 對于有約束優(yōu)化問題,如果場地限制是個凸的形狀,而山也是象下圖中神山岡仁波齊那樣的凸函數(shù)(“凸”是啥意思各位自行查找),這就叫凸優(yōu)化問題。凸優(yōu)化式的登山問題,理論界研究比較充分,解決起來也相對容易。因此,在設(shè)計目標(biāo)函數(shù)時,我們往往傾向于構(gòu)造一個凸問題,這樣后面的事情就一馬平川了。 好了,既然有約束優(yōu)化問題可以轉(zhuǎn)化成無約束優(yōu)化問題來解決,我們就要重點掌握無約束優(yōu)化問題的思路和方法了。要順利登頂,無非要解決這三個基本問題:
根據(jù)這三點的不同,方法也是琳瑯滿目。各種方法的細(xì)節(jié),當(dāng)然不是本文能說清,但我希望帶領(lǐng)大家在這個領(lǐng)域走上一遭,讓諸位大致了解在什么情況下,應(yīng)該有何種思路。至于具體的方法,大家再去查書就行了。因此,堅持要問“哪里有code下載”的朋友們,敬請你們出門,上橋,右轉(zhuǎn)! 如果這片山地有很多山峰,要摸清地形,最高效的策略,是先開著直升機飛到空中看看全貌,找到最高峰的大致位置,再去那里精細(xì)地勘察。遺憾的是,目前所有實用的優(yōu)化方法,都沒有這種直升機式的航拍能力。據(jù)傳說,量子計算實現(xiàn)以后,可能會有這種一目千里的辦法,這個我們就不提了。 在有多個山峰的情況下,一般的方法都只能找到離自己的出發(fā)點比較近的某個峰,這稱為局部最優(yōu)(Local Optimum)。一定要找到全局最高峰的方法也有,例如模擬退火、遺傳算法等,但這都是帶有一些隨機性的方法,簡單說就是像醉鬼一樣瞎撞,當(dāng)然醉鬼爬山,肯定就很慢了,所以工程上并不常用。我們在這里,也只討論一個峰的優(yōu)化問題。 在登山過程中,我們一般都假設(shè):給定一個位置x,對應(yīng)的海拔高度f(x)是可以計算出來的——這不是廢話么,高低都不知道的還優(yōu)化個什么勁?除了計算海拔高度,我們往往還希望知道,在當(dāng)前位置往哪個方向最陡峭,也就是上升地最快,這就是梯度▽f(x)(注意,梯度是個方向而不是一個值,在數(shù)學(xué)上來看就是一個矢量,不懂的回去找你的體育老師重修去?。?/span> 這里要注意了:在實踐中,梯度能不能算出來,可就不一定了。如果梯度算不出來,或者算起來時間代價極大,怎么辦呢?這種場景雖然遇上的不多,但是萬一遇上了,不知道怎么辦也是抓瞎,就好像說相聲的不會太平歌詞,別人掙一百,你掙七十五。 在梯度無法計算的情況下,我們可以采用這樣的方法:從上圖中找三個人站成個三角形,海拔最低的那個人想辦法朝海拔高的方向走一段,然后再重新看三個人的海拔高度。就這樣把這個三角形象個阿米巴蟲一樣不斷伸縮,最終可以收斂到最高點,這個方法叫做下降單純形法(Downhill Simplex),或者就叫阿米巴(Ameoba)變形蟲法。用這種方法,爬地球上的山峰,三個人配合就夠了;而爬N維空間里的山峰,就得N+1個人配合了。 當(dāng)然,如果梯度可以計算,那就簡單多了:只要沿著最陡峭的方向走上一小步,海拔肯定是升高的,走完這一小步,再計算新的梯度,小車不倒只管推,總有走到山頂?shù)哪且惶欤@就叫做梯度下降法(Gradient Descent)。 梯度法在實操過程中,又有兩種思路:一種是在所有訓(xùn)練樣本上算好方向,然后加起來得到總的方向,這叫做批處理模式(Batch Mode);還有一種是在一小批樣本上算方向,走一小步,然后再取下一小批樣本算方向,這叫做隨機梯度下降法(Stochastic Gradient Descent,SGD)。聽起來好像是前一種方法更加合理,可實際上,常用的是后一種。 那么,批處理的梯度法有什么問題呢?我們看看下面這個圖就明白了:在這樣一個長條狀等高線的地區(qū)登山,如果每一步都按梯度方向來(注意梯度方向跟等高線垂直的),就會走出這樣拐來拐去的路線,不知啥時候才能爬到山頂。有人說,這樣奇怪的山很常見么?沒錯,很常見。因此,批處理的梯度法,工程上基本是不可用的。而SGD的方法,由于不同的數(shù)據(jù)片引入了一定的隨機性,也就是有點兒亂撞的意思,反而收斂性要好得多。 這種隨機性帶來的好處,有時候是超出人類想象的。Google的大神Jeff Dean等人干脆搞了個參數(shù)服務(wù)器(Parameter Server),讓一堆機器分別讀數(shù)據(jù)片段,完全互相不商量地去更新同一個模型,結(jié)果不但訓(xùn)練得飛快,收斂性也相當(dāng)好,您瞧這找誰說理去! 那么批處理的方法就不能用了么?不然。根據(jù)上面的圖來看,只要引入二階導(dǎo)數(shù)信息,就非常容易避免拐來拐去的問題了。二階導(dǎo)數(shù),我們稱為Hession矩陣H(x) = ▽^2 f(x),注意,H已經(jīng)是一個矩陣而不是矢量了。用二階導(dǎo)數(shù)修正一下走的方向,沿著 {H(x)}^(-1) ▽f(x)的方向走,這就叫做牛頓法(Newton Method)。 看起來,牛頓法應(yīng)該沒問題了?先別急,這個也不好用。學(xué)過線性代數(shù)的朋友都知道,H不一定正定阿!也就是說,從二階導(dǎo)來看,你不一定站在一個局部的拋物面上啊,萬一腳下是個馬鞍面,那還求什么極值?這怎么解決呢?嚴(yán)謹(jǐn)?shù)臄?shù)學(xué)家們決定用捏造的方法來解決!既然H不一定正定,那就造一個假的H出來,假的這個得是正定的,這就叫做擬牛頓法(Quasi-Newton Method)。當(dāng)然,要以假亂真,就不能胡來了,捏造的方法,基本上就是根據(jù)你前面走的幾步(比如前圖中那幾位)的海拔、梯度方向來擬合。具體的擬牛頓法有很多種,比較常見的一種,是BFGS方法,這里的四個字母,是四位數(shù)學(xué)家的名字。 擬牛頓法和牛頓法一樣,都會碰到一個工程上的挑戰(zhàn):當(dāng)x的維度很高時,H就會變得非常大。比方說x是一百萬維,H就有一萬億個元素,一般計算機的內(nèi)存可對付不了這么大的矩陣。于是,還要把H做個近似,將其分解為兩個條狀矩陣和一個對角陣,這樣規(guī)模就大大降低了。如果在BFGS方法上應(yīng)用這一技巧,就是著名的L-BFGS方法,這里的“L”,指的是“Limited-Memory”。 說到這兒,細(xì)心的讀者可能會發(fā)現(xiàn)一個問題,不論是梯度法、牛頓法、BFGS還是L-BFGS,都可以總結(jié)為“先方向,后步長”的方法。但是在找方向的過程中,又是編二階導(dǎo),又是近似的,這個方向找的還靠譜么?我只能說,大致上靠譜,不過確實也打了不小的折扣。那么如果不做這些妥協(xié)和近似行不行呢,辦法也是存在的,不過這就要要變成“先步長,后方向”的思路。 先方向后步長方法的典型代表,是置信域法(Trust-region method),與前面的擬牛頓法相比,它不用近似一個正定的H——這里的妙處在于,只要用金箍棒劃了一個圈兒,不管圈兒里是拋物面還是馬鞍面,最高點是可以求出來的,而且有個接近閉式的解! 不管是先步長還是先方向,步長到底選多大合適呢?說實話,這基本上是個玄學(xué)問題(如果不是神學(xué)問題的話):步子邁小了,得多怎才能爬上去;步子邁大了,象毗濕奴那樣一下子邁過三界的話,什么梯度、Hession矩陣就全亂了,優(yōu)化過程也變得不可控。但是,規(guī)律還是有的,那就是步長總是要按一定的規(guī)律逐漸變小的,好比你罰點球助跑的時候,前面大步流星,后面碎步緊倒,才能準(zhǔn)確找到球。 |
|