稱霸Kaggle的十大深度學習技巧!
Datawhale賽事
作者:Samuel Lynn-Evans,來源:量子位
是什麼祕訣讓 新手 們在短期內快速掌握並能構建最先進的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庫地址:
http://github.com/fastai/fastai
2. 使用多個而不是單一學習率

差分學習率(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
http://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

同時,記錄每個學習率對應的Loss值,然後畫出學習率和Loss值的關係圖:
learn.sched.plot()
# plots the loss against the learning rate

通過找出學習率最高且Loss值仍在下降的值來確定最佳學習率。在上述情況中,該值將為0.01。
4. 餘弦退火
在採用 批次隨機梯度下降 演算法時,神經網路應該越來越接近Loss值的全域性最小值。當它逐漸接近這個最小值時,學習率應該變得更小來使得模型不會超調且儘可能接近這一點。
餘弦退火(Cosine annealing)利用餘弦函式來 降低學習率 ,進而解決這個問題,如下圖所示:

從上圖可以看出,隨著x的增加,餘弦值首先 緩慢 下降,然後 加速 下降, 再次緩慢 下降。這種下降模式能和學習率配合,以一種十分有效的計算方式來產生很好的效果。
learn.fit(0.1, 1)
# Calling learn fit automatically takes advantage of cosine annealing
我們可以用Fast.ai庫中的**learn.fit()**函式,來快速實現這個演算法,在整個週期中不斷降低學習率,如下圖所示:

同時,在這種方法基礎上,我們可以進一步引入重啟機制。
5. 帶重啟的SGD演算法
在訓練時, 梯度下降 演算法可能陷入區域性最小值,而不是全域性最小值。

梯度下降演算法可以通過 突然提高學習率 ,來“跳出”區域性最小值並找到通向全域性最小值的路徑。這種方式稱為 帶重啟的 隨機梯度下降方法(stochastic gradient descent with restarts, SGDR ),這個方法在Loshchilov和Hutter的ICLR論文中展示出了很好的效果。
這篇論文是:SGDR: Stochastic Gradient Descent with Warm Restarts
http://arxiv.org/abs/1608.03983
用Fast.ai庫可以快速匯入SGDR演算法。當呼叫learn.fit(learning_rate, epochs)函式時,學習率在每個週期開始時重置為引數輸入時的初始值,然後像上面餘弦退火部分描述的那樣,逐漸減小。

每當學習率下降到最小點,在上圖中為每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.

利用這些引數,和使用差分學習率,這些技巧是Fast.ai使用者在影象分類問題上取得良好效果的關鍵。
Fast.ai論壇有個帖子專門討論Cycle_mult和cycle_len函式,地址在這裡:
http://forums.fast.ai/t/understanding-cycle-len-and-cycle-mult/9413/8
更多關於學習率的詳細內容可參考這個Fast.ai課程:
http://course.fast.ai/lessons/lesson2.html
6. 人格化你的啟用函式
Softmax只喜歡選擇一樣東西;
Sigmoid想知道你在[-1, 1]區間上的位置,並不關心你超出這些值後的增加量;
Relu是一名俱樂部保鏢,要將負數拒之門外。
……
以這種思路對待啟用函式,看起來很愚蠢,但是 安排一個角色 後能確保把他們用到正確任務中。
正如fast.ai創始人Jeremy Howard指出,不少學術論文中也把Softmax函式用在多分類問題中。在DL學習過程中,我也看到它在論文和部落格中多次使用不當。
7. 遷移學習在NLP問題中非常有效
正如預訓練好的模型在計算機視覺任務中很有效一樣,已有研究表明,自然語言處理(NLP)模型也可以從這種方法中受益。
在Fast.ai第4課中,Jeremy Howard用遷移學習方法建立了一個模型,來判斷IMDB上的電影評論是積極的還是消極的。
這種方法的效果立竿見影,他所達到的準確率超過了Salesforce論文中展示的所有先前模型:
http://einstein.ai/research/learned-in-translation-contextualized-word-vectors。

這個模型的關鍵在於先訓練模型來獲得對語言的一些理解,然後再使用這種預訓練好的模型作為新模型的一部分來分析情緒。
為了建立第一個模型,我們訓練了一個迴圈神經網路(RNN)來預測文字序列中的下個單詞,這稱為 語言建模 。當訓練後網路的準確率達到一定值,它對每個單詞的編碼模式就會傳遞給用於情感分析的新模型。
在上面的例子中,我們看到這個語言模型與另一個模型整合後用於情感分析,但是這種方法可以應用到 其他任何NLP任務 中,包括 翻譯 和 資料提取 。
而且,計算機視覺中的一些技巧,也同樣適用於此,如上面提到的凍結網路層和使用差分學習率,在這裡也能取得更好的效果。
這種方法在NLP任務上的使用涉及很多細節,這裡就不貼出程式碼了,可訪問相應課程和程式碼。
課程:
http://course.fast.ai/lessons/lesson4.html
程式碼:http://github.com/fastai/fastai/blob/master/courses/dl1/lesson4-imdb.ipynb
8. 深度學習在處理結構化資料上的優勢
Fast.ai課程中展示了深度學習在處理結構化資料上的突出表現,且無需藉助特徵工程以及領域內的特定知識。
這個庫充分利用了PyTorch中 embedding 函式,允許將 分類變數 快速轉換為嵌入矩陣。
他們展示出的技術比較簡單直接,只需將分類變數轉換為數字,然後為每個值分配嵌入向量:

在這類任務上,傳統做法是建立虛擬變數,即進行一次熱編碼。與之相比,這種方式的優點是用四個數值代替一個數值來描述每一天,因此可獲得更高的資料維度和更豐富的關係。
這種方法在Rossman Kaggle比賽中獲得第三名,惜敗於兩位利用專業知識來建立許多額外特徵的領域專家。
相關課程:
http://course.fast.ai/lessons/lesson4.html
程式碼:
http://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:
http://www.cs.toronto.edu/~hinton/absps/JMLRdropout.pdf
然而,PyTorch庫使它的實現變得很簡單,用Fast.ai庫載入它就更容易了。

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. 創新力很關鍵
在DAWNBench比賽中,Fast.ai團隊提出的模型不僅速度最快,而且計算成本低。要明白,要構建成功的DL應用,不只是一個利用大量GPU資源的計算任務,而應該是一個需要創造力、直覺和創新力的問題。
本文中討論的一些突破,包括Dropout層、餘弦退火和帶重啟的SGD方法等,實際上是研究者針對一些問題想到的不同解決方式。與簡單地增大訓練資料集相比,能 更好地提升準確率 。
矽谷的很多大公司有大量GPU資源,但是,不要認為他們的先進效果遙不可及,你也能靠創新力提出一些新思路,來挑戰效果排行榜。
事實上,有時計算力的侷限也是一種機會,因為需求是創新的動力源泉。
關於作者
Samuel Lynn-Evans過去10年一直在教授生命科學課程,注意到機器學習在科學研究中的巨大潛力後,他開始在巴黎42學校學習人工智慧,想將NLP技術應用到生物學和醫學問題中。
原文:http://blog.floydhub.com/ten-techniques-from-fast-ai/
乾貨學習,
點
贊
三連
↓
- 擴散模型爆火!這是首篇綜述
- 費曼:任何偉大的科學成就,都源於思想自由
- 我是如何從頭寫一篇頂級論文的
- 初入科研的幾點心得——以交叉學科為例
- AI拿下藝術大獎,它離文學獎還有多遠?
- 哈佛大學教授:拒絕「調參俠」從學好數學開始!
- 資料探勘入門:從動手實踐開始!
- 超全面! 15 種 Python IDE 工具使用對比
- 資料科學競賽:你從未見過的究極進化祕笈!
- 華為、百度、訊飛!大廠資料競賽最新彙總
- Jina AI 聯合Datawhale,發起學習專案!
- 我寫了一份初學者的學習實踐教程!
- 我們做了一個智慧零售結算平臺
- 最新NLP賽事實踐總結!
- 科大訊飛活躍競賽彙總!(12個)
- 一文讀懂遺傳演算法工作原理(附Python實現)
- 寫程式碼復現論文的幾點建議!
- 發了6篇SCI的師兄告訴我的祕密:科研工具推薦合集!
- 周志華:“資料、演算法、算力” 人工智慧三要素,在未來要加上“知識”!
- 我的機器學習之路!