15.調參(Tuning hyperparameters)

weixin_34253539發表於2019-03-03

不可否認的是,現在在做深度學習的過程中,調引數是一件非常重要且主要的事情。那麼,今天我們來講一下調引數這件事。

Grid Search

Grid Search就是窮舉,窮舉所有的超參組合。
當你對決策樹調參,如果只對一個超參優化,比如樹的最大深度,嘗試。那麼可以表示為:

5631876-6ce8f87f61d6b6c1.png

如果你還想對分裂標準進行調參,分別試試gini和entropy,那麼就相當要對
組引數進行嘗試。如下圖:
5631876-d33f8e67711fcfaf.png

所以這就是為什麼叫做gird search,網格搜尋。grid search是對網格中每個交點進行遍歷,從而找到最好的一個組合。
網格的維度就是超參的個數。如果有
個超參,每個超參有
個候選,那麼我們就要遍歷
個組合。所以說盡管效果不錯,但是計算代價是非常非常大的。

Random Search

有另外一個方法叫做Random Search,就是說我們不要循規倒矩的把每一個可能性都試過,我們隨機取樣的方式取樣出我們想要測試的test。舉例來說我這邊有個點,我們不要個點都做,我們說個點裡面抽一些點出來試,看哪一點的結果最好,就選那一個點就好了,這個叫做Random Search
其實在deep learning裡面,Random Search通常是蠻有效率的,為什麼?你把所有你要search的方法組合統統拿出來在data做測試,其實的那些方法,他們的performance可能沒有太大的差距。因為今天在做deep learning的時候,通常只有某幾個引數對你的結果有特別決定性的影響,有很多引數對你的結果的影響是不大的。所以今天在所有的引數組合裡面有很多種引數,它的performance的其實都是一樣,你performance最好的那幾組的引數組合,它的結果可能都是大同小異的,所以其實沒有必要找過所有的引數組合,舉最好的那一組出來,你其實只要選前名的幾種的出來,其實結果應該就夠好了。

好,這是基本的假設。在這個前提之下,假設我們現在有個點,我們想要做grid search,我們從點裡面隨便選一個點,它落在的機率是多少?很簡單,就是除以;接下來我們取樣次,他們落在裡面的機率是多少?你就先計算每一次取樣 不到的機率是,取樣到的機率即: 。
我們希望這個機率大於的話,如果給你跟你就可以輕易地把推出來。舉例來說,如果今天,要選到, 如果你要確保說有超過的機率,你一定可以取樣到的結果,你只需要取樣次;或是更進一步假設只要是取樣到你就滿足了,那你取樣的次數就可以降到只要取樣次就可以保證有超過的機率取樣到的引數組合,因為的指數項的下降是非常快的,所以其實你不需要取樣太多次,就可以取樣到你想要的東西,所以其實做random search是也是一個非常有效率的方式。

5631876-68b20fadf6607f26.jpg

Model-based Hyperparameter Optimization

有另外一個做法叫做Model-based Hyperparameter Optimization,這個做法就叫做Bayesian的optimization,今天我們就只講一下它的概念。
假設橫軸代表說你要去調的引數,比如說learning rate,(這邊一維就代表你要調一個引數,但實做上你要調的引數往往有數十個,所以它其實是在一個高維的空間中做Bayesian的optimization)我們選擇一個learning rate,然後去跑一下結果得到一個Accuracy,見下圖中的點1;我們再選另外一個learning rate再跑一下,結果再得到一個Accuracy,見下圖中的點2;現在我們就得到兩個Accuracy。接下來我們根據這兩筆training data就learn一個regression model估測說:如果給定不同的學習率,我們期待的Accuracy有多大?這個regression model通常會有一個Bayesian的model,這個Bayesian的model可以告訴我們說在這些region裡面model的confidence有多大。舉例來說,如下圖所示,因為兩個點是已知的,所以這兩個點的confidence就非常大,這個位置因為沒有取樣的點,所以這個位置的confidence就非常小,藍色的區域代表今天model在估測的時候覺得可能的區間;藍色區域越大就代表confidence越小。

5631876-5edb8cadedc72584.png

好,接下來我們要根據上圖中黑色的這一個曲線,即estimate的結果選下一個點。怎麼選 就取決於兩件事,一個是:我們希望找一組根據我們的model估測出來它會得到比較好的結果的引數組合;假設我們只這麼做,那machine已經知道說這個點它的正確率最高,每次選要estimate正確率的時候,他就只會選在這個區域,這不是我們要的。第二條件是我們也需要machine去做一些探查去做一些搜尋,看看說在hyperparameter的空間裡面,有沒有哪些地方是我們沒有探查到的,那沒有探查到的地方我們應該探檢視看:如果設那一組引數組合會得到什麼樣的結果,所以今天會同時考慮兩件事情,一件事情是根據這個模型估測出來的結果,另外一個是這個模型他的confidence,我們希望選一個估測出來正確率高,但是confidence低的地方,根據估測的正確率和confidence,你會定出一個acquisition function,就是上圖中綠色的這個函式,還有選綠色的函式值最高的地方,比如說在上圖紅色三角這個點。

好,接下來選了這個點,比如說這個learning rate以後,再去跑一下你的model得到Accuracy;你現在你就有三筆training data去做你的regression的problem,你在得到一條regression的線,還有得到在每一個區域這個regression的confidence。如下圖所示:
5631876-863a49a7f30b1927.png

而接下來就反覆那個過程,接下來取樣在這個地方你就得到新的點:
5631876-7d034adc12aa8845.png

你這個regression的estimate就會越來越準。
這個是Bayesian的optimization,這個方法到底work嘛?我有點難告訴你說他是work的,因為這個方法的好壞就取決於你的regression的model做的好不好,而regression的model也是一個假設,也是hyperparameter……
這個regression的model到底合不合理,你也是要憑著直覺設出來,所以這個方法到底好不好久取決於regression的model到底好還是不好。

Reinforcement Learning

剛才是用一個regression的model,也許可以作用更復雜的model,比如說用RNN來決定network的架構,google現在很流行的用machine來learn machine,用network來learn network;所以假設你要train一個CNN,怎麼做?你先train一個神奇的RNN,這個RNN它的output就是數字,它的第一個output就代表第一個layer的filter的高,然後接下來output第一個layer的output的寬,接下來output你的stride是多少,然後output要有幾個filter,這是第一層,然後接下output第二層,然後就一直output下去,把它所有的資料收集起來,你就得到了一個CNN的架構。


5631876-4733d36838e06ef6.png

RNN它的架構是每個時間點的的輸出會被當做下一個時間點的輸入,你使用RNN去sample一排數字你就得到一個CNN,那麼這個RNN怎麼來?是這樣來的,我們得到一個CNN以後你就拿他去你的training set上train一下,然後在驗證集上你就可以得到Accuracy,然後這個Accuracy就是RNN的reward,我們用reinforcement learning的方法來硬train這個RNN,所以我們還沒有講過reinforcement learning,但是它的基本概念你就是調RNN的引數,希望它得到的reward的期望值越大越好。

你用同樣的方法其實也可以設計LSTM的架構,我們之前上課的時候已經講過了,而且這樣的方法可以被視為是一種meta learning了,或者是learn to learn的方法。這邊是設計了CNN跟LSTM的架構,也可以設計啟用函式,那個Swish就是這樣子來的:
你先假設說啟用函式有固定的樣子(即輸入一個值,輸出一個值),今天假設說輸入這個值先把它複製3份,然後前面兩個值通過一個Unary的函式,Unary函式如下圖所示;然後通過一個Binary函式,Binary函式有如圖所示;然後再通過一個Unary函式;然後第三份也通過Unary函式;再在一起通過Binary函式得到最後的output。

5631876-3e0fbb8673ac2347.png

在每一個block裡面Unary函式Binary函式要選什麼呢?把它當做RNN的output,讓RNN告訴你說到底要選哪一個Unary或者是Binary函式。在learn 啟用函式的時候,RNN的output就是有可能的Unary或者是Binary函式,然後接下來你就硬train下去,RNN先產生一個啟用函式,這個啟用函式learn一下得到Accuracy,然後去update一下RNN,再產生新的啟用函式再update,就這樣不斷的迴圈,最後就可以找出一個最好的啟用函式,就是Swish。

在這邊Swish的paper裡面,他們有講說他們找到的最好的八個啟用函式就列舉在這邊,如下圖所示:
5631876-84190a645b00ad68.png

這些的啟用函式有什麼特色?有一個特色是他們好像都有直接使用到input x。然後另外一個特色就是有一些啟用函式,居然是有周期性的,這個也是作者相當自豪的一點,因為正常在設計啟用函式的時候,你絕對不會設計這種啟用函式,舉例來說,像綠色的這樣的一個啟用函式,有一些奇怪的地方,覺得不太make sense:因為你input在這個地方,在這個地方它的output都是一樣的,machine就會分辨不出到底是什麼樣的input,反正用RNN learn出來就是這個樣子,machine超越人,設計出來的啟用函式就是這麼回事,你沒有辦法想象的。

還可以拿來決定學習率,我們知道說學習率有一些決定的strategy,比如說Adam和RMSProp等等,其實這些不同的學習率的strategy,有一個共同的表示是:舉例來說SGD,我們大家都熟知的SGD,代表那個gradient,gradient乘上identity,就是SGD
RMSProp呢?RMSProp是有同樣gradient乘上identity,,但是這邊有一個,是過去的gradient的平方的estimation,就等於是你把過去的gradient的平方和 把它平均起來。 好,把平方和開根號,然後再把除上開根號的結果就是RMSProp。
那麼Adam呢?AdamRMSProp不一樣的地方就是把gradient換成,就是momenton,momenton就是gradient平均,是gradient的平方的estimation,是gradient的estimation,除掉的開根號就得到Adam

5631876-ece55e45d79acb97.png

好,我們怎麼知道說什麼時候要,什麼,什麼時候開根號,什麼時候做什麼?所以怎麼辦?讓machine來決定要怎麼調學習率:

5631876-1409e15a30fd1961.png

這邊一樣learn一個RNN,他的第一個輸出就代表了第一個Operand,那Operand有什麼呢?
5631876-4140048901ea776e.png

,然後再輸出第二個Operand,再輸出第一個Unary函式,這邊有各種Unary函式:
5631876-f5739c21ac07b58d.png

再輸出第二個Unary函式,然後輸出Binary函式,有各種不同Binary函式:
5631876-e207a640bebe1ba0.png

你就可以製造一個新的learning的strategy,新版的Adam,新版的RMSProp,最後得到什麼結果?最後得到一個新的learning的strategy叫做PowerSign,其實他沒有做很完整的實驗,但他的結果看起來疑似可以training得到新的test上,叫它作為reinforcement learning的時候,machine是train在image的test上,但是你learn出來的learning的strategy好像可以apply在其他比如說translation,language model上面,好像也可以得到不錯的結果。

然後他這邊是舉其中一個實驗,這個實驗是在月牙形的loss函式上面,它是一個對gradient descent來說經典的難題,四個經典的方法包括SGD,Momenton,Adam,RMSProp,來發現說SGD,Adam,RMSProp,其實都沒有辦法從開始的地方走到終點這個地方,這三個方法都走不到;Momenton可以走到,那PowerSign跟Momenton一樣強,而且走了一個很崎嶇的路徑但是他最後也走到了。

5631876-b684f93b1c704929.png

而且很好奇,說PowerSign長什麼樣子,它其實也沒有很複雜,它長這樣

5631876-dfc4a669d74f4039.png

。他還蠻單純的,我們把gradient前面乘上
5631876-3ee4a12ddabf437a.png

這次聽起來蠻自覺的,如果gradient跟Momenton同向,e的指數項就是正,那你的gradient就會乘上一個正的值,是一個比較大的學習率,因為如果你今天你的gradient跟Momenton反向,那指數項就是負的,e的指數項就是一個小於1的值,所以你學習率就會減小,所以這個聽起來蠻直觀的。

這些方法雖然聽起來很潮,但是這是好孩子也沒辦法學,你在家裡也沒辦法自己嘗試,你可會想說我現在在做作業2,還有一點點時間,看要不要自己發明一些新的RNN的結構,我看你還是洗洗睡了這樣子,其實你給我看產生SVN的架構paper,他說他用了800張gpu,這個實驗實在是好,還是沒辦法學的一個task。

相關文章