1. 訓練數(shù)據(jù)
許多 ML 開發(fā)者習慣把原始訓練數(shù)據(jù)直接扔給 DNN——為什么不這么做呢?既然任何 DNN (大多數(shù)人的假設(shè))仍然能夠給出不錯的結(jié)果,不是嗎?但是,有句老話叫“給定恰當?shù)臄?shù)據(jù)類型,一個簡單的模型能比復雜 DNN 提供更好、更快的結(jié)果”。雖然這有一些例外,但在今天,這句話仍然沒有過時。因此,不管你是在計算機視覺( CV),自然語言處理(NLP)還是統(tǒng)計建模(Statistical Modelling)等領(lǐng)域,想要對原始數(shù)據(jù)預處理,有幾個方法可以得到更好的訓練數(shù)據(jù):
獲取越大的數(shù)據(jù)庫越好。DNN 對數(shù)據(jù)很饑渴,越多越好。
去除所有包含損壞數(shù)據(jù)的訓練樣本,比如短文字,高度扭曲的圖像,假輸出標簽,包含許多虛值(null values)的屬性。
Data Augmentation(數(shù)據(jù)擴張)——生成新樣例。以圖像為例,重新調(diào)節(jié),增加噪聲等等。
2. 選擇恰當?shù)募詈瘮?shù)(activation function)
激勵函數(shù)是所有神經(jīng)網(wǎng)絡(luò)的核心部分之一。
激勵函數(shù)把渴望已久的非線性(non-linearity)加入了模型。多年來,Sigmoid 函數(shù) 一直是多數(shù)人傾向的選擇。但是,Sigmoid 函數(shù)不可避免地存在兩個缺陷:1. 尾部 ?sigmoids 的飽和,進一步導致梯度消失。2. 不以 0 為中心(輸出在 0 到 1 之間)。
一個更好的替代選擇是 Tanh 函數(shù)。數(shù)學上來說,Tanh 只是調(diào)整、平移過的 Sigmoid 函數(shù):tanh(x) = 2*sigmoid(x) - 1。雖然 Tanh 仍舊存在梯度消失的缺陷,但好消息是:Tanh 以 0 為中心。因此,把 Tanh 作為激勵函數(shù)能更快地收斂(converge)。我發(fā)現(xiàn)使用 Tanh 通常比 Sigmoid 效果更好。
你還可以探索其他選擇,比如 ReLU, SoftSign 等等。對于一些特定任務(wù), 它們能夠改善上述問題。
3. 隱藏單元和隱層(Hidden Units and Layers)的數(shù)量
保留超出最優(yōu)數(shù)量的隱藏單元,一般是比較保險的做法。這是因為任何正則化方法( regularization method)都會處理好超出的單元,至少在某種程度上是這樣。在另一方面,保留比最優(yōu)數(shù)量更少的隱藏單元,會導致更高的模型欠擬合(underfitting)幾率。
另外,當采用無監(jiān)督預訓練的表示時(unsupervised pre-trained representations,下文會做進一步解釋),隱藏單元的最優(yōu)數(shù)目一般會變得更大。因此,預訓練的表示可能會包含許多不相關(guān)信息(對于特定任務(wù))。通過增加隱藏單元的數(shù)目,模型會得到所需的靈活性,以在預訓練表示中過濾出最合適的信息。
選擇隱層的最優(yōu)數(shù)目比較直接。正如 Yoshua Bengio 在 ?Quora 中提到的:
“你只需不停增加層,直到測試誤差不再減少。”
4. 權(quán)重初始化 (Weight Initialization)
永遠用小的隨機數(shù)字初始化權(quán)重,以打破不同單元間的對稱性(symmetry)。但權(quán)重應該是多小呢?推薦的上限是多少?用什么概率分布產(chǎn)生隨機數(shù)字?
當使用 Sigmoid 激勵函數(shù)時,如果權(quán)重初始化為很大的數(shù)字,那么 sigmoid 會飽和(尾部區(qū)域),導致死神經(jīng)元(dead neurons)。如果權(quán)重特別小,梯度也會很小。因此,最好是在中間區(qū)域選擇權(quán)重,比如說那些圍繞平均值均衡分布的數(shù)值。
幸運的是,已經(jīng)有許多關(guān)于初始權(quán)重合適取值的研究。這對于高效的收斂非常重要。為初始化均衡分布的權(quán)重,均勻分布(uniform distribution )或許是最好的選擇之一。另外,就像論文中所展示的(Glorot and Bengio, 2010),有更多輸入連接(fan_in)的單位,應該有相對更小的權(quán)重。
多虧這些十分透徹的試驗,現(xiàn)在我們已經(jīng)有了經(jīng)過檢驗的公式,可以直接用來權(quán)重的初始化。
比如說在 ?~ Uniform(-r, r) 提取的權(quán)重,對于 tanh 激勵 ?r=sqrt(6/(fan_in+fan_out));對于 sigmoid 激勵 r=4*(sqrt(6/fan_in+fan_out)) 。fan_in 是上一層的大小, 而 fan_out 是下一層的。
5. 學習率
這或許是最重要的超參數(shù)之一,調(diào)節(jié)著學習過程。如果學習率設(shè)置得太小,你的模型很可能需要 n 年來收斂。設(shè)置得太大,再加上不多的初始訓練樣本,你的損失可能會極高。一般來說,0.01 的學習率比較保險。但AI科技評論提醒各位讀者,這不是一個嚴格的標準。最優(yōu)學習率與特定任務(wù)的屬性息息相關(guān)。
相比固定學習率,在每個周期、或每幾千個樣例后逐漸降低學習率是另一個選擇。雖然這能更快地訓練,但需要人工決定新的學習率。一般來說,學習率可以在每個周期后減半。幾年前,這種策略十分普遍。
幸運的是,我們現(xiàn)在有了更好的、基于動能(momentum based)的方法,來調(diào)整學習率。這取決于誤差函數(shù)的曲率。另外,既然有些參數(shù)有更快、或更慢的學習速率;它或許能幫助我們針對模型中的單獨參數(shù),設(shè)定不同的學習率。
最近有大量關(guān)于優(yōu)化方法的研究,導致了自適應學習率(adaptive learning rates)。目前我們有許多選擇,從老式動能方法( Momentum Method ),到 ?Adagrad、Adam (個人最愛)、 RMSProp 等等。;類似于 Adagrad 或 Adam 的方法,能替我們省去人工選擇初始學習率的麻煩;給定合適的時間,模型會開始平滑地收斂。當然,選擇一個特別合適的初始學習率仍然能起到幫助作用。
6. 超參數(shù)調(diào)參:扔掉網(wǎng)格搜索,擁抱隨機搜索
網(wǎng)格搜索(Grid Search )在經(jīng)典機器學習中十分普遍。但它在尋找 DNN 的最優(yōu)超參數(shù)方面一點也不高效。這主要是由于 DNN 嘗試不同超參數(shù)組合所耗費的時間。隨著超參數(shù)不斷增長,網(wǎng)格搜索需要的計算性能會指數(shù)級增長。
有兩種解決辦法:
1. 取決于你之前的經(jīng)驗,你可以人工對部分常見超參數(shù)調(diào)參,比如學習率、隱層數(shù)目。
2. 采用隨機搜索(random search),或者隨機采樣代替網(wǎng)格搜索,來選擇最優(yōu)超參數(shù)。
超參數(shù)組合通常在期望范圍之內(nèi)、從均勻分布中被選擇出來。加入之前獲得的知識來進一步縮小搜尋空間,也是有可能的(比如,學習率不應該太大也不應該太小)。大家發(fā)現(xiàn),隨機搜索比網(wǎng)格搜索高效地多。
7. 學習方法
隨機梯度下降( Stochastic Gradient Descent )的老方法也許對于 DNN 不是那么有效率(有例外)。最近,有許多研究聚焦于開發(fā)更靈活的優(yōu)化算法,比如 Adagrad、Adam,、AdaDelta,、RMSProp 等等。在提供自適應學習率之外,這些復雜的方法還對于模型的不同參數(shù)使用不同的學習率,通常能有更平滑的收斂。把這些當做超參數(shù)是件好事,你應該每次都在訓練數(shù)據(jù)的子集上試試它們。
8. 權(quán)重的維度保持為 2 的冪
即便是運行最先進的深度學習模型,使用最新、最強大的計算硬件,內(nèi)存管理仍然在字節(jié)(byte)級別上進行。所以,把參數(shù)保持在 64, 128, 512, 1024 等 2 的次方永遠是件好事。這也許能幫助分割矩陣和權(quán)重,導致學習效率的提升。當用 GPU 運算,這變得更明顯。
9. 無監(jiān)督預訓練(Unsupervised Pretraining )
不管你進行的是 NLP(自然語言處理)、計算機視覺還是語音識別等任務(wù),無監(jiān)督預訓練永遠能幫助你訓練監(jiān)督、或其他無監(jiān)督模型:NLP 中詞向量就(Word Vectors)無所不在;你可以用 ImageNet 的數(shù)據(jù)庫,使用無監(jiān)督方式對你的模型預訓練,或是對于兩個類別的監(jiān)督分類;或是更大頻域的音頻樣本,來在揚聲器消崎模型(speaker disambiguation model)中使用該信息。
10. Mini-Batch(小批量) 對比隨機學習(Stochastic Learning)
訓練一個模型的主要目的是學習合適的參數(shù),即產(chǎn)生輸入到輸出的最優(yōu)映射。這些參數(shù)利用每個訓練樣本進行調(diào)參,不管你決定使用 batch, mini-batch 還是隨機學習。當采用隨機學習方法時,學習每個訓練樣本后權(quán)重的梯度都會進行調(diào)參,向梯度加入噪音(隨機學習中“隨機”的由來)。這樣做的結(jié)果十分理想,比如說,訓練中加入的噪音使得模型更不容易過擬合。
但是,隨機學習方法也許效率不高。如今的計算設(shè)備有非常可觀的運算能力,隨機學習很可能會浪費其中的一大部分。如果我們能計算矩陣相乘,那么為什么要限制自己,重復單個矢量組之間的乘法呢?因此,為了更高的吞吐率和更快的學習,我推薦使用 mini-batch 而不是隨機學習。
但是,選擇適當?shù)?batch 規(guī)模同樣重要。所以我們能保留一些噪音(相比大規(guī)模 batch),與此同時更高效地利用計算性能。一般來說,包含 ?16 個到 128 個樣例的 batch(2 的冪)是不錯的選擇。通常,一旦你發(fā)現(xiàn)了更重要的超參數(shù)(通過隨機搜索或是人工搜索),batch 規(guī)模就會確性下來。但是,有些場景中模型得到訓練數(shù)據(jù)流(比如網(wǎng)絡(luò)學習),那么采用隨機學習就是不錯的選擇。
11. 打亂訓練樣本
這來自于信息理論(Information Theory)——“學習到一件不太可能發(fā)生的事卻發(fā)生了,比學習一件很可能發(fā)生的事已經(jīng)發(fā)生,包含更多的信息。”同樣的,把訓練樣例的順序隨機化(在不同周期,或者 mini-batch),會導致更快的收斂。如果模型看到的很多樣例不在同一種順序下,運算速度會有小幅提升。
12. 使用 Dropout 正則化
如果有數(shù)百萬的參數(shù)需要學習,正則化就是避免 DNN 過擬合的必須手段。你也可以繼續(xù)使用 L1/L2 正則化,但 Dropout 是檢查 DNN 過擬合的更好方式(AI科技評論按:Dropout 是指隨機讓網(wǎng)絡(luò)某些隱層節(jié)點的權(quán)重不工作,不工作的那些節(jié)點可以暫時認為不是網(wǎng)絡(luò)結(jié)構(gòu)的一部分,但是它的權(quán)重會保留下來)。執(zhí)行 Dropout 很容易,并且通常能帶來更快地學習。0.5 的默認值是一個不錯的選擇,當然,這取決于具體任務(wù)。如果模型不太復雜,0.2 的 Dropout 值或許就夠了。
在測試階段,Dropout 應該被關(guān)閉,權(quán)重要調(diào)整到相應大小。只要對一個模型進行 Dropout 正則化,多一點訓練時間,誤差一定會降低。
13. 周期 / 訓練迭代次數(shù)
“對深度學習模型進行多個周期的訓練,會得到更好的模型”——我們經(jīng)常聽到這句話。但多少周期才是“多”呢?其實,這里有一個簡單的策略:繼續(xù)按照一個固定的樣例數(shù)或者周期訓練模型,比如兩萬個樣例或者一個周期。在每批樣例之后,比較測試誤差(test error)和訓練誤差(train error),如果它們的差距在縮小,那么繼續(xù)訓練。另外,記得在每批訓練之后,保存模型的參數(shù),所以訓練好之后你可以從多個模型中做選擇。
14. 可視化
訓練深度學習模型有上千種出差錯的方式。我猜大家都遇到過這樣的場景:模型已經(jīng)訓練了幾個小時或者好幾天,然而在訓練完成之后,才意識到某個地方出問題了。為了不讓你自己神經(jīng)錯亂,一定要對訓練過程作可視化處理。比較顯而易見的措施是保存或打印損失值、訓練誤差、測試誤差等項目的日志。
在此之外,一個很好的措施是采用可視化庫(visualization library ),在幾個訓練樣例之后、或者周期之間,生成權(quán)重柱狀圖。這或許能幫助我們追蹤深度學習模型中的一些常見問題,比如梯度消失與梯度爆發(fā)(Exploding Gradient)。
15. 使用支持 GPU 和自動微分法 (Automatic Differentiation)的庫
謝天謝地,對于快速創(chuàng)建原型模型,我們已經(jīng)有了相當不錯的庫,比如 Theano, Tensorflow, Keras 等等。幾乎所有這些深度學習庫支持 GPU 計算和自動微分法。所以,你不需要深入研究核心 GPU 編程技術(shù)(除非你想——這絕對很有意思)。你也不需要寫自己的微分代碼——在非常復雜的模型上這相當費勁(但若需要,你應該有能力去做)。 Tensorflow還提供了分布式計算的支持——如果你是土豪的話。