天天看點

稱霸Kaggle的十大深度學習技巧

在各種Kaggle競賽的排行榜上,都有不少剛剛進入深度學習領域的程式員,其中大部分有一個共同點:

都上過Fast.ai的課程。

這些免費、重實戰的課程非常鼓勵學生去參加Kaggle競賽,檢驗自己的能力。當然,也向學生們傳授了不少稱霸Kaggle的深度學習技巧。

是什麼秘訣讓新手們在短期内快速掌握并能建構最先進的DL算法?一位名叫塞缪爾(Samuel Lynn-Evans)的法國學員總結了十條經驗。

他這篇文章發表在FloydHub官方部落格上,因為除了來自Fast.ai的技巧之外,他還用了FloydHub的免設定深度學習GPU雲平台。

接下來,我們看看他從fast.ai學來的十大技藝:

1.使用Fast.ai庫

這一條最為簡單直接。

from fast.ai import *

Fast.ai庫是一個新手友好型的深度學習工具箱,而且是目前複現最新算法的首要之選。

每當Fast.ai團隊及AI研究者發現一篇有趣論文時,會在各種資料集上進行測試,并确定合适的調優方法。他們會把效果較好的模型實作加入到這個函數庫中,使用者可以快速載入這些模型。

于是,Fast.ai庫成了一個功能強大的工具箱,能夠快速載入一些目前最新的算法實作,如帶重新開機的随機梯度下降算法、差分學習率和測試時增強等等,這裡不逐一提及了。

下面會分别介紹這些技術,并展示如何使用Fast.ai庫來快速使用它們。

這個函數庫是基于PyTorch建構,構模組化型時可以流暢地使用。

Fast.ai庫位址:

https://github.com/fastai/fastai 2.使用多個而不是單一學習率
稱霸Kaggle的十大深度學習技巧

差分學習率(Differential Learning rates)意味着在訓練時變換網絡層比提高網絡深度更重要。

基于已有模型來訓練深度學習網絡,這是一種被驗證過很可靠的方法,可以在計算機視覺任務中得到更好的效果。

大部分已有網絡(如Resnet、VGG和Inception等)都是在ImageNet資料集訓練的,是以我們要根據所用資料集與ImageNet圖像的相似性,來适當改變網絡權重。

在修改這些權重時,我們通常要對模型的最後幾層進行修改,因為這些層被用于檢測基本特征(如邊緣和輪廓),不同資料集有着不同基本特征。

首先,要使用Fast.ai庫來獲得預訓練的模型,代碼如下:

from fastai.conv_learner import *

# import library for creating learning object for convolutional #networks
model = VVG16()

# assign model to resnet, vgg, or even your own custom model
PATH = './folder_containing_images' 
data = ImageClassifierData.from_paths(PATH)

# create fast ai data object, in this method we use from_paths where 
# inside PATH each image class is separated into different folders

learn = ConvLearner.pretrained(model, data, precompute=True)

# create a learn object to quickly utilise state of the art
# techniques from the fast ai library
           

建立學習對象之後(learn object),通過快速當機前面網絡層并微調後面網絡層來解決問題:

learn.freeze()

# freeze layers up to the last one, so weights will not be updated.

learning_rate = 0.1
learn.fit(learning_rate, epochs=3)

# train only the last layer for a few epochs
           

當後面網絡層産生了良好效果,我們會應用差分學習率來改變前面網絡層。在實際中,一般将學習率的縮小倍數設定為10倍:

learn.unfreeze()

# set requires_grads to be True for all layers, so they can be updated

learning_rate = [0.001, 0.01, 0.1]
# learning rate is set so that deepest third of layers have a rate of 0.001, # middle layers have a rate of 0.01, and final layers 0.1.

learn.fit(learning_rate, epochs=3)
# train model for three epoch with using differential learning rates
           

3.如何找到合适的學習率

學習率是神經網絡訓練中最重要的超參數,沒有之一,但之前在實際應用中很難為神經網絡選擇最佳的學習率。

Leslie Smith的一篇周期性學習率論文發現了答案,這是一個相對不知名的發現,直到它被Fast.ai課程推廣後才逐漸被廣泛使用。

這篇論文是:

Cyclical Learning Rates for Training Neural Networks

https://arxiv.org/abs/1506.01186

在這種方法中,我們嘗試使用較低學習率來訓練神經網絡,但是在每個批次中以指數形式增加,相應代碼如下:

learn.lr_find()
# run on learn object where learning rate is increased  exponentially

learn.sched.plot_lr()
# plot graph of learning rate against iterations
           
稱霸Kaggle的十大深度學習技巧

同時,記錄每個學習率對應的Loss值,然後畫出學習率和Loss值的關系圖:

learn.sched.plot()
# plots the loss against the learning rate
           
稱霸Kaggle的十大深度學習技巧

通過找出學習率最高且Loss值仍在下降的值來确定最佳學習率。在上述情況中,該值将為0.01。

4.餘弦退火

在采用批次随機梯度下降算法時,神經網絡應該越來越接近Loss值的全局最小值。當它逐漸接近這個最小值時,學習率應該變得更小來使得模型不會超調且盡可能接近這一點。

餘弦退火(Cosine annealing)利用餘弦函數來降低學習率,進而解決這個問題,如下圖所示:

稱霸Kaggle的十大深度學習技巧

從上圖可以看出,随着x的增加,餘弦值首先緩慢下降,然後加速下降,再次緩慢下降。這種下降模式能和學習率配合,以一種十分有效的計算方式來産生很好的效果。

learn.fit(0.1, 1)
# Calling learn fit automatically takes advantage of cosine annealing
           

我們可以用Fast.ai庫中的learn.fit()函數,來快速實作這個算法,在整個周期中不斷降低學習率,如下圖所示:

稱霸Kaggle的十大深度學習技巧

同時,在這種方法基礎上,我們可以進一步引入重新開機機制。

5.帶重新開機的SGD算法

在訓練時,梯度下降算法可能陷入局部最小值,而不是全局最小值。

稱霸Kaggle的十大深度學習技巧

梯度下降算法可以通過突然提高學習率,來“跳出”局部最小值并找到通向全局最小值的路徑。這種方式稱為帶重新開機的随機梯度下降方法(stochastic gradient descent with restarts, SGDR),這個方法在Loshchilov和Hutter的ICLR論文中展示出了很好的效果。

SGDR: Stochastic Gradient Descent with Warm Restarts

https://arxiv.org/abs/1608.03983

用Fast.ai庫可以快速導入SGDR算法。當調用learn.fit(learning_rate, epochs)函數時,學習率在每個周期開始時重置為參數輸入時的初始值,然後像上面餘弦退火部分描述的那樣,逐漸減小。

稱霸Kaggle的十大深度學習技巧

每當學習率下降到最小點,在上圖中為每100次疊代,我們稱為一個循環。

cycle_len = 1
# decide how many epochs it takes for the learning rate to fall to
# its minimum point. In this case, 1 epoch

cycle_mult=2
# at the end of each cycle, multiply the cycle_len value by 2

learn.fit(0.1, 3, cycle_len=2, cycle_mult=2)
# in this case there will be three restarts. The first time with
# cycle_len of 1, so it will take 1 epoch to complete the cycle.
# cycle_mult=2 so the next cycle with have a length of two epochs, 
# and the next four.
           
稱霸Kaggle的十大深度學習技巧

利用這些參數,和使用差分學習率,這些技巧是Fast.ai使用者在圖像分類問題上取得良好效果的關鍵。

6.人格化你的激活函數

Softmax隻喜歡選擇一樣東西;

Sigmoid想知道你在[-1, 1]區間上的位置,并不關心你超出這些值後的增加量;

Relu是一名俱樂部保镖,要将負數拒之門外。

……

以這種思路對待激活函數,看起來很愚蠢,但是安排一個角色後能確定把他們用到正确任務中。

正如fast.ai創始人Jeremy Howard指出,不少學術論文中也把Softmax函數用在多分類問題中。在DL學習過程中,我也看到它在論文和部落格中多次使用不當。

7.遷移學習在NLP問題中非常有效

正如預訓練好的模型在計算機視覺任務中很有效一樣,已有研究表明,自然語言處理(NLP)模型也可以從這種方法中受益。

在Fast.ai第4課中,Jeremy Howard用遷移學習方法建立了一個模型,來判斷IMDB上的電影評論是積極的還是消極的。

這種方法的效果立竿見影,他所達到的準确率超過了Salesforce論文中展示的所有先前模型。

稱霸Kaggle的十大深度學習技巧

這個模型的關鍵在于先訓練模型來獲得對語言的一些了解,然後再使用這種預訓練好的模型作為新模型的一部分來分析情緒。

為了建立第一個模型,我們訓練了一個循環神經網絡(RNN)來預測文本序列中的下個單詞,這稱為語言模組化。當訓練後網絡的準确率達到一定值,它對每個單詞的編碼模式就會傳遞給用于情感分析的新模型。

在上面的例子中,我們看到這個語言模型與另一個模型內建後用于情感分析,但是這種方法可以應用到其他任何NLP任務中,包括翻譯和資料提取。

而且,計算機視覺中的一些技巧,也同樣适用于此,如上面提到的當機網絡層和使用差分學習率,在這裡也能取得更好的效果。

這種方法在NLP任務上的使用涉及很多細節,這裡就不貼出代碼了,可通路相應課程和代碼。

代碼:

https://github.com/fastai/fastai/blob/master/courses/dl1/lesson4-imdb.ipynb

8.深度學習在處理結構化資料上的優勢

Fast.ai課程中展示了深度學習在處理結構化資料上的突出表現,且無需借助特征工程以及領域内的特定知識。

這個庫充分利用了PyTorch中embedding函數,允許将分類變量快速轉換為嵌入矩陣。

他們展示出的技術比較簡單直接,隻需将分類變量轉換為數字,然後為每個值配置設定嵌入向量:

稱霸Kaggle的十大深度學習技巧

在這類任務上,傳統做法是建立虛拟變量,即進行一次熱編碼。與之相比,這種方式的優點是用四個數值代替一個數值來描述每一天,是以可獲得更高的資料次元和更豐富的關系。

這種方法在Rossman Kaggle比賽中獲得第三名,惜敗于兩位利用專業知識來建立許多額外特征的領域專家。

https://github.com/fastai/fastai/blob/master/courses/dl1/lesson3-rossman.ipynb

這種用深度學習來減少對特征工程依賴的思路,也被Pinterest證明過。他也提到過,他們正努力通過深度學習模型,期望用更少的工作量來獲得更好的效果。

9.更多内置函數:Dropout層、尺寸設定、TTA

4月30日,Fast.ai團隊在斯坦福大學舉辦的DAWNBench競賽中,赢得了基于Imagenet和CIFAR10的分類任務。在Jeremy的奪冠總結中,他将這次成功歸功于fast.ai庫中的一些額外函數。

其中之一是Dropout層,由Geoffrey Hinton兩年前在一篇開創性的論文中提出。它最初很受歡迎,但在最近的計算機視覺論文中似乎有所忽略。這篇論文是:

Dropout: A Simple Way to Prevent Neural Networks from Overfitting:

https://www.cs.toronto.edu/~hinton/absps/JMLRdropout.pdf

然而,PyTorch庫使它的實作變得很簡單,用Fast.ai庫加載它就更容易了。

稱霸Kaggle的十大深度學習技巧

Dropout函數能減弱過拟合效應,是以要在CIFAR-10這樣一個相對較小的資料集上取勝,這點很重要。在建立learn對象時,Fast.ai庫會自動加入dropout函數,同時可使用ps變量來修改參數,如下所示:

learn = ConvLearner.pretrained(model, data, ps=0.5, precompute=True)
# creates a dropout of 0.5 (i.e. half the activations) on test dataset. 
# This is automatically turned off for the validation set
           

有一種很簡單有效的方法,經常用來處理過拟合效應和提高準确性,它就是訓練小尺寸圖像,然後增大尺寸并再次訓練相同模型。

# create a data object with images of sz * sz pixels 
def get_data(sz): 
    tmfs = tfms_from_model(model, sz)
    # tells what size images should be, additional transformations such
    # image flips and zooms can easily be added here too

    data = ImageClassifierData.from_paths(PATH, tfms=tfms)
    # creates fastai data object of create size

    return data

learn.set_data(get_data(299))
# changes the data in the learn object to be images of size 299
# without changing the model.

learn.fit(0.1, 3)
# train for a few epochs on larger versions of images, avoiding overfitting
           

還有一種先進技巧,可将準确率提高若幹個百分點,它就是測試時增強(test time augmentation, TTA)。這裡會為原始圖像造出多個不同版本,包括不同區域裁剪和更改縮放程度等,并将它們輸入到模型中;然後對多個版本進行計算得到平均輸出,作為圖像的最終輸出分數,可調用learn.TTA()來使用該算法。

preds, target = learn.TTA()
           

這種技術很有效,因為原始圖像顯示的區域可能會缺少一些重要特征,在模型中輸入圖像的多個版本并取平均值,能解決上述問題。

10.創新力很關鍵

稱霸Kaggle的十大深度學習技巧

在DAWNBench比賽中,Fast.ai團隊提出的模型不僅速度最快,而且計算成本低。要明白,要建構成功的DL應用,不隻是一個利用大量GPU資源的計算任務,而應該是一個需要創造力、直覺和創新力的問題。

本文中讨論的一些突破,包括Dropout層、餘弦退火和帶重新開機的SGD方法等,實際上是研究者針對一些問題想到的不同解決方式。與簡單地增大訓練資料集相比,能更好地提升準确率。

矽谷的很多大公司有大量GPU資源,但是,不要認為他們的先進效果遙不可及,你也能靠創新力提出一些新思路,來挑戰效果排行榜。

事實上,有時計算力的局限也是一種機會,因為需求是創新的動力源泉。

原文釋出時間為:2018-08-07

本文作者:Samuel Lynn-Evans

本文來自雲栖社群合作夥伴“

機器學習算法與Python學習

”,了解相關資訊可以關注“