1. 程式人生 > >【深度學習】從fast.ai學到的十大技巧

【深度學習】從fast.ai學到的十大技巧

那些允許新手在短短几周內實施世界級演算法的祕訣是什麼呢?在GPU驅動的喚醒中留下經驗豐富的深度學習從業者?請允許我用十個簡單的步驟告訴你。

如果您已經在練習深度學習並希望快速瞭解fast.ai在課程中使用的強大技術,請繼續閱讀。如果你已經完成了fast.ai並想要回顧一下你應該學到的東西,請繼續閱讀。如果你正在調查研究深度學習的想法,請繼續閱讀,並希望看到該領域如何發展以及fast.ai可以為初學者提供什麼。

現在,在我們開始之前,您應該知道您需要訪問GPU才能有效地執行fast.ai內容。對於我的fast.ai專案,我一直在使用FloydHub。經過對其他基於雲的解決方案的大量實驗和研究,我發現FloydHub是在雲GPU上訓練深度學習模型的最佳和最簡單的方法。我喜歡能夠在FloydHub 上的

專案中輕鬆跟蹤我的實驗,使得視覺化和過濾哪些模型的效能最佳。他們還擁有最簡單的解決方案來管理(並自動版本化)您的資料集,您將學習在任何DL專案中將會非常有價值。

好的,讓我們開始吧。

1.使用Fast.ai庫

from fast.ai import *

fast.ai庫不僅是讓新手快速實施深度學習的工具包,而且是當前最佳實踐的強大而便捷的源。每當fast.ai團隊(以及他們的AI研究人員和合作者網路)發現一篇特別有趣的論文時,他們就會在各種資料集上進行測試,並找出如何調整它的方法。如果它們成功,它將在庫中實現,並且使用者可以快速訪問該技術。

結果是一個功能強大的工具箱,包括快速訪問最佳實踐,例如隨機梯度下降與重啟,差分學習率和測試時間增加(更不用說更多)。

下面將介紹這些技術中的每一種,我們將展示如何使用fast.ai庫快速實現它們。該庫是基於PyTorch構建的,您可以非常流暢地使用它們。要開始使用FloydHub上的庫,請檢視他們的2分鐘安裝

2.不要使用一個學習率,使用多個

差異學習率意味著在訓練期間更高層的變化比更深層更多。在預先存在的架構之上構建深度學習模型是一種經過驗證的方法,可以在計算機視覺任務中產生更好的結果。
大多數這些架構(即Resnet,VGG,初始......)都是在ImageNet上進行培訓的,並且根據資料與ImageNet上影象的相似性,這些權重需要或多或少地大幅改變。在修改這些權重時,模型的最後幾層通常需要進行最大的變化,而已經訓練有素且檢測基本特徵(例如邊緣和輪廓)的更深層次需要更少。

首先,要使用快速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.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.如何找到合適的學習率

學習率是訓練神經網路最重要的超引數,但直到最近才決定它的價值令人難以置信的hacky。萊斯利史密斯可能在其關於週期性學習率的論文中偶然發現了答案; 一個相對未知的發現,直到它被fast.ai課程推廣。

在這種方法中,我們進行試執行並使用較低的學習率訓練神經網路,但每批次都會以指數方式增加神經網路。這可以使用以下程式碼完成:

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

learn.sched.plot_lr()
# plot graph of learning rate against iterations

每次迭代,學習率都呈指數增長

同時,記錄學習率的每個值的損失。然後我們根據學習率繪製損失:

learn.sched.plot()
# plots the loss against the learning rate

找出損失仍在減少的地方,但尚未達到穩定水平。

通過找到學習率最高且損失仍在下降的值來確定最佳學習率,在上述情況下,該值將為0.01。

4.餘弦退火

隨著每批隨機梯度下降(SGD),您的網路應該越來越接近損失的全域性最小值。因為它越來越接近這個最小值,因此學習率應該變得更小以使你的演算法不會超調,而是儘可能接近這一點。餘弦退火通過降低餘弦函式後的學習率來解決這個問題,如下圖所示。

隨著我們增加x,我們看到餘弦(x)在這個波浪形狀之後減少。

看看上面的圖,我們看到隨著我們增加x,餘弦值首先緩慢下降,然後更快,然後再稍微慢一些。這種降低模式與學習速率很好地協作,以計算有效的方式產生很好的結果。

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

該技術在使用時由快速ai庫自動實現learn.fit()。上面的程式碼將使我們的學習率在整個時期內降低,如下圖所示。

學習率在一個需要200次迭代的時期內降低

但是,我們可以比這更進一步,並引入重啟。

5.重啟後的隨機梯度下降

在訓練期間,梯度下降可能會陷入區域性最小值而不是全域性最小值。

梯度下降可能會陷入區域性最小值

通過突然提高學習率,梯度下降可以“跳出”區域性最小值並找到通向全域性最小值的方式。這樣做被稱為帶重啟的隨機梯度下降(SGDR),這一想法在Loshchilov和Hutter的論文中表現得非常有效。

快速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.

每個週期需要兩倍於上一週期完成的時期

使用這些引數以及使用差異學習速率是允許快速ai使用者在影象分類問題上表現良好的關鍵技術。

Cycle_multcycle_len進行了討論這裡的fast.ai論壇,而上述關於學習率可以發現,概念更全面地解釋這個快速AI教訓這個部落格帖子

6. Anthropomorphise你的啟用功能

Softmax喜歡挑選一件事。Sigmoid想知道你在-1和1之間的位置,超出這些值並不關心你增加了多少。Relu是一名俱樂部保鏢,他不會讓負數通過門。

以這種方式處理啟用函式似乎很愚蠢,但給它們一個字元可以確保不將它們用於錯誤的任務。正如傑里米·霍華德所指出的那樣,即使是學術論文也經常使用softmax進行多類分類,而且在我研究DL的短暫時間裡,我也已經看到它在部落格和論文中使用不當。

7.轉學在NLP中非常有效

正如使用預先訓練的模型已被證明在計算機視覺中非常有效一樣,越來越清楚的是,自然語言處理(NLP)模型可以從這樣做中受益。

在fast.ai 的第4課中,傑里米·霍華德建立了一個模型,以確定IMDB評論是使用轉移學習是積極的還是消極的。立即觀察到這種技術的力量,他所達到的精確度超過了Bradbury等人論文中提出的所有先前的努力。

預先存在的架構提供最先進的NLP結果。

成功的祕訣在於首先訓練模型以獲得對語言的一些理解,然後再使用這種預先訓練的模型作為模型的一部分來分析情緒。

為了建立第一模型,訓練遞迴神經網路(RNN)以預測文字序列中的下一個單詞。這稱為語言建模。一旦網路經過高度準確的訓練,其對每個單詞的編碼就會傳遞給用於情感分析的新模型。

在該示例中,我們看到該語言模型與模型整合以執行情感分析,但是該相同方法可以用於從翻譯到資料提取的任何NLP任務。

再次,計算機視覺中的上述原則同樣適用於此,凍結和使用差異學習率可以產生更好的結果。

NLP這種方法的實現對我來說太詳細了,無法在這篇文章中分享程式碼,但是如果你有興趣在這裡觀看課程並在這裡訪問程式碼。

8.深度學習可以挑戰ML處理結構化資料

Fast.ai展示了在結構化資料上快速生成出色結果的技術,無需藉助特徵工程或應用領域特定知識。

他們的庫充分利用了PyTorch的嵌入功能,允許將分類變數快速轉換為嵌入矩陣。

他們展示的技術相對簡單,只需將分類變數轉換為數字,然後為每個值分配嵌入向量:

一週中的每一天都嵌入了四個值。

與建立虛擬變數(即執行一個熱編碼)的傳統方法相比,這樣做的好處是每天可以用四個數字代替一個數字,因此我們獲得更高的維度和更豐富的關係。

本課程中顯示的實現(此處的程式碼)在Rossman Kaggle比賽中獲得第三名,只有擁有自己的程式碼才能建立許多額外功能的領域專家才能擊敗。

Pinterest也證實了使用深度學習大大減少對特徵工程的需求的想法,他們已經說過這種情況,因為他們轉向深度學習模型,以更少的工作獲得最先進的結果!

9.一個遊戲獲勝的捆綁:建立規模,輟學和TTA

4月30日,fast.ai團隊在Imagenet和CIFAR10分類上贏得了DAWNBench競賽(由斯坦福大學運營)。在Jeremy的勝利寫作中,他將自己的成功歸功於fast.ai圖書館中的一些額外功能。

其中之一是兩年前Geoffrey Hinton在這篇開創性論文中提出的Dropout概念。儘管它最初受歡迎,但在最近的計算機視覺論文中似乎有所忽略。然而,PyTorch使其實現變得異常簡單,並且在快速的ai上它比以往更容易。

空格表示由退出功能敲除的啟用。

Dropout對抗過度擬合,因此在CIFAR10這樣一個相對較小的資料集上獲勝是非常重要的。 在建立學習物件時,快速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

有關Dropout的更多資訊,請參閱此視訊(從4:57開始)。

他們用於解決過度擬合和提高準確性的另一種非常簡單有效的方法是對較小的影象尺寸進行訓練,然後再增加尺寸並再次訓練相同的模型。

# 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

可以將精度提高一個或兩個的最終技術是測試時間增加(TTA)。這涉及拍攝原始影象的一系列不同版本(例如裁剪不同區域,或更改縮放)並將其傳遞通過模型。然後計算不同版本的平均輸出,並將其作為影象的最終輸出分數。它可以通過執行來呼叫learn.TTA()

preds, target = learn.TTA()

這種技術很有效,因為影象的原始裁剪可能會錯過一個重要的特徵。為模型提供圖片的多個版本並取平均值會降低這種效果。

10.創造力是關鍵

fast.ai團隊不僅在DAWNBench比賽中贏得最快速度的獎品,而且這些相同的演算法也因最便宜的執行而獲獎。這裡要學到的教訓是,建立成功的DL應用程式不僅僅是在這個問題上放棄大量GPU,而應該是創造力,直覺和創新的問題。

本文中討論的大多數突破(退出,餘弦退火,SGD重啟,列表繼續......)實際上是如此精確的時刻,有人想到以不同的方式解決問題。然後,這些方法的準確性提高了,而不僅僅是通過簡單地向少數IBM計算機丟擲另外一千個影象來實現。

因為有很多大型犬在矽谷有很多大型GPU,不要以為你不能挑戰它們,或者你不能創造出特殊或創新的東西。

事實上,有時你可能會看到約束是一種祝福; 畢竟,必要性是發明之母。