機器之心GitHub項目:從循環到卷積,探索序列建模的奧秘
機器之心原創,作者:蔣思源。
本文討論並實現了用於序列模型的基本深度方法,其中循環網路主要介紹了傳統的 LSTM 與 GRU,而卷積網路主要介紹了最近 CMU 研究者提出的時間卷積網路與實證研究。相比於我們熟知的經典循環網路方法,用 CNN 實現序列建模可能會更有意思,因此本文的實現部分重點介紹了時間卷積網路的實現。
這是機器之心 GitHub 實現項目的第四期,前面幾期分別介紹了卷積神經網路、生成對抗網路與帶動態路由的 CapsNet。
機器之心項目地址:https://github.com/jiqizhixin/ML-Tutorial-Experiment
文章結構
序列建模
循環網路
- 表達式
- 計算圖
- LSTM
- GRU
卷積與時間卷積網路
- 全卷積與因果卷積
- 空洞卷積
- 高速公路網路與殘差模塊
實現
- LSTM的語言建模
- 時間卷積網路的語言建模
序列建模廣泛存在於自然語言處理、語音識別和計算機視覺等領域,這種任務通常需要將輸入序列轉換為輸出序列,例如將輸入的英文語句轉換為輸出的中文語句。從實踐經驗上來說,一般我們都將循環神經網路視為序列建模的默認配置。甚至 Ian Goodfellow 在《深度學習》一書中使用「序列建模:循環和遞歸網路」作為章節名,這些都表明序列建模與循環架構有非常緊密的聯繫。
因此本文在前一部分主要介紹了循環網路的概念、表達式和計算圖,並著重描述了 LSTM 與 GRU 兩種流行的變體。在實現部分,我們將基於 TensorFlow 在語言建模任務中實現 LSTM 與 GRU。
但序列建模不僅僅只有 RNN,一個關鍵的想法是在一維時間序列上使用一維卷積運算。此外,最近的研究表明一些卷積架構能在音頻合成、語言建模和機器翻譯任務中達到頂尖的準確度。因此,我們是否能找到像 LSTM 那樣的一般架構處理時序問題就顯得十分重要。
為了了解這種用於序列建模的卷積網路,我們將解讀最近 Shaojie Bai 等人完成的架構與實驗,包括構建時間卷積網路的因果卷積、空洞卷積和殘差連接等。後面我們同樣會根據他們提出的 TCN 測試語言建模任務,並盡量保證參數數量和 LSTM 與 GRU 處於同一量級。
序列建模
序列建模即將一個輸入或觀測序列映射到一個輸出或標記序列,李航在《統計學習方法》中也將其稱為標註問題。他表明標註問題是分類問題的推廣,又是更複雜的結構預測問題的簡單形式。標註問題或序列建模的目的在於學習一個模型,從而能對觀測序列給出標記序列作為預測,即最大化概率 P(y_1,y_2,...,y_n | x_1,x_2,...,x_n)。在傳統機器學習方法中,序列建模常用的方法有隱馬爾可夫模型和條件隨機場等,但近來 RNN 等深度方法憑藉強大的表徵能力在序列建模問題上有非常突出的表現。
但根據 Shaojie Bai 等人的定義,序列建模應該是在給定時間步 t 的情況下,只使用 x_0 到 x_t 的序列信息預測輸出 y_t。當然這只是一般化的定義,具體問題還需要具體分析,例如機器翻譯最好可以使用雙向 RNN 獲取整個句子的信息再轉化為譯文。因此一般序列建模的形式化表述如下:
序列建模為任意滿足因果約束的映射函數 f: X^T+1 → Y^T +1,它僅依賴於 x_1,x_2,...,x_t 而不使用 x_t,x_t+1,...,x_T 的信息預測 y_t。
循環網路
循環神經網路是一類用於處理序列問題的神經網路,循環網路可以擴展到更長的序列。循環網路相比經典的全連接網路有非常大的提升,例如參數共享和構建長期依賴關係等。對於語句的序列建模,全連接網路會給每個輸入特徵分配一個單獨的參數,所以它需要分別學習句子每個位置的所有語言規則。而循環神經網路會在多個時間步內共享相同的參數,因此不必學習句子每個位置的所有語言規則。此外,循環網路會有一個記憶機製為當前時間步的預測提供前面時間步的信息。
表達式
其實循環神經網路的基本原理可使用非常優美的表達式展示,若考慮動態系統的經典形式:
它其實也可以視為一個循環神經網路,因為本質上任何涉及循環的函數都可以視為一個循環神經網路。以上 s^t 可視為系統在第 t 步的狀態,因此後一步的系統狀態會取決於前一步的系統狀態。我們注意到每一個系統狀態的計算都會使用相同的函數與參數,這樣循環地向後計算就能構建一個循環系統。如下第三個時間步的系統狀態可以表示為:
這樣的表達式其實就展示了循環網路的本質。若我們具體考慮循環網路每一個時間步都存在輸入,且使用變數 h 表示循環網路的隱藏狀態(代替上述系統的狀態),那麼我們可以將一般的循環神經網路抽象為以下表達式:
其中 x^t 表示第 t 個時間步上的輸入,當前時間步的隱藏狀態取決於前一時間步的隱藏狀態、當前時間步和所有時間步都有相同的參數θ。我們同樣可以將該表達式展開,例如 h^3 = f(h^2, x^3; θ) = f(f(h^1, x^2; θ), x^3; θ)。
該 RNN 的抽象表達式也說明了它只會利用過去時間步的信息來預測當前的狀態。此外,循環神經網路連續使用相同的函數 f 與參數θ來計算不同時間步的狀態,這種方式在多個時間步上共享了相同的參數而降低了模型規模。
循環神經網路與全連接網路的區別可以很直觀地從抽象表達式中看出來,因為有無權重共享機制是它們最重要的屬性。最基本的全連接網路可以抽象為一個簡單的複合函數,因為每一層全連接網路其實都可以看作一個函數逼近器。
以下展示了三層全連接網路的抽象表示,其中 f^1 表示第一層或輸入層,將第一層的值作為輸入並計算第二層的激活值 f^2,然後將第二層的激活值作為輸入計算第三層的激活值。這種複合函數展示了全連接網路的前饋傳播過程,而將複合函數的鏈式求導法則作為反向傳播演算法也就顯得十分自然。
根據上面的全連接表達式,我們清楚地了解到循環網路複合的函數都是一樣的,而全連接網路複合的函數是不一樣的,這也是循環體權重共享的特點。當然我們描述循環網路的表達式只是循環體的抽象,典型的循環網路會增加額外的架構特性,例如讀取狀態信息 h 進行預測的輸出層或導師驅動過程等。而很多循環網路的修正都集中在改進循環體以關注長期依賴關係,例如 LSTM 和 GRU 等。
以上只是從概念上解釋循環網路,我們並沒有具體學習循環網路的架構與模塊,下一部分我們將以計算圖的形式具體展示循環網路的結構,包括常見的展開式與不同的變體架構等。
計算圖
上一節的抽象表達式展示了循環體的本質,而它們可以直觀地用計算圖表示出來。計算圖是形式化一組計算結構的方式,一般情況下,我們看到的循環網路展開結構都是這種計算圖,這一章節展示的計算圖參考自《深度學習》。例如上一節中隱藏狀態 h^t = f(h^t-1, x^t; θ) 的計算圖可以表示為:
該計算圖展示了一個不帶輸出單元的循環網路架構,它只使用前一個時間步的隱藏單元信息和當前時間步的輸入信息,並利用相同的函數計算下一個隱藏單元的值。此外,上圖從左到右分別為循環圖和展開圖,循環圖非常簡潔,但展開圖詳細描述了計算過程與信息流動路徑。
上述的計算圖其實只描述了循環體,它缺少了輸出映射與輸出單元。一般循環神經網路根據輸出單元和循環結構可以分為三種,即 Elman Network 類、Jordan Network 類和 N 到 1 的網路。以下分別是這三種網路的計算圖,它們基本上構成了循環神經網路架構(雙向 RNN 可以是它們的反向疊加)。
Elman Network 代表了一類循環網路,它的每一個時間步都有一個輸入與輸出,且循環連接發生在隱藏單元與隱藏單元之間。我們通過累積每一個預測 y hat 與 y 之間的誤差來確定損失函數 L,並執行沿時間的反向傳播訓練整個網路。
以上展示了這種循環連接發生在隱藏層之間的網路,其中 x 和 y 分別代表數據點與對應的標註,h 為隱藏單元或循環體,L 是預測值與標註值之間的距離與損失。一般在第 t 個時間步,我們會輸入數據 x^t,並計算隱藏狀態 h^t = tanh(W*h^{t-1}+U*x^t),隨後 h^t 將傳入下一個時間步與當前時間步輸出的對數概率 o^t = c + V*h^t。最後我們就能根據輸出與標註值計算模型損失。
這種網路架構是非常經典的結構,我們可以將隱藏單元視為記憶的累積,即將過去的信息傳遞到未來時間步。這種架構也非常容易擴展到深度架構,例如我們在 h 和 o 之間再加一個循環單元 h 或在循環體中額外添加全連接結構等。如下展示了上述循環架構的計算式:
其中在第 t 個時間步上的輸入 x^t 可以是一個詞嵌入向量或簡單地使用 One-hot 編碼。一般權重矩陣 U 的維度為 [詞嵌入長度 * 隱藏層的單元數],偏置向量 b 的維度等於隱藏層單元數。隱藏層輸出的向量(每一個元素為隱藏單元的激活值),我們在將隱藏層向量執行仿射變換後,可將 o 視為未歸一化的對數概率,並計算 softmax 以和標註的詞嵌入向量進行對比。
Jordan Network 代表了一類循環網路,它的每一個時間步都有一個輸入與輸出,但循環連接只存在當前時間步的輸出和下一個時間步的隱藏單元之間。因為該架構在隱藏單元之間沒有循環連接,因此它沒有一個記憶機制來捕捉所有用於預測未來時間步的歷史信息。
這種架構雖然在能力上並沒有那麼強大,但它的優勢在於訓練過程中的解耦合與並行過程。因為既然我們使用 o^t 作為傳遞到後一步的信息,那麼為什麼我們就不能使用標註 y^t 替換 o^t 而作為傳遞到後面的信息呢?通過使用 y^t 替換 o^t,網路不再需要先計算前一時間步的隱藏狀態,再計算後一步的隱藏狀態,因此所有計算都能並行化。
Jordan Network 類的架構在推斷時還是會使用前一時間步的輸出值 o 來計算後一時間步的隱藏狀態。這種網路的一大缺點是,訓練過程中觀察到的數據與測試時看到的數據會有較大的不同。
最後一種架構會先讀取整個序列,然後再產生單個輸出,循環連接存在於隱藏單元之間。這種架構常用於閱讀理解等序列模型。
這種架構只在最後一個隱藏單元輸出觀察值並給出預測,它可以概括序列併產生用於進一步運算的向量,例如在編碼器解碼器架構中,它可用於編碼整個序列並抽取上下文向量。
以上是循環神經網路抽象概念與基本的架構表示,它們非常有助於我們理解「循環」這個概念。但在實際建模中,RNN 經常出現梯度爆炸或梯度消失等問題,因此我們一般使用長短期記憶單元或門控循環單元代替基本的 RNN 循環體。它們引入了門控機制以遺忘或保留特定的信息而加強模型對長期依賴關係的捕捉,它們同時也大大緩解了梯度爆炸或梯度消失的問題。
下面我們將簡要介紹這兩種非常流行的 RNN 變體,它們同樣希望生成通過時間的路徑,且導數既不會消失也不會爆炸。
LSTM
如前所示,循環網路的每一個隱藏層都有多個循環單元,隱藏層 h^t-1 的向量儲存了所有該層神經元在 t-1 步的激活值。一般標準的循環網路會將該向量通過一個仿射變換並添加到下一層的輸入中,即 W*h^{t-1}+U*x^t。而這個簡單的計算過程由於重複使用 W 和 U 而會造成梯度爆炸或梯度消失。因此我們可以使用門控機制控制前一時間步隱藏層保留的信息和當前時間步輸入的信息,並選擇性地輸出一些值而作為該單元的激活值。
一般而言,我們可以使用長短期記憶單元代替原版循環網路中的隱藏層單元而構建門控循環神經網路。以下兩張圖分別介紹了 LSTM 的基本概念和詳細的計算過程。
以下是 LSTM 單元的簡要結構,其中 Z 為輸入部分,Z_i、Z_o 和 Z_f 分別為控制三個門的值,即它們會通過激活函數 f 對輸入信息進行篩選。一般激活函數可以選擇為 Sigmoid 函數,因為它的輸出值為 0 到 1,即表示這三個門被打開的程度。
若我們輸入 Z,那麼該輸入向量通過激活函數得到的 g(Z) 和輸入門 f(Z_i ) 的乘積 g(Z)f(Z_i ) 就表示輸入數據經篩選後所保留的信息。Z_f 控制的遺忘門將控制以前記憶的信息到底需要保留多少,保留的記憶可以用方程 c*f(z_f)表示。以前保留的信息加上當前輸入有意義的信息將會保留至下一個 LSTM 單元,即我們可以用 c = g(Z)f(Z_i) + cf(z_f) 表示更新的記憶,更新的記憶 c 也表示前面與當前所保留的全部有用信息。我們再取這一更新記憶的激活值 h(c) 作為可能的輸出,一般可以選擇 tanh 激活函數。最後剩下的就是由 Z_o 所控制的輸出門,它決定當前記憶所激活的輸出到底哪些是有用的。因此最終 LSTM 的輸出就可以表示為 a = h(c)f(Z_o)。
上圖非常形象地展示了 LSTM 單元的工作原理,我們修改了《深度學習》一書中的結構圖,以更詳細地解釋該單元的計算過程。
上圖詳細描述了 LSTM 單元的計算過程,其中 x^t 表示第 t 個時間步的輸入向量,一般可以是詞嵌入向量。h^t-1 為上一個時間步隱藏單元的輸出向量,該向量的元素個數等於該層神經元或 LSTM 單元的數量。U 和 W 分別是輸入數據和前一時間步隱藏單元輸出值的權重矩陣,一個 LSTM 單元因為不同的門控與輸入,需要 8 個不同的權重矩陣。此外,s^t 為第 t 個時間步的內部狀態或記憶,它會記住所有對於預測相關的信息。最後,b 代表了各個門控和輸入的偏置項。
首先我們會向輸入門、遺忘門和輸出門饋送當前時間步的輸入 x^t 與前一步的隱藏單元 h^t-1,在對它們進行線性變換後,利用 Sigmoid 函數壓縮到區間(0, 1)以作為門控。這三個門控的計算式如上圖所示分別為 g^t、f^t 和 q^t,其中 i 表示該層級中的第 i 個 LSTM 單元。
我們將輸入與輸入門對應元素相乘,這就代表了當前時間步需要添加到記憶 s^t 的信息。而前一時間步的記憶 s^t-1 與遺忘門 f^t 對應元素相乘就表示了需要保留或遺忘的歷史信息是多少,最後將這兩部分的信息相加在一起就更新了記憶 s^t,這一過程見上圖 s^t 的計算式。最後我們將記憶 s^t 的激活值與輸出門 q^t 對應元素相乘,就能計算出當前時間步的 LSTM 單元輸出值,這一計算過程如上圖 h^t 所示。
Goodfellow 表示記憶 s^t-1 也可以用作門控單元的額外輸入(如上圖所示),但一般 LSTM 的門控單元只使用前一時間步的輸出 h^t-1 作為輸入,因此我們也不太確定怎樣才能使用 s^t-1 作為門控單元的額外輸入。
GRU
GRU 背後的原理與 LSTM 非常相似,即用門控機制控制輸入、記憶等信息而在當前時間步做出預測。GRU 有兩個有兩個門,即一個重置門(reset gate)和一個更新門(update gate)。這兩個門控機制的特殊之處在於,它們能夠保存長期序列中的信息,且不會隨時間而清除或因為與預測不相關而移除。
從直觀上來說,重置門決定了如何將新的輸入信息與前面的記憶相結合,更新門定義了前面記憶保存到當前時間步的量。如果我們將重置門設置為 1,更新門設置為 0,那麼我們將再次獲得標準 RNN 模型。使用門控機制學習長期依賴關係的基本思想和 LSTM 一致,但還是有一些關鍵區別:
- GRU 有兩個門(重置門與更新門),而 LSTM 有三個門(輸入門、遺忘門和輸出門)。
- GRU 並不會控制並保留內部記憶(c_t),且沒有 LSTM 中的輸出門。
- LSTM 中的輸入與遺忘門對應於 GRU 的更新門,重置門直接作用於前面的隱藏狀態。
在 Kyunghyun Cho 等人第一次提出 GRU 的論文中,他們用下圖展示了門控循環單元的結構:
上圖的更新 z 將選擇隱藏狀態 h 是否更新為新的 h tilde。重置門 r 將決定前面的隱藏狀態是否需要遺忘。下面我們將具體解釋這兩個門控與隱藏狀態。
以下將描述第 j 個隱藏單元激活值的計算方式。首先重置門 r_j 的計算式可以表示為:
其中 σ 為 Sigmoid 函數,[*]_j 向量中的第 j 個元素,x 和 h_t-1 分別為當前輸入和前面層級的隱藏狀態,W_r 和 U_r 分別為更新門的權重矩陣。這個門控將當前輸入與前面隱藏狀態分別執行一個線性變換,再將結果壓縮至 0 到 1 以決定到底有多少過去的信息需要遺忘。同樣,更新門的計算式可以表示為:
更新門控制了前面時間步的記憶信息和當前時間步所記的信息,並傳遞到當前時間步最終記憶的信息,這一點在以下兩個計算式中有非常明確的展示。
首先我們需要確定當前時間步需要記憶的信息,即前面隱藏層的信息到底需要保留多少以作為這一步的記憶。如下所示重置門 r 通過 Hadamard 乘積確定需要遺忘的歷史信息,如果門控 r 為 0,那麼該時間步記憶的內容就僅從輸入獲取,如果門控 r 為 1,那麼就將利用所有的歷史信息作為該時間步的記憶。注意我們將 h tilde 理解為該時間步的記憶,如果我們將它和前面時間步的記憶 h_t-1 組合,那麼就能得出當前時間步的最終記憶。
其中 Φ 為激活函數,一般我們可以選擇 tanh。在計算 h tilde 後,我們可以根據下式組合它與前面時間步的隱藏狀態,而最終得到當前時間步下該單元的激活值或隱藏狀態:
上式將使用更新門 z 權衡前面時間步的記憶和這一時間步的記憶,並得出當前時間步的最終記憶或激活值。
因此,重置門其實強制隱藏狀態遺忘一些歷史信息,並利用當前輸入的信息。這可以令隱藏狀態遺忘任何在未來發現與預測不相關的信息,同時也允許構建更加緊緻的表徵。而更新門將控制前面隱藏狀態的信息有多少會傳遞到當前隱藏狀態,這與 LSTM 網路中的記憶單元非常相似,它可以幫助 RNN 記住長期信息。
由於每個單元都有獨立的重置門與更新門,每個隱藏單元將學習不同尺度上的依賴關係。那些學習捕捉短期依賴關係的單元將趨向於激活重置門,而那些捕獲長期依賴關係的單元將常常激活更新門。
卷積與時間卷積網路
卷積神經網路,即至少在一層上使用卷積運算來代替一般的矩陣乘法運算的神經網路,一般我們認為卷積網路擅長處理「網格結構的數據」,例如圖像就是二維的像素網格。但其實時序數據同樣可以認為是在時間軸上有規律地採樣而形成的一維網格,根據 Shaojie Bai 等人的實驗結果,一般的時間卷積網路甚至比 LSTM 或 GRU 有更好的性能。
卷積的基本概念其實已經有非常多的入門教程,因此這裡只簡要說明一般的卷積運算與一維卷積。在卷積運算中,卷積核會在輸入圖像上滑動以計算出對應的特徵圖。卷積層試圖將神經網路中的每一小塊進行更加深入的分析,從而得出抽象程度更高的特徵。一般來說通過卷積層處理的神經元結點矩陣會變得更深,即神經元的組織在第三個維度上會增加。
一般來說,卷積運算主要通過稀疏權重、參數共享和平移等變性等特性加強了機器學習系統。稀疏權重即卷積核大小會遠小於輸入圖像的大小,這允許卷積網路存儲更少的參數和使用更少的計算而實現高效的性能。參數共享也是非常優秀的屬性,因為我們假設數據擁有局部結構,那麼只需要在小範圍神經元中使用不同的參數,而大範圍內的神經元可共享參數。最後的平移不變性也建立在參數共享的基礎上,它可以直觀理解為若移動輸入中對象,那麼輸出中的表示也會移動同樣的量。
以下展示了簡單的一維卷積,適用於序列建模的卷積網路一般就是採用的這種架構。從一維卷積的連接方式可以清晰地了解權重共享的方式,圖中每個卷積層使用了一個大小為 3 的卷積核,即 k1、k2 和 k3 和 f1、f2 和 f3。下層每一個神經元只會和上層神經元部分連接,例如 h_3 只能由下層的局部神經元 x_2、x_3 和 x_4 計算得出。
在序列建模任務中,最下層的 x 可視為句子等輸入序列,最上層的 g 可視為輸出序列,中間的 h 即隱藏層。當然,這種一維卷積並沒有限制為只能查看當前時間步以及之前信息的因果卷積。越上層的神經元擁有越廣感受野,因此高層的卷積單元將有能力構建長期依賴關係。如上所示,g_3 可以觀察到輸入序列的所有信息。
一維卷積從直觀上確實能實現序列建模,但我們經常使用的還是循環網路,尤其是 LSTM 或 GRU。不過在論文 An Empirical Evaluation of Generic Convolutional and Recurrent Networks for Sequence Modeling 中,作者表明他們所提出的時間卷積網路可作為一般的序列建模框架,且擁有非常好的效果。本文後面將介紹這種網路,並在 PTB 數據集上分別使用 RNN 與 TCN 構建語言模型。
時間卷積也是從一般的卷積運算中延伸得出,下面簡要介紹了卷積序列預測的一般架構。我們的目標是將卷積網路的最佳實踐經驗精鍊為一個簡單的架構,它能便捷地處理時序建模問題。這種時間卷積網路(TCN)的顯著的特點有如下幾點,首先架構中的卷積存在因果關係,這意味著從未來到過去不會存在信息「泄漏」。其次卷積架構可以將任意長度的序列映射到固定長度的序列。除此之外,TCN 還強調利用殘差模塊和空洞卷積來構建長期依賴關係。
TCN 論文圖 1:TCN 架構的組成元素。(a)為空洞係數 d=1, 2, 4、卷積核大小 k=3 的空洞因果卷積,感受野能覆蓋輸入序列中的所有值。(b)為 TCN 殘差塊,當殘差輸入和輸出有不同的維度,我們會添加一個 1x1 的卷積。(c)為 TCN 中的殘差連接示例,其中藍線為殘差函數中的卷積核,綠線為恆等映射。
全卷積與因果卷積
為了使用卷積運算處理時序數據,TCN 結合了一維全卷積與因果卷積兩種結構。通過使用一維全卷積網路,TCN 可以產生和輸入序列等長的輸出序列,且每一個隱藏層通過使用 Padding 可以保持和輸出層等長。而通過使用因果卷積,TCN 可以保證前面時間步的預測不會使用未來的信息,因為時間步 t 的輸出只會根據 t-1 及之前時間步上的卷積運算得出。因此總的來說時間卷積網路簡單地組合一維全卷積和因果卷積而轉化為適合序列數據的模型。
全卷積網路最開始在論文 Fully Convolutional Networks for Semantic Segmentation(2015)中提出,它將傳統卷積神經網路最後幾個全連接層替換為卷積層。一般卷積網路會使用全連接層將特徵圖映射為固定長度的向量,且每一個元素代表一個類別。這種結構相當於將卷積抽取的高級特徵實現線性組合而最終預測類別,但它的局限性體現在只能對整張圖像或整段序列做分類處理。
因此引入全卷積的意義在於它能實現密集型的預測,即在二維卷積下對圖像實現像素級的分類,在一維卷積下對序列實現元素級的預測。此外,由於低層的卷積運算感受野較小,對於特徵的位置變化不敏感,而高層的卷積網路感受野非常大,對特徵的變化也非常敏感。因此 TCN 用一維卷積替代最後幾個全連接層有助於感受整個輸入序列的信息,這對於構建長期記憶非常有幫助。以下展示了帶全連接層的卷積網路和全卷積網路的區別:
如上所示,全卷積網路將預測類別概率(上)轉化為像素級的預測(下)。
因果卷積首次是在 WaveNet(van den Oord et al., 2016)論文中提出,從直觀上來說,它類似於將卷積運算「劈」去一半,令其只能對過去時間步的輸入進行運算。對於 TCN 所使用的一維卷積來說,因果卷積可以簡單將一般卷積的輸出移動幾個時間步而實現。在訓練過程中,所有過去時間步的卷積預測可以並行化,因為它們的輸入和標註真值都是已知的,所以這相對於循環網路在訓練上有非常大的優勢。因果卷積的結構將結合空洞卷積一起展示。
空洞卷積(Dilated Convolutions)
因果卷積其實還有一個問題,它需要非常多的層級數或較大的卷積核來擴寬感受野,而較大的感受野正式構建長期記憶所必須的。因此,如果我們不希望通過前面兩種會增加計算量的方法擴展感受野,那我們就需要使用空洞卷積(或稱擴張卷積)增加數個量級的感受野。
空洞卷積最大的特性就是擴張感受野,它不是在像素間插入空白像素,而是略過一些已有的像素。當然,我們也可以理解為保持輸入不變,並向卷積核中添加一些值為零的權重,從而在計算量基本不變的情況下增加網路觀察到的圖像範圍或序列長度。此外,如果我們將一般卷積運算的步幅增大,那同樣也能起到增加感受野的效果,但卷積步幅大於 1 就會起到降採樣的效果,輸出的序列長度會減小。如下展示了因果卷積結合空洞卷積的效果:
如上所示,一維卷積的卷積核大小為 2,第一層使用的 dilation 為 1,即常規的卷積運算。而後面層級的空洞大小依次加大,常規卷積只能從右到左觀察到 5 個輸入數據,而空洞卷積可以觀察到所有 16 個輸入數據。
形式上,對於 1 維的輸入序列 x ∈ R^n 和卷積核 f : {0, . . . , k ? 1} → R,空洞卷積運算 F 可以定義為:
其中 d 為擴張係數、k 為卷積核大小,s ? d · i 計算了採用上層哪一個單元。擴張係數控制了每兩個卷積核間會插入多少零值,當 d=1 時,空洞卷積就會退化為一般的卷積運算。使用較大的擴張係數允許輸出端的神經元表徵更大範圍的輸入序列,因此能有效擴張感受野。
一般在使用空洞卷積時,我們將隨著網路深度 i 的增加而指數級地增大 d,即 d=O(2^i)。這確保了卷積核在有效歷史信息中覆蓋了所有的輸入,同樣也確保了使用深度網路能產生極其長的有效歷史信息。
高速公路網路與殘差連接
殘差網路在計算機視覺中有非常強大的表達能力,它因為解決了深層網路的訓練問題而可以大大增加網路的層數。但要理解殘差網路與殘差連接,我們需要先理解高速公路網路(Highway Networks)。
高速公路網路受到 LSTM 的啟發,它通過門控令信息在多個神經網路層級中可以高效流動,從而能使用傳統基於梯度的方法快速訓練深度網路。一般而言,若每一層的卷積運算可以用隱藏函數 H 表示,那麼給定該層的輸入 x 與權重矩陣 W_H,輸出可以表示為 y = H(x, W_H)。在高速公路網路中,傳入後一層的信息不僅是當前層的計算結果,同時還包含了前面層級的計算結果。高速公路網路會使用門控機制控制每一層向後傳遞的信息:
其中 H(x, W_H) 表示當前層傳統卷積運算的結果,而非線性函數 T(x, W_T) 表示轉換門,它控制了當前層的卷積運算結果對當前層輸出的貢獻大小。C(x,W_C) 表示攜帶門,它控制了當前層的輸入信息最終不經過計算直接傳到輸出端的大小。高速公路網路一般採用 1-T(x, W_T) 代替 C(x,W_C) 而減少門控的數量,且門控通過 Sigmoid 函數實現。
由於增加了復原輸入信息的可能性,模型會更加靈活,且當 T=1 而 C=0 時,高速公路網路就退化為了常規的卷積網路。而殘差網路與殘差連接正是這種架構的特例,如果我們令上式的 T 和 C 都等於 1,那麼它就代表了一個殘差模塊,即 y = H(x, W_H) + x。因為我們要學的是卷積核的權重 W_H,因此經過簡單的變形可得 H(x, W_H) = y-x。由此可知,我們實際需要學習的函數 H 是由殘差項 y-x 而得出,這也就是我們稱之為殘差網路的原因。
上圖為原論文中的殘差塊結構,其中 F(x) 和前面 H(x, W_H) 表示相同的過程。殘差塊的輸出結合了輸入信息與內部卷積運算的輸出信息,這種殘差連接或恆等映射表示深層模型至少不能低於淺層網路的準確度。
原論文展示了實踐中的兩種殘差塊,下圖左邊是一種採用堆疊兩個 3×3 的卷積運算方法,它在深層網路中表現並不是很好。右邊為一種瓶頸殘差網路,第一個 1×1 的卷積可以視為對輸入進行降維處理,因此中間的 3×3 卷積層將有更少的計算量,而後面的 1×1 卷積可以升維或恢復所有的信息。瓶頸殘差網路有更高的計算效率,因此在非常深的網路中能大量減小計算量。
由於 TCN 的感受野取決於網路深度 n、卷積核大小 k 和空洞卷積中的擴張係數 d,因此更深的 TCN 有更強的穩定性要求。例如在預測依賴於 2^12 歷史時間步和高維輸入空間下,網路需要達到 12 層。且每一層需要多個卷積核執行特徵抽取,在 TCN 論文作者設計的模型中,它使用了殘差模塊來加深卷積網路。
在 TCN 的殘差模塊內,有兩層空洞卷積和 ReLU 非線性函數,且卷積核的權重都經過了權重歸一化。此外,TCN 在殘差模塊內的每個空洞卷積後都添加了 Dropout 以實現正則化。
然而在標準的 ResNet 中,輸入可以直接加上殘差函數的輸出向量。而在 TCN 中,輸入與輸出有不同的維度,因此我們需要使用額外的 1×1 卷積來確保 F(x) 與 x 間對應像素相加有相同的維度。
然而,在標準 ResNet 中,輸入直接添加到殘餘函數的輸出中,在 TCN 中(通常是 ConvNets),輸入和輸出可以有不同的寬度。為了解決輸入輸出寬度的差異,我們使用額外的 1x1 卷積來確保元素相加⊕接收相同形狀的張量。
最後,時間卷積網路即結合了一維因果卷積和空洞卷積作為標準卷積層,而每兩個這樣的卷積層與恆等映射可以封裝為一個殘差模塊。這樣由殘差模塊堆疊起一個深度網路,並在最後幾層使用卷積層代替全連接層而構建完整的全卷積網路。
註:
由於原文字數超過了知乎的限制,所以「實現部分」請移步原文閱讀,感謝理解。原文鏈接:機器之心GitHub項目:從循環到卷積,探索序列建模的奧秘。
推薦閱讀: