第十章 序列建模:循環和遞歸網路 (開篇引言)
2017-05-05
Recurrent and Recursive Nets
https://www.youtube.com/watch?v=p6xzPqRd46w
重點摘要:
循環神經網路 (Recurrent Neural Network, RNN) 是一類用於處理序列數據的神經網路。就像卷積網路是專門用於處理網格化數據(如圖像)的神經網路一樣,循環神經網路專門用於處理序列 x^(1), ..., x^(τ)
。正如同卷積網路可以很容易地擴展到具有很大寬度和高度的圖像,以及處理大小可變的圖像,循環網路可以擴展到更長的序列(比起不基於序列的特化網路長得多)。大多數循環網路也能處理可變長度的序列。
從多層網路出發到循環網路,我們需要利用上世紀 80 年代機器學習和統計模型早期思想的優點:在模型的不同部分共享參數。參數共享使得模型能夠擴展到不同形式的樣本(這裡指不同長度的樣本)並進行泛化。如果我們在每個時間點都有一個獨立的參數,我們不但不能泛化到訓練時沒有見過序列長度,也不能在時間上共享不同序列長度和不同位置的統計強度。參數共享的概念體現在每個時間步中使用相同的更新規則和相同的參數集。
Q: 什麼是循環神經網路 (RNN)?它主要用於處理什麼類型的數據?
A: 循環神經網路 (RNN) 是一種專門設計用來處理序列數據的神經網路。序列數據的例子包括時間序列(如股票價格)、文本(詞語序列)、語音(聲學特征序列)等。
Q: RNN 的一個關鍵特性是什麼,使其能夠處理可變長度的序列並在不同時間步之間共享知識?
A: RNN 的一個關鍵特性是參數共享 (parameter sharing)。在處理序列的不同時間步時,RNN 使用相同的權重集和相同的更新規則。這使得模型能夠:
- 處理可變長度的序列: 因為應用於每個時間步的計算模塊是相同的。
- 在時間上共享統計強度: 模型可以在序列的不同位置和不同長度的序列之間泛化學到的模式,因為它在所有時間步都使用相同的參數。
Q: 相比於每個時間步都使用獨立參數的模型,RNN 的參數共享有什麼優點?
A:
- 泛化能力: 能夠泛化到訓練時未見過的序列長度。
- 統計效率: 可以在序列的不同部分共享學到的模式,減少了學習所需參數的數量,提高了統計效率。
- 模型規模: 避免了模型參數隨序列長度線性或更快增長的問題。
10.1 展開計算圖
重點摘要:
計算圖是形式化一組計算結構的方式,如那些涉及將輸入和參數映射到輸出和損失的計算。通過展開 (unfolding) 操作,可以將一個包含循環的圖(如 RNN 的定義)轉換為一個不包含循環的、但可能非常深的計算圖(有向無環圖, DAG)。這個展開的圖明確地展示了序列中每個時間步的計算流程以及參數是如何在不同時間步之間共享的。
例如,一個簡單的動態系統 s^(t) = f(s^(t-1); θ)
(公式 10.1) 可以展開為 s^(3) = f(f(f(s^(0); θ); θ); θ)
(公式 10.3)。
當 RNN 處理輸入序列 x^(t)
時,其狀態更新通常可以寫成 h^(t) = f(h^(t-1), x^(t); θ)
(公式 10.5)。展開這個遞歸關係就得到了一個計算圖,其中每個時間步 t
的狀態 h^(t)
依賴於前一個時間步的狀態 h^(t-1)
和當前時間步的輸入 x^(t)
,並且函數 f
和參數 θ
在所有時間步都是共享的。
這個展開的計算圖是理解 RNN 如何處理序列以及如何在其上應用反向傳播算法(稱為 BPTT)的基礎。
Q: 什麼是計算圖的「展開 (unfolding)」操作?它在 RNN 的上下文中是如何應用的?
A: 「展開」操作是指將一個包含循環依賴的計算圖(例如,RNN 中狀態依賴於前一時刻狀態的定義)轉換為一個不包含循環的、但可能包含重複結構的有向無環圖 (DAG)。
在 RNN 的上下文中,如果 RNN 的狀態更新規則是 h^(t) = f(h^(t-1), x^(t); θ)
,我們可以將這個遞歸關係沿著時間序列展開。例如,對於一個長度為 τ 的序列:
* h^(1) = f(h^(0), x^(1); θ)
* h^(2) = f(h^(1), x^(2); θ) = f(f(h^(0), x^(1); θ), x^(2); θ)
* …
* h^(τ) = f(h^(τ-1), x^(τ); θ)
這樣就得到了一個從初始狀態 h^(0)
和輸入序列 x^(1), ..., x^(τ)
到最終狀態 h^(τ)
(以及可能的輸出序列) 的前饋計算路徑。在這個展開的圖中,函數 f
和參數 θ
在每個時間步都是共享的副本。
Q: 為什麼要對 RNN 的計算圖進行展開?它有什麼好處?
A: 對 RNN 的計算圖進行展開的主要好處是:
- 消除循環依賴: 將原始定義中的循環結構轉換為一個(可能非常深的)前饋結構。
- 應用標準的反向傳播: 一旦展開成 DAG,就可以直接應用標準的反向傳播算法來計算損失函數關於模型參數
θ
和初始狀態h^(0)
(如果可學習) 的梯度。這個應用於展開 RNN 圖的反向傳播算法被稱為「通過時間反向傳播 (Back-Propagation Through Time, BPTT)」。 - 清晰化計算流程: 展開的圖清晰地展示了信息如何在時間序列中流動,以及參數是如何在不同時間步之間共享的。
Q: 在展開的 RNN 計算圖中,哪些元素是跨時間步共享的?
A: 在展開的 RNN 計算圖中,以下元素是跨時間步共享的(即在每個時間步的計算模塊中使用的是相同的實例或副本):
- 狀態轉移函數
f
: 用於從前一時刻狀態和當前輸入計算當前狀態的函數。 - 模型參數
θ
: 狀態轉移函數f
(以及可能的輸出函數)所使用的權重和偏置。
10.2 循環神經網路
重點摘要:
基於第 10.1 節中展開圖和參數共享的思想,可以設計各種循環神經網路。典型的 RNN 架構如圖 10.3 所示,包含輸入 x^(t)
、隱藏狀態 h^(t)
、輸出 o^(t)
和目標 y^(t)
。損失 L
衡量 o^(t)
與 y^(t)
的距離。
狀態更新通常為:
a^(t) = b + Wh^(t-1) + Ux^(t)
(輸入到隱藏層的仿射變換) (公式 10.8)
h^(t) = tanh(a^(t))
(隱藏層激活) (公式 10.9)
輸出通常為:
o^(t) = c + Vh^(t)
(隱藏層到輸出的仿射變換) (公式 10.10)
ŷ^(t) = softmax(o^(t))
(預測機率) (公式 10.11)
參數 U, V, W, b, c
在所有時間步共享。總損失是所有時間步損失之和 L = Σ_t L^(t)
(公式 10.13)。
RNN 的一個關鍵優勢是其處理可變長度序列的能力,以及在不同時間位置共享統計強度的能力。
通過時間反向傳播 (Back-Propagation Through Time, BPTT) 是一種將標準反向傳播應用於展開的 RNN 計算圖以計算梯度的算法。計算成本與序列長度 τ 成正比。
10.2.1 導師驅動過程和輸出循環網路
重點摘要:
在訓練 RNN 時,尤其是在生成序列的任務中(如語言模型),存在一個問題:如果模型在某個時間步 t
產生了一個錯誤的輸出 ŷ^(t)
,這個錯誤可能會影響到後續時間步 t+1
的輸入(如果 ŷ^(t)
被用作 x^(t+1)
的一部分),從而導致錯誤的級聯。
導師驅動 (Teacher Forcing) 是一種訓練策略,它在訓練期間,總是使用真實的目標序列中的前一個值 y^(t-1)
(而不是模型自身在前一步的預測 ŷ^(t-1)
) 作為當前時間步 t
的輸入(如果模型結構允許這種輸入)。這樣做可以避免錯誤的累積,並為模型的每個時間步提供更穩定和正確的學習信號。
然而,純粹的導師驅動可能導致訓練時和測試時的條件不匹配(因為測試時沒有真實的目標值作為輸入)。開環 (open-loop) 系統是指在推斷(測試)時,模型完全依賴於自身生成的歷史輸出來預測未來。
一些策略(如 Bengio et al., 2015b 提出的 scheduled sampling)試圖在訓練過程中逐步從導師驅動過渡到更接近開環的行為,以緩解這種不匹配。
Q: 什麼是導師驅動 (teacher forcing)?它在 RNN 訓練中是如何應用的?
A: 導師驅動是一種訓練循環神經網路(特別是那些需要生成序列的模型,如語言模型或序列到序列模型中的解碼器)的策略。
在導師驅動下,當模型需要在時間步 t
生成輸出 ŷ^(t)
並將其作為下一個時間步 t+1
的輸入 x^(t+1)
時,我們不使用模型在前一步的實際預測 ŷ^(t)
,而是使用訓練數據中真實的目標值 y^(t)
作為 x^(t+1)
。
也就是說,在每個時間步,模型接收到的作為「前一時刻輸出」的輸入,始終是來自真實數據的正確值,而不是模型自身可能帶有錯誤的預測。
Q: 使用導師驅動訓練 RNN 有什麼優點和缺點?
A:
- 優點:
- 加速收斂和穩定訓練: 由於模型在每個時間步都接收到正確的輸入(來自真實目標),它可以更快地學習到輸入和輸出之間的正確映射,避免了由於早期預測錯誤導致的錯誤累積和訓練不穩定。
- 解耦時間步之間的依賴: 使得每個時間步的損失計算和梯度反向傳播在某種程度上更加獨立,簡化了優化問題。
- 缺點:
- 訓練與推斷不匹配 (Exposure Bias): 在訓練時,模型總是看到真實的歷史序列作為輸入;但在推斷(測試)時,模型必須依賴於自身先前生成的(可能不完美的)輸出來預測後續的輸出。這種訓練和推斷條件的不匹配可能導致模型在推斷時性能下降,尤其是在生成長序列時,錯誤容易累積。
- 可能學到對錯誤不魯棒的模型: 由於模型在訓練時很少暴露在自身產生的錯誤序列中,它可能沒有學會如何從錯誤中恢復。
Q: 什麼是開環 (open-loop) 和閉環 (closed-loop) 系統在 RNN 中的含義?
A:
- 開環 (Open-loop) / 自回歸 (Autoregressive) 模式: 在推斷或生成階段,RNN 依賴於其自身在前一個時間步生成的輸出來作為當前時間步的輸入。這形成了一個反饋迴路,模型的輸出會影響其未來的輸入。這種模式下,模型是「閉環」運行的(從控制理論角度看,系統的輸出反饋到輸入)。
- 導師驅動下的訓練可以被視為一種「開環」訓練設置, 因為模型在每個時間步接收的「歷史輸出」輸入是由外部(導師,即真實數據)提供的,而不是由模型自身的反饋迴路產生的。 (注意:教材中 “open-loop” 的用法可能與其他上下文略有不同,這裡強調的是推斷時的自回歸行為。)
10.2.2 計算循環神經網路的梯度
重點摘要:
計算 RNN 參數的梯度依賴於將標準反向傳播算法應用於展開的計算圖,這個過程稱為通過時間反向傳播 (Back-Propagation Through Time, BPTT)。
梯度的計算從最終時間步的損失開始,沿著展開圖反向傳播到初始時間步。由於參數 U, V, W, b, c
在所有時間步都是共享的,所以它們的總梯度是它們在每個時間步產生的梯度的總和。
例如,對於損失 L
關於權重 W
(連接 h^(t-1)
到 h^(t)
)的梯度,可以通過對所有時間步 t
的 ∂L/∂W^(t)
求和得到,其中 W^(t)
是在時間步 t
使用的 W
的副本。
∂L/∂L^(t) = 1
(公式 10.17)
` (∇{o^(t)} L)_i = ŷ^(t)_i - 1{i,y^(t)} ` (對於 softmax 和交叉熵損失) (公式 10.18)
然後梯度可以反向傳播到 h^(t)
,再到 a^(t)
,然後到 h^(t-1)
等。
∇_{h^(t)} L = (∂a^(t+1)/∂h^(t))^T (∇_{a^(t+1)} L) + (∂o^(t)/∂h^(t))^T (∇_{o^(t)} L)
(公式 10.20, 10.21 的組合形式)
Q: 什麼是通過時間反向傳播 (BPTT)?它是如何工作的?
A: 通過時間反向傳播 (BPTT) 是一種將標準的反向傳播算法應用於展開後的循環神經網路計算圖,以計算損失函數關於 RNN 參數的梯度的算法。
- 工作原理:
- 前向傳播: 首先,沿著時間序列從頭到尾(或從輸入到輸出)對 RNN 進行前向計算,得到每個時間步的隱藏狀態、輸出以及最終的總損失。這個過程相當於在展開的計算圖上進行一次完整的前向傳播。
- 反向傳播: 然後,從最終時間步的損失開始,沿著展開的計算圖從後向前(即從時間 τ 到時間 1)反向傳播梯度。
- 計算損失關於每個時間步輸出的梯度。
- 計算損失關於每個時間步隱藏狀態的梯度(這會涉及到從當前時間步的輸出以及下一個時間步的隱藏狀態傳回的梯度)。
- 計算損失關於共享參數(如
U, V, W, b, c
)在每個時間步的局部梯度。
- 梯度累加: 由於 RNN 的參數是在所有時間步共享的,所以損失函數關於這些共享參數的總梯度是它們在每個時間步產生的局部梯度的總和。
Q: 在 BPTT 中,共享參數(如權重矩陣 W
)的梯度是如何計算的?
A: 由於 RNN 的參數(例如,連接 h^(t-1)
到 h^(t)
的權重矩陣 W
)是在所有時間步共享的,損失函數 L
(通常是所有時間步損失 L^(t)
的總和)關於這個共享參數 W
的總梯度,是 L
關於在每個時間步 t
使用的 W
的副本 W^(t)
的偏導數的總和。
即,∂L/∂W = Σ_t ∂L/∂W^(t)
。
在反向傳播過程中,我們會計算出每個 ∂L/∂W^(t)
(通過鏈式法則,將 ∂L/∂h^(t)
的梯度反向傳播到 W^(t)
),然後將它們累加起來得到最終的 ∂L/∂W
。
Q: BPTT 的計算複雜度與什麼因素有關?
A: BPTT 的計算複雜度(對於單個序列)主要與以下因素成正比:
- 序列長度 τ: 因為需要在展開的圖上進行 τ 步的前向傳播和 τ 步的反向傳播。
- 每個時間步的計算量: 這取決於 RNN 的隱藏層大小、輸入維度、輸出維度以及所使用的激活函數和層的類型。 總體而言,BPTT 的計算成本大約是 τ 乘以運行一個時間步 RNN 的成本。
10.2.3 作為有向圖模型的循環網路
重點摘要:
循環神經網路可以被解釋為一種結構化的有向圖模型。圖 10.7 展示了如何將一個 RNN 表示為一個有向圖,其中每個時間步的變數(如 x^(t)
, h^(t)
, y^(t)
)是圖中的節點,它們之間的依賴關係由有向邊表示。
這種視角有助於理解 RNN 如何定義序列數據的聯合機率分佈(如果輸出是機率性的)。例如,一個 RNN 可以定義 P(y^(1), ..., y^(τ) | x^(1), ..., x^(τ)) = Π_t P(y^(t) | x^(1), ..., x^(t), y^(1), ..., y^(t-1))
(公式 10.31 的一種理解)。
圖 10.8 進一步展示了 RNN 模型中隱藏狀態的邊緣化如何導致輸出之間複雜的遠程依賴。雖然 RNN 的直接連接(如 h^(t-1)
到 h^(t)
)是局部的,但通過隱藏狀態的傳播,任何早期時間步的輸入都可能影響到任何後續時間步的輸出。
Q: 如何將循環神經網路 (RNN) 看作是一種有向圖模型?圖中的節點和邊分別代表什麼?
A: 可以將 RNN(在其展開的形式下)看作是一個有向圖模型:
- 節點 (Nodes): 代表在不同時間步的隨機變數,例如:
- 輸入序列的元素
x^(t)
- 隱藏狀態
h^(t)
- 輸出序列的元素
y^(t)
(或模型的預測ŷ^(t)
)
- 輸入序列的元素
- 有向邊 (Directed Edges): 代表這些變數之間的條件依賴關係。例如:
- 從
x^(t)
和h^(t-1)
指向h^(t)
的邊,表示h^(t)
依賴於當前輸入和前一時刻的隱藏狀態。 - 從
h^(t)
指向y^(t)
(或ŷ^(t)
) 的邊,表示當前輸出依賴於當前隱藏狀態。 - 如果模型是自回歸的(例如,語言模型),可能還有從
y^(t-1)
指向h^(t)
(或x^(t)
) 的邊。 這個展開的圖是一個有向無環圖 (DAG)。
- 從
Q: 從有向圖模型的角度看,RNN 是如何定義序列數據的聯合機率分佈或條件機率分佈的?
A: 如果 RNN 的輸出層(例如,使用 softmax)產生了機率分佈,那麼整個 RNN(在其展開形式下)可以定義一個關於輸出序列 Y = (y^(1), ..., y^(τ))
在給定輸入序列 X = (x^(1), ..., x^(τ))
時的條件機率分佈 P(Y|X)
。
根據有向圖模型的鏈式法則,這個條件機率可以分解為:
P(Y|X) = Π_{t=1}^τ P(y^(t) | y^(1), ..., y^(t-1), X)
在標準的 RNN 結構中,由於馬爾可夫假設(當前輸出主要依賴於當前隱藏狀態,而當前隱藏狀態包含了歷史信息),這個分解通常可以簡化為:
P(Y|X) = Π_{t=1}^τ P(y^(t) | h^(t))
其中 h^(t)
依賴於 h^(t-1)
和 x^(t)
。
如果模型是純粹的生成模型(沒有外部輸入 X
),它也可以定義一個序列 Y
的聯合機率 P(Y) = Π_t P(y^(t) | y^(<t))
。
Q: 為什麼說 RNN 雖然看起來是局部連接的(例如,h^(t)
只直接依賴於 h^(t-1)
和 x^(t)
),但它能夠捕捉長程依賴關係?
A: 儘管 RNN 在時間上的直接連接是局部的(即 h^(t)
的計算只直接使用了 h^(t-1)
和 x^(t)
),但信息可以通過隱藏狀態 h
在時間序列中逐層傳播。
h^(t)
包含了來自 h^(t-1)
的信息,而 h^(t-1)
又包含了來自 h^(t-2)
的信息,以此類推。因此,在時間步 t
的隱藏狀態 h^(t)
理論上可以包含來自所有先前時間步 1, ..., t-1
的輸入 x^(1), ..., x^(t-1)
的信息摘要。
這使得 RNN 的輸出 y^(t)
能夠間接地依賴於遠早於 t
的輸入,從而有能力捕捉長程依賴關係。然而,在實踐中,標準 RNN 在捕捉非常長的依賴關係時可能會遇到梯度消失或梯度爆炸的問題。
由於後續的章節(10.3 雙向 RNN 到 10.12 外部記憶)涉及到更具體的 RNN 架構和技術,我將為每個主要的小節提供摘要和 Q&A。
10.3 雙向 RNN
重點摘要:
標準 RNN 在時間步 t
的預測 ŷ^(t)
只能利用過去的輸入 x^(1), ..., x^(t)
和當前的輸入 x^(t)
。然而,在許多應用中(如語音識別、手寫識別、生物信息學),當前輸出可能同時依賴於過去和未來的上下文。
雙向 RNN (Bidirectional RNN, BiRNN) (Schuster and Paliwal, 1997) 正是為了解決這個問題而提出的。它包含兩個獨立的 RNN:
- 一個前向 RNN (forward RNN),按正常的時間順序(從
t=1
到τ
)處理輸入序列,得到一系列前向隱藏狀態h⃗^(t)
。 - 一個反向 RNN (backward RNN),按相反的時間順序(從
t=τ
到1
)處理輸入序列,得到一系列反向隱藏狀態h⃖^(t)
。 在時間步t
的最終輸出o^(t)
通常是基於前向隱藏狀態h⃗^(t)
和反向隱藏狀態h⃖^(t)
的組合(例如,將它們拼接起來然後通過一個輸出層)。 圖 10.11 展示了雙向 RNN 的典型計算圖。BiRNN 在許多序列建模任務上都取得了比單向 RNN 更好的性能,因為它能夠利用完整的上下文信息。然而,它要求能夠一次性獲得整個輸入序列,因此不適用於需要實時預測(即在接收到完整序列之前就必須做出預測)的場景。
Q: 為什麼在某些序列建模任務中,僅僅利用過去的上下文信息是不夠的?雙向 RNN 試圖解決什麼問題?
A: 在許多序列建模任務中,對當前時間步的正確理解和預測不僅依賴於過去的上下文,還依賴於未來的上下文。例如:
- 自然語言理解: 一個詞的含義可能取決於它後面出現的詞(例如,在「我打籃球」和「我打電話」中,「打」的含義不同)。
- 語音識別: 一個音素的發音可能受到其後續音素的協同發音 (coarticulation) 影響。
- 手寫識別: 一個字符的識別可能需要參考其左右相鄰的字符。 標準的單向 RNN 只能利用過去和當前的輸入來進行預測,無法利用未來的上下文信息。 雙向 RNN (BiRNN) 試圖解決這個問題,它旨在讓模型在進行預測時能夠同時考慮到輸入序列中過去和未來的上下文。
Q: 雙向 RNN (BiRNN) 的基本結構是怎樣的?它如何結合過去和未來的上下文信息?
A: BiRNN 的基本結構包含兩個並行的、獨立的 RNN 層(或多層):
- 前向 RNN (Forward RNN): 這個 RNN 按照正常的時序(從序列的開始到結束)處理輸入序列,計算出一系列前向隱藏狀態
h⃗^(t)
。每個h⃗^(t)
總結了從序列開始到時間步t
的「過去」上下文信息。 - 反向 RNN (Backward RNN): 這個 RNN 按照相反的時序(從序列的結束到開始)處理輸入序列,計算出一系列反向隱藏狀態
h⃖^(t)
。每個h⃖^(t)
總結了從序列結束到時間步t
的「未來」上下文信息。 在每個時間步t
,最終的輸出(或用於預測的表示)是通過結合相應的前向隱藏狀態h⃗^(t)
和反向隱藏狀態h⃖^(t)
來得到的。結合的方式可以是拼接 (concatenation)、相加、取平均等。 通過這種方式,模型在時間步t
的決策可以同時利用x^(1), ..., x^(t)
(通過前向 RNN) 和x^(t), ..., x^(τ)
(通過反向 RNN) 的信息。
Q: 使用雙向 RNN 有什麼主要的優點和局限性?
A:
- 優點:
- 利用完整上下文: 能夠在每個時間步利用輸入序列的完整過去和未來上下文信息,這對於許多需要理解全局依賴的任務(如機器翻譯的編碼器、命名實體識別、情感分析等)非常重要,通常能帶來比單向 RNN 更好的性能。
- 局限性:
- 需要完整序列: 為了計算反向 RNN 的狀態,必須能夠一次性獲得整個輸入序列。這使得 BiRNN 不適用於那些需要對正在輸入的序列進行實時預測(即在接收到完整序列之前就必須輸出結果)的在線 (online) 任務,例如實時語音識別的解碼或實時時間序列預測。
- 計算成本略高: 相對於單向 RNN,BiRNN 的參數數量和計算量大約是其兩倍(因為有兩個獨立的 RNN)。
接下來的摘要將繼續涵蓋 RNN 的不同架構和訓練挑戰。
10.4 編碼器-解碼器架構 (基於序列到序列的架構)
重點摘要: 許多人工智能任務可以被框定為將一個輸入序列映射到一個輸出序列,且輸入和輸出序列的長度可能不同。例如,語音識別(聲學特征序列到詞序列)、機器翻譯(源語言句子到目標語言句子)、問答(問題序列到答案序列)。 編碼器-解碼器 (Encoder-Decoder) 或 序列到序列 (Sequence-to-Sequence, Seq2Seq) 架構 (Sutskever et al., 2014; Cho et al., 2014a) 是為處理這類問題而設計的。它包含兩個主要的 RNN 組件:
- 編碼器 (Encoder): 一個 RNN,讀取整個輸入序列
x^(1), ..., x^(nx)
,並將其總結為一個固定大小的上下文表示C
(通常是編碼器 RNN 的最後一個隱藏狀態,或者所有隱藏狀態的某種池化)。 - 解碼器 (Decoder): 另一個 RNN,以編碼器產生的上下文表示
C
作為初始狀態(或輸入的一部分),然後逐個生成輸出序列y^(1), ..., y^(ny)
。在生成每個y^(t)
時,解碼器通常也會接收前一個生成的輸出y^(t-1)
作為輸入(在訓練時可能是導師驅動的真實值,在推斷時是模型自身的預測)。 圖 10.12 展示了這種架構。一個關鍵的挑戰是,單個固定大小的上下文向量C
可能難以承載長輸入序列的所有必要信息,這催生了後續的注意力機制。
Q: 什麼是編碼器-解碼器 (Encoder-Decoder) 或序列到序列 (Seq2Seq) 架構?它主要用於解決什麼類型的問題?
A: 編碼器-解碼器(或序列到序列)架構是一種基於循環神經網路的框架,專門設計用來處理那些輸入是一個序列而輸出也是一個序列的任務,特別是當輸入序列和輸出序列的長度可能不同的時候。 它主要用於解決以下類型的問題: * 機器翻譯: 將一種語言的句子(輸入序列)翻譯成另一種語言的句子(輸出序列)。 * 文本摘要: 將一篇較長的文檔(輸入序列)總結成一個較短的摘要(輸出序列)。 * 對話系統/聊天機器人: 將用戶的輸入語句(輸入序列)轉換為一個合適的回复語句(輸出序列)。 * 語音識別: 將聲學特征序列(輸入序列)轉換為文本轉錄(輸出序列)(儘管現代端到端語音識別也常使用其他架構)。 * 圖像描述生成: 將圖像(可以通過 CNN 編碼為一個序列或向量)轉換為描述圖像內容的文本序列。
Q: 編碼器-解碼器架構包含哪兩個主要的 RNN 組件?它們各自的作用是什麼?
A:
- 編碼器 (Encoder) RNN:
- 作用: 讀取並處理整個輸入序列(例如,源語言句子中的詞嵌入序列)。它的目標是將輸入序列的信息壓縮和編碼成一個(通常是固定大小的)向量表示,這個向量被稱為上下文向量 (context vector) 或「思想向量 (thought vector)」。這個上下文向量應該包含了理解輸入序列並生成相應輸出序列所需的全部必要信息。通常,編碼器的最後一個時間步的隱藏狀態被用作上下文向量。
- 解碼器 (Decoder) RNN:
- 作用: 以編碼器產生的上下文向量作為初始狀態(或其輸入的一部分),然後逐個地、自回歸地生成輸出序列中的元素(例如,目標語言句子中的詞語)。在生成每個輸出元素時,解碼器通常也會考慮它在前一個時間步生成的元素。
Q: 傳統的編碼器-解碼器架構在處理長輸入序列時可能會遇到什麼主要問題?
A: 主要問題是信息瓶頸 (information bottleneck)。編碼器需要將整個(可能是非常長的)輸入序列的所有相關信息都壓縮到一個固定大小的上下文向量中。當輸入序列非常長時,這個固定大小的向量很難有效地捕捉和保留所有必要的信息,特別是序列早期部分的信息可能會在編碼過程中丟失或被稀釋。這會導致解碼器在生成輸出序列時,尤其是在需要依賴輸入序列早期信息的長輸出序列時,性能下降。
10.5 深度循環網路
重點摘要:
標準 RNN 的計算可以分解為三個參數塊及其相關的變換:從輸入到隱藏狀態 (U
),從前一個隱藏狀態到當前隱藏狀態 (W
),以及從隱藏狀態到輸出 (V
)。可以通過增加這些塊的深度(即使用 MLP 替換這些仿射變換)來創建深度循環網路 (Deep RNN)。
- 增加輸入到隱藏、隱藏到隱藏、隱藏到輸出的映射深度: 例如,將
h^(t) = tanh(Wh^(t-1) + Ux^(t) + b)
中的Wh^(t-1) + Ux^(t) + b
替換為一個 MLP 的輸出。 - 堆疊多個循環層: 類似於堆疊多個前饋層,可以將一個 RNN 的隱藏狀態序列作為另一個 RNN 的輸入序列,從而形成一個具有多個循環隱藏層的深度 RNN。 實驗表明,增加適當的深度通常能夠提高 RNN 的性能,允許模型學習更複雜的序列模式和層次化表示。然而,過深的 RNN 也可能更難訓練。圖 10.13 展示了幾種可能的深度 RNN 結構。
Q: 什麼是深度循環網路 (Deep RNN)?它可以通過哪些方式來增加「深度」?
A: 深度循環網路 (Deep RNN) 是指那些在其計算路徑中引入了額外非線性層或堆疊了多個循環層的循環神經網路,目的是增加模型的表達能力和學習層次化表示的能力。
增加「深度」的方式主要有:
1. 加深狀態轉移函數: 在計算當前隱藏狀態 h^(t)
時,將傳統的單個仿射變換加非線性激活(例如,tanh(Wh^(t-1) + Ux^(t) + b)
)替換為一個更深的多層感知機 (MLP)。也就是說,從 h^(t-1)
和 x^(t)
到 h^(t)
的映射本身是一個小的深度前饋網路。
2. 加深從隱藏狀態到輸出的映射: 類似地,將從隱藏狀態 h^(t)
到輸出 o^(t)
的映射(通常是 Vh^(t) + c
)替換為一個 MLP。
3. 堆疊多個循環層 (Stacked RNN): 將多個 RNN 層堆疊起來。第一層 RNN 處理原始輸入序列,其輸出(隱藏狀態序列)作為第二層 RNN 的輸入序列,以此類推。每一層都可以學習不同抽象級別的序列表示。
Q: 為什麼要在 RNN 中引入深度?它可能帶來什麼好處?
A: 在 RNN 中引入深度的主要目的是:
- 增強模型表達能力: 深度結構允許模型學習更複雜的、非線性的函數和數據表示,從而能夠捕捉序列中更複雜的模式和依賴關係。
- 學習層次化表示: 類似於深度前饋網路和卷積網路,深度 RNN(特別是堆疊的 RNN)有潛力學習數據的層次化時間表示。較低層的 RNN 可能學習局部的、短期的模式,而較高層的 RNN 可能在這些模式的基礎上學習更全局的、長期的結構。
- 提高性能: 在許多序列建模任務上,實驗表明,適當增加 RNN 的深度通常能夠帶來性能的提升。
Q: 增加 RNN 的深度是否總是有益的?它可能帶來什麼挑戰?
A: 增加 RNN 的深度並非總是有益的,它也可能帶來一些挑戰:
- 優化困難: 非常深的 RNN 可能更難訓練,更容易出現梯度消失或梯度爆炸的問題(儘管像 LSTM/GRU 這樣的門控單元以及梯度裁剪等技術有助於緩解這些問題)。
- 計算成本增加: 更深的網路通常意味著更多的參數和更大的計算量,導致訓練和推斷時間增加。
- 過擬合: 如果訓練數據不足,過深的網路更容易發生過擬合。 因此,需要根據具體任務和數據集來選擇合適的深度,並配合適當的正則化和優化策略。
接下來是關於遞歸網路、長期依賴、回聲狀態網路等更具體的 RNN 相關技術。
10.6 遞歸神經網路
重點摘要: 遞歸神經網路 (Recursive Neural Network) 是循環神經網路的一個推廣,它不是沿著線性序列進行操作,而是作用於一個層次化的樹狀結構(例如,自然語言句子的句法分析樹,或化學分子的結構)。 在遞歸網路中,相同的轉移函數(帶有共享參數)被遞歸地應用於樹的子結構,以計算父節點的表示。例如,一個父節點的表示可以由其子節點的表示通過一個神經網路層來計算。 這種結構允許模型捕捉基於層次結構的組合語義。例如,在自然語言處理中,可以從詞的表示開始,逐步組合成短語的表示,再到句子的表示。 與 RNN 類似,遞歸網路也可以展開為一個計算圖(一個樹狀的 DAG),並使用反向傳播(稱為樹形反向傳播, backpropagation through structure)來計算梯度。圖 10.14 展示了一個典型的遞歸網路計算圖。
Q: 什麼是遞歸神經網路 (Recursive Neural Network)?它與標準的循環神經網路 (RNN) 在處理的數據結構上有何主要區別?
A: 遞歸神經網路是一種神經網路,它通過對一個層次化的樹狀結構(而不是線性序列)進行遞歸操作來處理數據。 與標準 RNN 的主要區別在於: * RNN: 主要處理線性序列數據,其循環連接是沿著時間軸(或序列的線性順序)進行的。 * 遞歸 RNN: 處理具有樹狀結構的數據,其遞歸操作是基於輸入數據的層次結構(例如,從葉節點向根節點,或反之)進行的。相同的神經網路模塊被遞歸地應用於樹的不同子結構。
Q: 遞歸神經網路通常應用於哪些類型的任務?請舉例說明。
A: 遞歸神經網路通常應用於那些輸入數據本身具有自然層次結構或樹狀結構的任務。例如:
- 自然語言處理:
- 句法分析 (Syntactic Parsing): 學習句子的句法結構樹。
- 情感分析: 基於句子的句法結構來判斷其情感傾向(例如,一個短語的情感可能由其組成詞的情感以及它們之間的句法關係決定)。
- 語義組合性 (Semantic Compositionality): 學習如何將詞語的含義組合成短語或句子的含義。
- 化學信息學/藥物發現: 處理分子結構(可以表示為圖或樹)。
- 計算機視覺: 處理場景的層次化結構。
- 程序語言處理: 分析代碼的抽象語法樹 (AST)。
Q: 遞歸神經網路是如何學習和傳播信息的?
A: 遞歸神經網路通過在其輸入的樹狀結構上遞歸地應用一個相同的神經網路模塊(帶有共享的權重)來學習和傳播信息。 通常,信息是從樹的葉節點向根節點(自底向上)傳播的: 1. 樹的葉節點(例如,句子中的詞語)首先被轉換為初始的向量表示(例如,詞嵌入)。 2. 然後,對於樹中的每個非葉節點,其表示是通過將其子節點的表示作為輸入,送入一個共享的神經網路層(例如,一個標準的前饋層或更複雜的組合函數)來計算得到的。 這個過程遞歸地進行,直到計算出樹的根節點的表示,這個根節點的表示通常被用來代表整個輸入樹的語義或結構信息,並用於後續的任務(如分類)。 也可以設計自頂向下傳播信息的遞歸網路。
由於後續的章節涉及到 RNN 訓練中的具體挑戰和更高級的架構,我將繼續為每個主要小節提供摘要和 Q&A。
10.7 長期依賴的挑戰
重點摘要: 循環神經網路的一個核心挑戰是學習和處理序列中的長期依賴 (long-term dependencies) 關係,即當前輸出可能依賴於很久以前的輸入。 梯度消失/爆炸 (Vanishing/Exploding Gradients) 問題是導致 RNN 難以捕捉長期依賴的主要原因 (Hochreiter, 1991a; Bengio et al., 1994a)。當通過時間反向傳播 (BPTT) 計算梯度時,梯度信號需要沿著時間序列反向傳播多個時間步。在這個過程中,梯度可能會因為與權重矩陣的重複相乘而呈指數級減小(梯度消失)或指數級增大(梯度爆炸)。
- 梯度消失: 使得模型難以學習到遠距離歷史信息對當前狀態的影響,因為來自遠處的梯度信號在傳播到早期時間步時變得非常微弱。
- 梯度爆炸: 使得學習過程不穩定,梯度可能變得非常大,導致參數更新過大,損失函數可能變為 NaN。 圖 10.15 展示了重複組合函數(類似 RNN 中的狀態轉移)如何導致輸出對輸入的敏感度(Jacobian 的模)急劇變化。 儘管存在這些問題,但 RNN 在許多情況下仍然是有效的,特別是當依賴關係不是非常長,或者使用了更先進的架構(如 LSTM, GRU)和訓練技巧時。
Q: 什麼是 RNN 中的「長期依賴 (long-term dependencies)」問題?
A: 長期依賴問題是指在序列數據中,當前時間步的輸出或狀態可能依賴於序列中很久以前(即相隔多個時間步)的輸入或狀態。標準的 RNN 在學習和捕捉這種跨越長時間間隔的依賴關係時會遇到困難。
Q: 導致 RNN 難以學習長期依賴的主要原因是什麼?請解釋梯度消失和梯度爆炸。
A: 主要原因是梯度消失 (vanishing gradients) 和梯度爆炸 (exploding gradients) 問題,這些問題在通過時間反向傳播 (BPTT) 計算梯度時尤為突出。
- 梯度消失: 在 BPTT 過程中,梯度從後面的時間步向前面的時間步傳播。如果 RNN 狀態轉移函數的 Jacobian 矩陣的奇異值(或權重矩陣的模)在多次連乘後持續小於 1,那麼梯度信號在反向傳播的過程中會呈指數級衰減,導致傳播到較早時間步的梯度變得非常小(接近於零)。這使得模型參數(特別是那些影響早期狀態的參數)無法從遠距離的未來信息中得到有效的學習信號,從而難以學習長期依賴。
- 梯度爆炸: 相反,如果 Jacobian 矩陣的奇異值(或權重矩陣的模)在多次連乘後持續大於 1,那麼梯度信號在反向傳播的過程中會呈指數級增大,導致梯度變得非常大。這會使得基於梯度的優化過程非常不穩定,參數更新步長過大,可能導致損失函數震盪甚至發散 (NaN)。
Q: 梯度消失和梯度爆炸問題對 RNN 的訓練有何影響?
A:
- 梯度消失的影響:
- 模型難以學習到輸入序列中遠距離的上下文信息。
- 訓練收斂緩慢,或者模型可能收斂到一個只能捕捉短期依賴的次優解。
- 梯度爆炸的影響:
- 訓練過程不穩定,損失函數可能突然增大或變成 NaN。
- 參數更新過大,可能導致模型跳過最優解。
- 需要使用很小的學習率,進一步減慢訓練速度。
10.8 回聲狀態網路
重點摘要: 回聲狀態網路 (Echo State Network, ESN) (Jaeger, 2003; Maass et al., 2002) 以及相關的液態機 (Liquid State Machine, LSM) (Maass et al., 2002) 採用了一種不同的策略來處理循環網路的訓練困難。 ESN 的核心思想是將循環隱藏層(稱為「儲存池」, reservoir)的權重固定下來(通常是隨機生成的,並滿足某些條件以確保「回聲狀態屬性」),而只學習從儲存池到輸出的讀出 (readout) 連接的權重。 「回聲狀態屬性」指的是儲存池的狀態應該是輸入歷史的一個「回聲」,即它能夠以一種非線性的方式捕捉和混合過去的輸入信息,並且這個內部狀態最終會「遺忘」遙遠的過去(即對初始狀態不敏感)。 由於儲存池的權重是固定的,訓練讀出層的權重就變成了一個簡單的線性回歸(或其他線性模型)問題,可以非常高效地解決,例如使用偽逆法。 ESN 和 LSM 避免了訓練循環權重時的梯度消失/爆炸問題,並且訓練速度非常快。然而,它們的性能可能不如端到端訓練的、精心設計的 RNN(如 LSTM),並且儲存池的設計(如大小、稀疏度、譜半徑)本身也需要一定的技巧和調整。
Q: 什麼是回聲狀態網路 (ESN)?它的核心思想是什麼?
A: 回聲狀態網路 (ESN) 是一種特殊的循環神經網路,其核心思想是:
- 固定的、隨機的循環隱藏層 (儲存池, Reservoir): ESN 包含一個大規模的、連接稀疏或稠密的循環隱藏層,稱為「儲存池」。這個儲存池的內部權重(循環權重和輸入到儲存池的權重)在初始化後通常是固定不變的,不需要通過梯度下降等方法進行訓練。這些權重通常是隨機生成的,但需要滿足某些條件以確保網絡具有「回聲狀態屬性」。
- 可訓練的讀出層 (Readout Layer): 只有從儲存池的狀態到最終輸出的連接權重(即「讀出層」)是可訓練的。 ESN 的目標是讓固定的儲存池能夠將輸入的時間序列映射到一個高維的、動態豐富的內部狀態空間,然後從這個內部狀態空間中線性地「讀出」所需的輸出。
Q: ESN 中的「回聲狀態屬性 (echo state property)」指的是什麼?為什麼它很重要?
A: 「回聲狀態屬性」是指儲存池(循環隱藏層)的內部狀態應該是輸入歷史的一個漸近穩定的「回聲」。具體來說,它意味著:
- 漸近遺忘初始狀態: 經過足夠長的時間後,儲存池的當前狀態應該主要由最近的輸入歷史決定,而對網絡的初始狀態不敏感(即「洗掉」初始條件的影響)。
- 輸入的可區分性: 不同的輸入歷史應該導致儲存池產生不同的內部狀態軌跡,使得讀出層能夠區分它們。 回聲狀態屬性很重要,因為它確保了儲存池的動態行為是良好定義的、穩定的,並且能夠有效地表示輸入序列的信息,從而使得簡單的線性讀出層能夠從中學習到有用的映射。如果網絡不具備這個屬性(例如,如果儲存池的動態是混沌的或不穩定的),那麼訓練讀出層就會非常困難。
Q: 相比於標準的、端到端訓練的 RNN,ESN 有哪些主要的優點和缺點?
A:
- 優點:
- 訓練極快: 由於只有讀出層的線性權重需要訓練,可以使用高效的閉式解(如偽逆法)或快速的線性回歸算法,訓練速度遠快於需要 BPTT 的標準 RNN。
- 避免梯度消失/爆炸: 因為循環部分的權重是固定的,不存在訓練循環權重時的梯度消失或梯度爆炸問題。
- 概念相對簡單: 模型結構和訓練過程相對簡單。
- 缺點:
- 性能可能受限: 由於儲存池是隨機生成的且固定的,其表示能力可能不如經過端到端優化的 RNN(如 LSTM、GRU)那樣針對特定任務進行了特化。在許多複雜的序列建模任務上,ESN 的性能可能不如精心調整的現代 RNN。
- 儲存池設計依賴經驗和試錯: 儲存池的性能高度依賴於其超參數的選擇(如大小、連接稀疏度、權重的譜半徑等),而這些超參數的選擇往往缺乏理論指導,需要大量的經驗和試錯。
- 不學習輸入到隱藏層的表示: 模型不能像標準 RNN 那樣學習如何從原始輸入中提取最有用的特徵來驅動循環動態。
接下來是關於解決長期依賴的更高級 RNN 架構。
10.9 滲漏單元和其他處理多時間尺度的策略
重點摘要: 為了解決 RNN 中的長期依賴問題,研究者提出了多種策略,核心思想是創建能夠在不同時間尺度上操作的路徑。
- 時間維度的跳躍連接 (Skip Connections across Time): (Lin et al., 1996) 允許信息從較早的時間步直接跳躍到較晚的時間步,從而為梯度提供「捷徑」,使其更容易反向傳播到遠距離的過去。
- 滲漏單元 (Leaky Units): 引入一種機制,使得隱藏單元的狀態是其前一時刻狀態和當前輸入驅動的新狀態的線性組合(或加權平均)。例如,
μ^(t) ← αμ^(t-1) + (1-α)v^(t)
。如果α
接近 1,信息可以長時間保持;如果α
接近 0,信息快速被替換。α
可以是固定的,也可以是可學習的門控函數。 - 刪除連接 (Removing Connections): 在某些情況下,可以通過刪除 RNN 狀態中的某些連接來明確地將信息隔離在不同的時間尺度上操作。
10.9.1 時間維度的跳躍連接
重點摘要:
在時間維度上引入跳躍連接是指在 RNN 的展開圖中,除了相鄰時間步之間的連接外,還添加從 h^(t)
到 h^(t+d)
(其中 d > 1
) 的直接連接。這為梯度提供了一條更短的反向傳播路徑,有助於緩解梯度消失問題,使得模型更容易學習到跨越 d
個時間步的依賴關係。
Q: 在 RNN 中引入「時間維度的跳躍連接」是如何幫助處理長期依賴的?
A: 時間維度的跳躍連接(或延遲連接)允許信息和梯度在時間序列中「跳過」中間的時間步,直接從較早的時間步傳播到較晚的時間步(前向傳播),或者從較晚的時間步反向傳播到較早的時間步(反向傳播)。 這有助於處理長期依賴,因為: 1. 提供梯度「捷徑」: 梯度在反向傳播時,除了通過逐個時間步的標準路徑外,還可以通過這些跳躍連接形成的更短路徑進行傳播。這減少了梯度在長距離傳播過程中因多次與 Jacobian 矩陣相乘而衰減或爆炸的風險。 2. 直接建模長程交互: 跳躍連接使得模型能夠更直接地學習到相隔較遠時間步之間的依賴關係。
10.9.2 滲漏單元和一系列不同時間尺度
重點摘要:
滲漏單元通過對隱藏狀態進行類似於指數移動平均的更新,來維持一個隨時間緩慢變化的狀態。狀態 μ^(t)
是前一時刻狀態 μ^(t-1)
和由當前輸入 v^(t)
驅動的新值的加權平均:μ^(t) ← αμ^(t-1) + (1-α)v^(t)
。
參數 α
控制了時間尺度:
- 當
α
接近 1 時,狀態變化緩慢,信息可以保持很長時間(長記憶)。 - 當
α
接近 0 時,狀態變化快速,主要反映當前輸入(短記憶)。 不同的隱藏單元可以具有不同的α
值,從而使網路能夠在多個時間尺度上同時操作。這種思想在 LSTM 和 GRU 等門控 RNN 中得到了更精細的實現。
Q: 什麼是滲漏單元 (leaky unit)?它如何幫助 RNN 處理不同時間尺度的信息?
A: 滲漏單元是一種循環單元的設計,它通過對其內部狀態進行一種「滲漏式」的更新來維持信息。其狀態更新規則通常類似於一個指數移動平均:
s^(t) = α s^(t-1) + (1-α) input^(t)
其中 s^(t)
是在時間 t
的狀態,input^(t)
是由當前外部輸入和可能的其他循環連接驅動的更新,α
是一個介於 0 和 1 之間的「滲漏」係數或「記憶」係數。
- 如果
α
接近 1,那麼前一時刻的狀態s^(t-1)
在很大程度上被保留,狀態變化緩慢,使得單元能夠保持長期的記憶。 - 如果
α
接近 0,那麼前一時刻的狀態很快被遺忘,狀態主要由當前輸入決定,使得單元更側重於短期的信息。 通過讓 RNN 中的不同滲漏單元具有不同的滲漏係數α
(有些α
接近 1,有些接近 0),網路就可以同時在多個時間尺度上處理和存儲信息,從而有助於捕捉不同長度的依賴關係。
10.9.3 刪除連接
重點摘要: 另一種處理多時間尺度的策略是通過在 RNN 狀態的不同部分之間「刪除」某些連接,來創建在不同時間尺度上操作的模塊。例如,可以設計一個 RNN,其中一部分隱藏單元更新較快(例如,每個時間步都更新),而另一部分隱藏單元更新較慢(例如,每隔幾個時間步才更新一次,或者其更新依賴於快速更新單元的某種觸發信號)。這可以讓模型在細粒度時間尺度上處理快速變化的信息,同時在粗粒度時間尺度上整合和保持長期信息。
Q: 「刪除連接」如何被用來讓 RNN 在不同時間尺度上操作?
A: 「刪除連接」在這裡的含義更廣泛,指的是通過設計特定的連接模式或更新機制,使得 RNN 的不同部分(或不同的隱藏單元組)在事實上以不同的有效時間尺度進行更新和信息傳播。
例如,可以設計一個層次化的 RNN 結構:
* 低層 RNN: 以較快的頻率更新其狀態,處理輸入序列的細節和短期模式。
* 高層 RNN: 以較慢的頻率從低層 RNN 接收信息(例如,低層 RNN 每隔 k
個時間步才向高層 RNN 提供一次輸入,或者高層 RNN 的更新依賴於低層 RNN 狀態的某種池化或門控信號)。高層 RNN 因此能夠在更長的時間尺度上整合信息並捕捉長期依賴。
通過這種方式,雖然所有單元可能在每個名義上的時間步都參與計算,但由於信息的選擇性流動和更新頻率的差異,實際上形成了在不同時間尺度上操作的模塊。
接下來是關於門控 RNN(LSTM 和 GRU)以及更高級的序列建模技術。
10.10 長短期記憶和其它門控 RNN
重點摘要: 實際應用中最有效的序列模型是那些引入了門控機制 (gating mechanism) 的 RNN,如長短期記憶 (Long Short-Term Memory, LSTM) (Hochreiter and Schmidhuber, 1997) 和門控循環單元 (Gated Recurrent Unit, GRU) (Cho et al., 2014c 等)。 門控 RNN 的核心思想是引入一些「門 (gates)」,這些門是特殊的神經網路單元,它們可以學習控制信息在循環單元內部以及單元之間的流動。這些門可以決定哪些信息應該被遺忘,哪些新的信息應該被存儲,以及哪些信息應該被輸出。 這種精細的控制機制使得門控 RNN 能夠更有效地學習和保持長期依賴關係,並在很大程度上緩解了標準 RNN 中的梯度消失/爆炸問題。
10.10.1 LSTM
重點摘要:
LSTM (Hochreiter and Schmidhuber, 1997; Gers et al., 2000) 是最早被提出並被證明在處理長期依賴方面非常有效的門控 RNN。
LSTM 單元的核心是一個稱為「細胞狀態 (cell state)」s^(t)_i
的內部記憶,它可以看作是信息在時間上傳輸的「傳送帶」。LSTM 通過三個主要的門來控制細胞狀態中的信息:
- 遺忘門 (Forget Gate)
f^(t)_i
: (公式 10.40) 決定應該從前一個細胞狀態s^(t-1)_i
中丟棄多少信息。它查看h^(t-1)
和x^(t)
,並為細胞狀態的每個元素輸出一個介於 0 和 1 之間的值(0 表示完全遺忘,1 表示完全保留)。 - 輸入門 (Input Gate)
g^(t)_i
: (公式 10.42) 決定哪些新的信息(來自一個候選的更新值,通常由tanh
層產生)應該被存儲到細胞狀態中。 - 輸出門 (Output Gate)
q^(t)_i
: (公式 10.44) 決定細胞狀態的哪些部分(經過tanh
變換後)應該被輸出作為當前時間步的隱藏狀態h^(t)_i
(公式 10.43)。 細胞狀態的更新是通過遺忘門選擇性地遺忘舊信息,然後通過輸入門選擇性地添加新信息來實現的 (公式 10.41)。 LSTM 的這種門控結構使得梯度可以長時間地流動而不衰減,從而能夠學習到非常長的依賴關係。LSTM 在語音識別、機器翻譯、語言建模等許多序列任務上都取得了巨大成功。圖 10.16 展示了 LSTM 單元的內部結構。
Q: 什麼是長短期記憶 (LSTM) 網路?它的核心創新是什麼?
A: 長短期記憶 (LSTM) 網路是一種特殊的循環神經網路 (RNN),專門設計用來解決標準 RNN 在處理長期依賴關係時遇到的梯度消失和梯度爆炸問題。 其核心創新是引入了一個稱為細胞狀態 (cell state) 的內部記憶單元,以及一系列門控機制 (gating mechanisms)(遺忘門、輸入門、輸出門)來精細地控制信息流入、流出以及在細胞狀態中的保持。
Q: LSTM 單元包含哪三個主要的門?它們各自的功能是什麼?
A:
- 遺忘門 (Forget Gate)
f^(t)
:- 功能: 決定哪些信息應該從前一個時間步的細胞狀態
s^(t-1)
中被丟棄或遺忘。它根據當前輸入x^(t)
和前一時刻的隱藏狀態h^(t-1)
計算一個介於 0 和 1 之間的向量,該向量的每個元素作用於s^(t-1)
的相應元素(0 表示完全遺忘,1 表示完全保留)。
- 功能: 決定哪些信息應該從前一個時間步的細胞狀態
- 輸入門 (Input Gate)
g^(t)
: (注意:教材中g^(t)
是輸入門的激活值,實際上有兩個部分:一個 sigmoid 層決定哪些值需要更新,一個 tanh 層產生候選更新值)- 功能: 決定哪些新的信息應該被添加到當前的細胞狀態
s^(t)
中。它也由兩部分組成:- 一個 sigmoid 層(輸入門本身)決定細胞狀態的哪些位置需要被更新。
- 一個 tanh 層創建一個候選的更新值向量。 這兩部分的乘積被加到細胞狀態上。
- 功能: 決定哪些新的信息應該被添加到當前的細胞狀態
- 輸出門 (Output Gate)
q^(t)
:- 功能: 決定細胞狀態的哪些部分(經過 tanh 非線性變換後)將作為當前時間步的隱藏狀態
h^(t)
輸出。它根據當前輸入x^(t)
和前一時刻的隱藏狀態h^(t-1)
計算一個介於 0 和 1 之間的向量,然後將其與經過 tanh 處理的細胞狀態相乘得到最終的隱藏狀態輸出。
- 功能: 決定細胞狀態的哪些部分(經過 tanh 非線性變換後)將作為當前時間步的隱藏狀態
Q: LSTM 中的「細胞狀態 (cell state)」扮演什麼角色?它與隱藏狀態 (hidden state) 有何不同?
A:
- 細胞狀態
s^(t)
: 可以被看作是 LSTM 單元的內部記憶核心,信息可以在其中長時間地流動而幾乎不衰減(如果遺忘門允許)。它主要負責存儲和傳遞跨越長時間間隔的信息。細胞狀態的更新是通過門控的加法和乘法操作,這有助於保持梯度的穩定流動。 - 隱藏狀態
h^(t)
: 是 LSTM 單元在時間步t
的外部輸出,它通常是基於當前細胞狀態(經過輸出門的過濾和可能的非線性變換)計算得到的。隱藏狀態h^(t)
會被傳遞到網路的下一層(如果是堆疊 LSTM)或用於當前時間步的最終預測,並且也會作為輸入影響下一時間步 LSTM 單元的門和細胞狀態的計算。 簡而言之,細胞狀態是 LSTM 的內部「長期記憶」,而隱藏狀態是基於這個長期記憶和當前上下文計算得到的「短期工作記憶」和輸出。
10.10.2 其他門控 RNN
重點摘要: 除了 LSTM,還存在其他設計的門控 RNN,其中最著名的是門控循環單元 (Gated Recurrent Unit, GRU) (Cho et al., 2014c; Chung et al., 2014, 2015a 等)。 GRU 相較於 LSTM 結構更簡單,它只有兩個門:
- 更新門 (Update Gate)
u
: (公式 10.46) 類似於 LSTM 中的遺忘門和輸入門的組合。它決定了在多大程度上保留前一個隱藏狀態,以及在多大程度上接受由當前輸入和候選隱藏狀態計算得到的新信息。 - 重置門 (Reset Gate)
r
: (公式 10.47) 決定了在計算候選隱藏狀態時,應該在多大程度上忽略前一個隱藏狀態的信息。 GRU 的隱藏狀態更新公式 (公式 10.45) 直接結合了這兩個門的作用。 GRU 通常比 LSTM 具有更少的參數,在某些任務上可能更容易訓練且性能相當。LSTM 和 GRU 的選擇往往取決於具體的應用和經驗。
Q: 什麼是門控循環單元 (GRU)?它與 LSTM 在結構上有何主要區別?
A: 門控循環單元 (GRU) 是另一種流行的門控 RNN 架構,旨在解決標準 RNN 的長期依賴問題。
與 LSTM 的主要區別在於:
1. 門的數量: GRU 有兩個門(更新門和重置門),而 LSTM 有三個門(遺忘門、輸入門、輸出門)。
2. 細胞狀態: GRU 沒有像 LSTM 那樣明確的、獨立的細胞狀態 s^(t)
。它的隱藏狀態 h^(t)
直接承擔了信息存儲和傳遞的功能。
3. 參數數量: 由於門的數量較少且沒有獨立的細胞狀態,GRU 的參數數量通常比具有相同隱藏單元大小的 LSTM 要少。
總體而言,GRU 可以被看作是 LSTM 的一個簡化版本,它試圖用更少的組件來實現類似的控制信息流動的功能。
Q: GRU 中的更新門 (update gate) 和重置門 (reset gate) 各自的作用是什麼?
A:
- 更新門
u^(t)
:- 作用: 控制在多大程度上將前一個時間步的隱藏狀態
h^(t-1)
的信息「複製」到當前時間步的隱藏狀態h^(t)
,以及在多大程度上接受由當前輸入x^(t)
和經過重置門調節的前一隱藏狀態計算得到的「候選」新隱藏狀態。更新門的值接近 1 時,更多地保留舊狀態;接近 0 时,更多地接受新狀態。
- 作用: 控制在多大程度上將前一個時間步的隱藏狀態
- 重置門
r^(t)
:- 作用: 控制在計算「候選」新隱藏狀態時,應該在多大程度上「忘記」或「重置」前一個時間步的隱藏狀態
h^(t-1)
的信息。如果重置門的輸出接近 0,那麼在計算候選隱藏狀態時,h^(t-1)
的影響就會大大減小,使得候選狀態主要由當前輸入x^(t)
決定。
- 作用: 控制在計算「候選」新隱藏狀態時,應該在多大程度上「忘記」或「重置」前一個時間步的隱藏狀態
Q: 在實踐中,選擇 LSTM 還是 GRU 通常基於什麼考慮?
A: 在實踐中,選擇 LSTM 還是 GRU 並沒有一個絕對的定論,通常基於以下考慮:
- 經驗和實驗: 對於特定的任務和數據集,研究者可能會嘗試兩種架構,並根據驗證集的性能來選擇表現更好的一個。
- 計算資源和訓練時間: GRU 由於參數較少,通常比 LSTM 計算更快,訓練時間可能更短。如果計算資源有限或對訓練速度有要求,可能會傾向於選擇 GRU。
- 數據量: 在數據量較小的情況下,參數更少的 GRU 可能比 LSTM 更不容易過擬合。
- 任務複雜性: 對於非常複雜的、需要捕捉極其精細的長期依賴的任務,LSTM 由於其更複雜的門控結構,有時可能表現得稍好一些。但在許多任務上,兩者的性能往往非常接近。 總之,這是一個經驗性的選擇,通常建議都進行嘗試。
10.11 優化長期依賴
重點摘要: 除了使用門控 RNN(如 LSTM, GRU),還有其他一些技術旨在幫助 RNN 學習長期依賴關係,主要是通過改善梯度在時間序列中的傳播。
- 梯度裁剪 (Gradient Clipping): (Mikolov, 2012; Pascanu et al., 2013a) 是一種簡單但非常有效的解決梯度爆炸問題的方法。它在反向傳播計算出梯度後,如果梯度的范數超過一個預設的閾值
v
,就將梯度向量按比例縮小,使其范數等於v
(公式 10.48, 10.49)。這可以防止梯度過大導致的學習不穩定,但它並沒有解決梯度消失的問題。 - 引導信息流的正則化: 旨在鼓勵梯度能夠更好地流動。例如,Pascanu et al. (2013a) 提出了一個正則化項
Ω = Σ_t ( || (∇_{h^(t)}L) (∂h^(t)/∂h^(t-1)) || / ||∇_{h^(t)}L || - 1 )^2
(公式 10.52),它懲罰那些使得從h^(t)
反向傳播到h^(t-1)
的梯度(即(∇_{h^(t)}L) (∂h^(t)/∂h^(t-1))
)的范數顯著偏離∇_{h^(t)}L
的范數的情況。這鼓勵 Jacobian∂h^(t)/∂h^(t-1)
的作用更接近於保持梯度范數不變。
10.11.1 截斷梯度
重點摘要: 梯度裁剪 (Gradient Clipping) 是一種在訓練 RNN 時常用的穩定化技術,主要用於防止梯度爆炸。
- 工作原理: 在通過時間反向傳播 (BPTT) 計算得到梯度向量
g
後,檢查其范數(通常是 L2 范數)||g||
。如果||g||
超過一個預設的閾值v
,則將梯度向量g
按比例縮放,使其范數等於v
:g ← (v/||g||) g
。如果||g|| ≤ v
,則梯度保持不變。 - 作用: 它有效地限制了單次參數更新的步長,防止由於梯度爆炸導致的損失函數發散或參數更新過大而跳過最優解。
- 局限性: 梯度裁剪主要解決梯度爆炸問題,但它不能解決梯度消失問題。此外,選擇合適的裁剪閾值
v
通常需要一些經驗和實驗。
Q: 什麼是梯度裁剪 (gradient clipping)?它主要用於解決 RNN 訓練中的什麼問題?
A: 梯度裁剪是一種在訓練神經網路(特別是循環神經網路)時用來處理梯度爆炸 (exploding gradients) 問題的技術。 梯度爆炸是指在反向傳播過程中,梯度值變得非常大,導致基於梯度的優化算法(如 SGD)的參數更新步長也變得非常大,從而使得學習過程不穩定,損失函數可能劇烈震盪甚至變成 NaN(Not a Number)。 梯度裁剪通過在梯度更新參數之前,對梯度向量的范數(通常是 L2 范數)設定一個上限(閾值)。如果計算得到的梯度向量的范數超過了這個閾值,就將梯度向量按比例縮小,使其范數等於該閾值。如果范數未超過閾值,則梯度保持不變。
Q: 梯度裁剪是如何工作的?請描述其基本步驟。
A: 基本步驟如下:
- 通過反向傳播算法(例如 BPTT)計算出損失函數關於模型參數的梯度向量
g
。 - 計算梯度向量的范數
||g||
(通常是 L2 范數sqrt(Σ g_i^2)
)。 - 設定一個預定義的裁剪閾值
v
。 - 比較
||g||
和v
:- 如果
||g|| > v
(即梯度發生了「爆炸」),則對梯度向量g
進行縮放:g_clipped = (v / ||g||) * g
。這樣,g_clipped
的方向與原始梯度g
相同,但其范數被限制在v
。 - 如果
||g|| ≤ v
,則梯度保持不變:g_clipped = g
。
- 如果
- 使用裁剪後的梯度
g_clipped
來更新模型參數。
Q: 梯度裁剪能否解決梯度消失問題?為什麼?
A: 不能。梯度裁剪主要是為了解決梯度爆炸問題,它通過限制梯度的最大范數來防止參數更新過大。 梯度消失問題是指梯度在反向傳播過程中變得非常小(接近於零),導致模型參數(特別是影響早期時間步的)幾乎不更新,從而難以學習長期依賴。梯度裁剪不會放大已經很小的梯度,因此它對梯度消失問題沒有直接的幫助。解決梯度消失問題通常需要依賴於更先進的 RNN 架構(如 LSTM、GRU)、更好的初始化方法或更精細的優化策略。
10.12 外部記憶
重點摘要: 標準 RNN(即使是 LSTM 或 GRU)的記憶容量有限,主要存儲在其固定大小的隱藏狀態向量中。對於需要處理非常長的序列或需要精確回憶大量信息的任務,這種內部記憶可能不夠。 外部記憶 (External Memory) 機制旨在為神經網路提供一個類似於計算機內存的、可讀寫的大容量存儲空間。網路可以學習如何與這個外部記憶進行交互,例如,將信息寫入記憶、從記憶中讀取相關信息,並利用這些信息來輔助其計算和決策。
- 神經圖靈機 (Neural Turing Machine, NTM) (Graves et al., 2014) 和 可微神經計算機 (Differentiable Neural Computer, DNC) (Graves et al., 2016) 是著名的帶有外部記憶的架構。它們包含一個控制器(通常是 RNN 或前饋網路)、一個外部記憶矩陣,以及用於與記憶交互的讀寫頭 (read/write heads)。控制器學習生成控制讀寫頭操作的指令(例如,讀取哪個記憶位置、寫入什麼內容、注意力權重等)。
- 注意力機制與外部記憶: 讀寫操作通常基於注意力機制,允許讀寫頭選擇性地關注記憶的不同部分。可以是基於內容的尋址 (content-based addressing)(根據查詢與記憶內容的相似性)或基於位置的尋址 (location-based addressing)(直接指定記憶地址)。
- 優勢: 外部記憶顯著增強了模型處理長程依賴和執行需要大量事實知識或精確回憶的任務(如算法學習、知識庫問答)的能力。
- 挑戰: 訓練帶有外部記憶的網路通常更複雜,優化更困難,並且如何設計高效且可擴展的記憶交互機制仍然是一個活躍的研究領域。 圖 10.18 展示了一個外部記憶網路的示意圖。
Q: 為什麼標準 RNN(包括 LSTM 和 GRU)在處理需要極長記憶的任務時可能會遇到瓶頸?
A: 因為標準 RNN 的「記憶」主要存儲在其固定大小的隱藏狀態向量中。儘管 LSTM 和 GRU 通過門控機制改進了信息的長期保持能力,但隱藏狀態的容量畢竟是有限的。當需要處理的序列非常長,或者任務需要精確回憶和操作大量分散在序列中的信息時,這個固定大小的隱藏狀態可能難以有效地存儲所有必要的歷史信息,導致信息丟失或「遺忘」。
Q: 什麼是外部記憶 (external memory) 在神經網路中的概念?它試圖解決什麼問題?
A: 外部記憶在神經網路中的概念是指為神經網路(通常是 RNN 控制器)配備一個額外的、可讀寫的、通常容量較大的存儲模塊,類似於計算機系統中的 RAM。神經網路可以學習如何與這個外部記憶進行交互,例如,將計算的中間結果或輸入的重要信息寫入記憶,並在需要時從記憶中讀取相關信息來輔助其後續的計算和決策。 它試圖解決的問題是標準 RNN 內部記憶容量有限的瓶頸,旨在增強模型處理以下類型任務的能力: * 需要記憶和利用非常長的歷史上下文。 * 需要精確回憶和操作大量離散的事實或知識(例如,執行簡單算法、基於知識庫的問答)。 * 需要進行更複雜的、多步的推理。
Q: 神經圖靈機 (NTM) 或可微神經計算機 (DNC) 通常包含哪些主要組件?它們是如何與外部記憶交互的?
A: NTM 或 DNC 通常包含以下主要組件:
- 控制器 (Controller): 通常是一個神經網路(例如,前饋網路或 LSTM/GRU)。控制器接收外部輸入和從記憶中讀取的信息,並負責生成與外部記憶交互的指令。
- 外部記憶 (External Memory): 一個(通常是二維的)矩陣,用於存儲信息。記憶中的每一行可以被看作一個記憶槽 (memory slot)。
- 讀頭 (Read Head(s)): 用於從外部記憶中讀取信息。讀頭的操作通常基於注意力機制,控制器生成一個注意力權重分布,指示讀頭應該從記憶的哪些位置(或以何種加權組合)讀取信息。可以是基於內容的尋址(根據查詢與記憶內容的相似性)或基於位置的尋址。
- 寫頭 (Write Head(s)): 用於向外部記憶中寫入或修改信息。寫頭的操作也通常基於注意力機制,控制器生成一個注意力權重分布來決定寫入的位置,以及要寫入的內容和可能的擦除操作。 控制器、記憶和讀寫頭共同構成一個可微的系統,可以通過端到端的梯度下降進行訓練。
Q: 基於內容的尋址 (content-based addressing) 和基於位置的尋址 (location-based addressing) 在外部記憶網路中有何不同?
A:
- 基於內容的尋址: 讀取或寫入記憶的位置是根據一個「查詢向量」(由控制器生成)與記憶中存儲的內容之間的相似性來決定的。控制器計算查詢向量與記憶中每個記憶槽內容的相似度得分,然後將這些得分轉換為一個注意力權重分布,用於加權讀取或寫入。這種方式允許模型根據內容的相關性來檢索信息。
- 基於位置的尋址: 讀取或寫入記憶的位置是直接由控制器指定的(或者通過一些更依賴於先前訪問位置的機制來確定,例如,順序訪問或跳轉到特定偏移量的位置)。這種方式允許模型執行更類似於傳統計算機程序中對內存地址的直接操作。 現代的外部記憶網路(如 DNC)通常會結合使用這兩種尋址方式,以提供更靈活和強大的記憶交互能力。