1. 程式人生 > >利用 TensorFlow 一步一步構建一個多工學習模型

利用 TensorFlow 一步一步構建一個多工學習模型

 

介紹

為什麼是多工學習?

當你在思考新事物的時候,他們通常會利用他們以前的經驗和獲得的知識來加速現在的學習過程。當我們學習一門新語言的時候,尤其是相關的語言時,我們通常會使用我們一級學過的語言知識來加快這一門新語言的學習過程。這個過程也可以用另一種方式來理解 —— 學習一種新的語言可以幫助你更好的理解和說出自己的想法。

我們的大腦會同時學習多種不同的任務,無論我們是想將英文翻譯成中文,還是想將中文翻譯成德語,我們都是使用相同的大腦架構,也就是我們自己的腦袋。同理在我們的機器學習模型中,如果我們採用的是同一個網路來同時完成這兩個任務,那麼我們就可以把這個任務稱為 “多工學習”。

“多工學習” 是最近幾年或者說未來幾年非常有趣和令人興奮的一個研究領域,因為這個學習模式從根本上減少了學習新概念所需的資料量。深度學習其中一個最偉大的地方是,我們可以利用模型之間的引數共享來優化我們的模型,而這種方法在多工學習中將顯得尤為突出。

在我們開始這個領域的學習之前,我遇到了一些障礙 —— 雖然我們很容易理解實現多工學習所需要的網路架構,但是我們很難弄清楚在 TensorFlow 中是如何實現它的。除了 TensorFlow 中的標準網路之外,我們做任何事情都需要對其工作原理有一個很好的立即,但是網上大多數的教程都是沒有一個很好的指導教學功能。我希望以下教程可以簡單解釋一些關鍵概念,並幫助學習困難的你。

我們需要做什麼

通過一個例子瞭解 TensorFlow 的計算圖。使用 TensorFlow 進行多工學習。如果你已經瞭解了 TensorFlow 的計算圖,那麼你可以跳過這部分。

瞭解我們如何使用計算圖進行多工學習。我們將通過一個例子來說明如何調整一個簡單的計算圖來完成多工學習。

用一個簡單例子來理解計算圖

TensorFlow 的計算圖能讓 TensorFlow 執行的更加快,它是深度學習中一個很重要的組成部分,雖然這個組成部分時常讓人感到困惑。

計算圖可以能容易整理清楚模型的組織架構,這對我們進行多工學習是非常有意義的。首先,讓我們先來理解一些有關多工學習的概念吧。

一個簡單例子:線性變換

我們將對計算圖進行簡單的計算 —— 對輸入資料進行線性變換,並計算平方根損失。

 

上面這張圖和程式碼有幾點需要強調:

如果我們現在執行這個程式碼,我們不會得到任何輸出。請記住,計算圖只是一個模板 —— 它上面都不做。如果我們想要一個計算輸出,那麼我們必須告訴 TensorFlow 使用 Session 來進行執行。

我們還沒有明顯建立計算圖物件。你可能會希望我們必須在某處建立一個影象物件,以便 TensorFlow 知道我們想要建立的具體計算圖是什麼。事實上,我們可以通過使用 TensorFlow 操作,我們可以告訴 TensorFlow 哪些程式碼是在圖中。

提示:保持計算圖分離。你通常會在計算圖外面進行相當數量的資料操作和計算,也就是說我們要區分哪些程式碼是屬於計算圖的,哪些程式碼是不屬於計算圖的。我喜歡把我的計算圖放在一個單獨的檔案裡,這樣比較容易區分出來。

計算圖上的計算是在 TensorFlow 會話中進行的。要從會話中獲取結果,你需要提供兩件事情:目標結果和輸入資料。

目標結果或者操作。你可以告訴 TensorFlow 計算圖中哪些部分是要返回值的,並且會自動計算需要執行的內部計算結果。例如,你可以呼叫操作來初始化變數。

輸入通道。在大多數計算中,你將提供臨時輸入資料。在這種情況下,你可以使用此資料的佔位符構建圖形,並在計算時輸入它。並非所有計算或者操作都需要輸入 —— 對於許多人來說,所有資訊都包含在計算圖中。

如何使用計算圖來進行多工學習

當我們建立一個執行多工學習的神經網路時,我們希望網路中的某些神經元是被共享的,而網路的其它部分擇時針對不同任務而單獨設計的。當我們進行訓練的時候,我們希望每個獨立的任務都可以對共享神經元起到修改功能。

因此,首先,我們先繪製一個簡單的雙任務網路結構,該網路具有共享層和每個單獨任務的特定網路層。我們將用我們的目標將這些輸出提供給我們的損失函式。我已經在圖中標記出來哪些地方是需要我們進行設計佔位符的地方。

 

當我們訓練這個網路時,我們希望在訓練任務 2 的時候,不會改變任務 1 層的引數。但在訓練兩個中任何一個任務的時候,共享層的引數都會改變。這可能看起來有點困難 —— 通常我們在圖中只有一個優化器,因為你只優化一個損失函式。值得慶幸的是,我們可以巧妙的利用圖的性質來通過兩種方式來訓練這種模型。

交替訓練

第一種解決方案特別適用於需要一批任務 1 資料,然後再需要一批任務 2 資料的情況。

請記住,TensorFlow 會自動計算出你所需要的操作都需要進行哪些計算,並且只進行這些計算。這意味著如果我們只對其中一個任務定義一個優化器,它將只訓練計算該任務所需要的引數 —— 並且將其餘的引數單獨保留下來。由於任務 1 僅依賴於任務 1 層和共享層,所以任務 2 層的引數是不會改變的。讓我們在每個任務結束時畫出所需的優化器圖表。

 

我們可以通過交替呼叫每個任務優化器來進行多工學習,這意味著我們可以不斷地將每個任務的某些資訊傳送給另一個任務,因為這是通過共享層來完成的。不嚴格的說,我們正在發現一些任務之間的 “共性”。下面的程式碼為我們簡單的實現了這一個過程。如果你跟著我的思路在一步一步實現,那麼你可以複製下面的程式碼:

提示:什麼時候適合交替訓練?

當你為每個不同的任務有不同的資料集的時候,交替訓練是一個很好的注意(例如,從英語翻譯成法語和從英語翻譯成德語)。通過以這種方式設計網路,我們可以提高每項任務的效能,而不需去尋找更多的訓練資料。

交替訓練是我們最常見的一種情況,因為沒有那麼多的資料集可以同時滿足你兩個需求。我們來舉一個例子,比如,在機器視覺中,你可能需要執行其中的一項任務是來預測物件是否進行了旋轉,而另一個任務可能需要你去改變相機物件。這兩個任務顯然是相關度。

提示:什麼時候不適合交替訓練?

交替訓練很容易偏向特定的任務,第一種方法是顯而易見的。如果你的其中一個任務比別的任務有更大的資料集,那麼如果按照資料集的大小比例來進行訓練,你的共享層將包含擁有更多資料的任務的資訊。

第二種情況並不如此。如果交替進行訓練,模型中的最終任務會在引數中產生偏差。你沒有任何明顯的方法可以克服這個問題,但這確實意味著在你不需要進行交替訓練的時候,儘量採用第二種訓練方法。

聯合訓練

當你每個輸入都具有多個標籤的資料集,那麼你真正想要的是聯合訓練這些任務。問題是,你如何保持各個不同任務之間的獨立性?答案非常簡單。你只需要將單個任務的損失函式相加並優化就行了。下面是一個圖示,顯示一個可以聯合訓練的網路結構,具體程式碼也如下:

 

總結

在這篇文章中,我們已經瞭解到了深度學習中多工學習的基本原理。如果你以前使用過 TensorFlow 並且擁有自己的專案,那麼希望這已經足夠讓你入門開始動手做了。