博客 / 詳情

返回

吳恩達深度學習課程五:自然語言處理 第一週:循環神經網絡 (二)循環神經網絡

此分類用於記錄吳恩達深度學習課程的學習筆記。
課程相關信息鏈接如下:

  1. 原課程視頻鏈接:[雙語字幕]吳恩達深度學習deeplearning.ai
  2. github課程資料,含課件與筆記:吳恩達深度學習教學資料
  3. 課程配套練習(中英)與答案:吳恩達深度學習課後習題與答案

本篇為第五課的第一週內容,1.2到1.4的內容。


本週為第五課的第一週內容,與 CV 相對應的,這一課所有內容的中心只有一個:自然語言處理(Natural Language Processing,NLP)
應用在深度學習裏,它是專門用來進行文本與序列信息建模的模型和技術,本質上是在全連接網絡與統計語言模型基礎上的一次“結構化特化”,也是人工智能中最貼近人類思維表達方式的重要研究方向之一。
這一整節課同樣涉及大量需要反覆消化的內容,橫跨機器學習、概率統計、線性代數以及語言學直覺。
語言不像圖像那樣“直觀可見”,更多是抽象符號與上下文關係的組合,因此理解門檻反而更高
因此,我同樣會儘量補足必要的背景知識,儘可能用比喻和實例降低理解難度。
本篇的內容關於循環神經網絡,在 NLP 中,循環神經網絡就像卷積網絡在 CV 中一樣,是處理序列數據的核心特化模型,專門用於捕捉上下文依賴。

1. NLP 中的符號規範

在正式開始引入循環神經網絡前,我們同樣需要先了解一些相關的符號規範,主要是在數據的表示方面。

1.1 模型的輸入與輸出

image.png
再複述一下:

  1. \(x^{<t>}\)輸入序列在第 \(t\) 個時間步的輸入
  2. \(y^{<t>}\)輸出序列在第 \(t\) 個時間步的輸出
  3. \(T_x\)輸入序列的長度
  4. \(T_y\)輸出序列的長度

現在,結合我們之前的符號規範,就可以知道:
\(X^{(n)<t>}\) 代表一批次輸入中第 \(n\) 個樣本的第 \(t\) 個元素。

1.2 詞典(Vocabulary)

經過上一部分,我們知道,\(x^{<t>}\) 代表了一個序列中的某一個元素。
但是又有一個新的問題:在 NLP 任務中,\(x^{<t>}\) 往往是一個離散的符號,例如某個具體的詞(如 helloHi),而神經網絡本質上只能處理數值向量,並不能直接理解“詞”這一抽象概念。

因此,在將文本序列送入模型之前,我們必須先完成一件事情:給“詞”一個能輸入網絡的表示方法,即建立一種從“詞”到“數值表示”的映射規則。
顯然,這種映射關係必須是確定且唯一的,即每一個詞都對應一個唯一的數值表示。
其中一種表示方法,就是我們在多分類標籤表示中使用的獨熱編碼
我們看一個簡單的示例:
假設我們當前的詞典只包含 4 個詞:

\[{\text{hello},\ \text{Hi},\ \text{thanks},\ \text{bye}} \]

我們可以為詞典中的每一個詞分配一個唯一的索引:

\[\text{hello}\rightarrow 1,\quad \text{Hi}\rightarrow 2,\quad \text{thanks}\rightarrow 3,\quad \text{bye}\rightarrow 4 \]

在這種設定下,每一個詞都可以用一個長度為 4 的獨熱向量來表示。
例如:

  • \(\text{hello}\) 對應的表示為:\(x = [1,0,0,0]\)
  • \(\text{Hi}\) 對應的表示為:\(x = [0,1,0,0]\)
    詞典中的每個詞都有且僅有一個位置為 1,其餘位置全部為 0。
    從模型的角度來看,這樣的表示方式意味着:模型在任意時刻接收到的輸入,本質上是一個高維稀疏向量,這正好滿足“詞 → 數值向量”的一對一映射要求,因此能夠直接作為神經網絡的輸入。

然而,在真實的 NLP 任務中,一個不可忽視的現實問題是:詞典的規模通常非常巨大。
在常見的語言建模或翻譯任務中,詞典大小往往達到數萬甚至百萬級別
這意味着:

  • 獨熱向量的維度極高
  • 向量極度稀疏
  • 計算和存儲成本都非常不經濟

因此,在實際模型中,我們往往會採用一種更緊湊、也更具語義表達能力的詞表示方法,叫做詞向量(Embedding) ,我們會在之後的內容詳細展開它。
image.png
此外,還會出現另一個問題: 測試或實際使用時,可能會遇到詞典中從未出現過的詞。
對於這種不在詞典中的詞(Out-Of-Vocabulary,OOV),常見的一種處理方式是在詞典中額外引入一個特殊標記<UNK>,用於統一表示所有未知詞,這種方式雖然簡單,但也會丟失不同未知詞之間的差異性,這也是後續子詞建模方法要解決的問題之一。

這些我們都會在之後的實際演示中詳細展開,現在,先了解簡單的符號規範後,我們正式開始引入循環神經網絡。

2. 循環神經網絡(Recurrent Neural Network,RNN)

在上一篇對序列模型的介紹中,我們已經知道:全連接網絡和卷積網絡並不適合用來處理序列數據。
我們需要一種模型,在處理當前輸入的同時,能夠保留並更新對“過去信息”的表示,讓模型在理解當前內容時,不是孤立地“看這一刻”,而是基於整個上下文來判斷。
而這,就是 RNN 的基本思想。
RNN最早可追溯到 Jordan(1986)對序列連接主義模型的研究,而現代深度學習中常用的 RNN 基本形式,則來源於 Elman 在1990年發表的一篇論文: Finding Structure in Time中提出的遞歸狀態網絡結構。
可以看到,儘管論文距今已有幾十年,但像最初的 CNN 一樣,RNN 的思想並沒有被時間淹沒,而是不斷被推廣和創新,最終成為現代 NLP 中不可或缺的基礎模型。

現在,我們用一個最簡單的單層循環神經網絡來介紹 RNN 的傳播過程及其特點。

2.1 單層循環神經網絡的結構

來看課程裏這樣一個循環網絡的傳播示意圖
image.png
你可能會覺得,這個結構看起來好像不像傳統意義上的“單層網絡”,反而更像每一層都直接接收原始輸入的全連接網絡。
其實這正體現了 RNN 與 FN 或 CNN 的本質區別:在 RNN 中,每個時間步的隱藏狀態不會直接傳給下一層,而是傳遞給下一個時間步的自身。
也就是説,這個網絡的實際結構是這樣的:
image.png
也就是説,RNN 本質上就是在全連接層基礎上加了時間維度的循環連接
你會發現,如果拋開傳播邏輯不看,單層循環網絡實際上就是一層全連接層。
但這也恰恰説明了它的傳播邏輯的重要性,到底是怎麼樣的設計能讓單層的全連接層一躍而成為 NLP 的基石?
我們繼續。

2.2 單層循環神經網絡的正向傳播

瞭解了 RNN 的基本邏輯後, 現在,我們就來演示一下單層 RNN 的具體傳播過程中的一些細節:
image.png
瞭解了這些後,我們規範一下單層 RNN 的正向傳播過程:

  1. 初始狀態
    RNN 在第一個時間步輸入第一個元素 \(x^{<1>}\)(例如“韓”)時,同時會引入初始的偽激活值 (\(a^{<0>}\)) 作為網絡的初始狀態,\(a^{<0>}\) 通常設為零向量或隨機初始化。
  2. 逐步處理序列
    每個時間步,RNN 會將當前輸入 \(x^{<t>}\) 與上一時間步的隱藏狀態 \(a^{<t-1>}\) 一起輸入網絡,計算當前的隱藏狀態 \(a^{<t>}\),例如在第二步,輸入為 \(x^{<2>}\)(“信”)和 \(a^{<1>}\),得到 \(a^{<2>}\)
  3. 輸出生成
    每一步的隱藏狀態 \(a^{<t>}\) 都會產生一個預測輸出 \(\hat{y}^{<t>}\)。輸出不僅依賴當前輸入,也包含了前面時間步的歷史信息,這就是 RNN 能夠“記憶”序列上下文的原因。
  4. 信息傳遞
    隱藏狀態會沿時間步向後傳遞,使後續時間步的輸出能夠利用之前所有的序列信息,最終一步輸出 \(\hat{y}^{<T_x>}\) 包含整個序列的信息,可用於完整序列的預測或判斷。

明白了傳播邏輯後,我們便可以更好地理解 RNN 正向傳播的公式表達,我們先説明一下網絡中的參數表示:
image.png
現在便擺出正向傳播的通式如下:

\[a^{<t>} = g(W_{aa} a^{<t-1>} + W_{ax} x^{<t>} + b_a) \]

\[y^{<t>} = g(W_{ya} a^{<t>} + b_y) \]

總結一下:RNN 的正向傳播就是每個時間步將當前輸入和上一隱藏狀態結合,更新當前隱藏狀態並生成輸出,隱藏狀態沿時間步傳遞,從而使網絡能夠逐步累積和利用序列歷史信息

瞭解了正向傳播的大致流程後,我們再看看 RNN 的反向傳播是如何進行的。

2.3 單層循環神經網絡的反向傳播

經過上一部分,我們已經知道:RNN 的正向傳播,本質上是在時間維度上反覆使用同一組參數,並通過隱藏狀態把歷史信息向後傳遞。

那麼問題自然就來了: 這些跨時間步傳遞的信息,反向傳播時該怎麼“算梯度”?

答案是: 怎麼過去就怎麼回來——RNN 的反向傳播,並不是在“層”之間傳播,而是在時間維度上反向傳播,這種傳播被稱為 BPTT(Backpropagation Through Time)
我們來簡要演示一下這個過程:
image.png

在監督學習中,反向傳播的起點永遠是損失函數,對於 RNN 來説,損失通常是所有時間步損失的累加(默認 \(T_x = T_y\)):

\[\mathcal{L} = \sum_{t=1}^{T_x} \mathcal{L}^{<t>}(\hat{y}^{<t>}, y^{<t>}) \]

也就是説,每一個時間步的輸出都會對總損失產生貢獻
而對於單步的損失,最常用的仍然是我們比較熟悉的交叉熵損失,你可以通過鏈接查看我們之前的介紹,應用在 RNN 中,它的公式是這樣的:

\[\mathcal{L} = \sum_{t=1}^{T_x} \left( - \sum_{k=1}^{C} y_k^{<t>} \log \hat{y}_k^{<t>} \right) \]

因此,反向傳播時,我們會從最後一個時間步開始,逐步向前,把每個時間步的誤差信號往回傳, 由於參數在所有時間步共享,每個時間步的損失都會通過時間鏈路對這些參數產生梯度貢獻,最終用於更新的梯度,是沿時間維度反向傳播後,各時間步貢獻的綜合結果

這就是單層循環神經網絡的反向傳播,這樣我們就對 RNN 的基本運行邏輯有了大體的瞭解。

3.總結

概念 原理 比喻
序列數據 數據元素具有明確順序,當前理解依賴歷史上下文 一句話的意思要從前往後讀,不能只看中間一個詞。
時間步 \(t\) 序列中第 \(t\) 個位置,用於展開時間維度 時間軸上的第 \(t\) 幀畫面。
輸入 \(x^{}\) \(t\) 個時間步送入模型的輸入向量 當前這一秒你聽到的一個詞。
預測輸出 \(\hat{y}^{}\) 模型在第 \(t\) 個時間步給出的預測結果 聽到一句話後,此刻你做出的判斷。
序列長度 \(T_x, T_y\) 輸入序列與輸出序列的長度(可相同或不同) 一段話的字數 vs 你回答時説了幾句話。
詞典(Vocabulary) 從詞到索引的一一映射表 電話簿:名字 ↔ 電話號碼
RNN 核心思想 當前狀態由當前輸入 + 過去狀態共同決定 你理解一句話時,會不斷修正之前的理解。
BPTT 梯度沿時間維度反向傳播 從句尾倒回去反思:是哪一步理解錯了。
梯度累積 參數梯度來自所有時間步的綜合貢獻 每一句話的錯誤都會影響你下次的理解方式。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.