前一篇:《人工智慧模型學習到的知識是怎樣的一種存在?》
序言:在人工智慧領域,卷積神經網路(CNN)備受矚目,但神經網路的種類遠不止於此。實際上,不同型別的神經網路各有其獨特的應用場景。在接下來的幾節中,我將帶大家走近迴圈神經網路(RNN),深入瞭解其原理及其在處理人類自然語言中的改進與應用。
需要注意的是,目前自然語言處理領域主流的技術框架是基於 Transformer 架構的模型(如ChatGPT)。Transformer 克服了 RNN 在長序列上下文捕捉中的侷限性,並以更高的訓練效率和效能成為行業標準。我們在前面已經詳細介紹過 Transformer 的相關內容。
本節對 RNN 的介紹,旨在幫助大家理解人工智慧技術在序列建模領域的歷史演進,以及它是如何一步步發展到今天的狀態的。
在前面的幾章節中,我們瞭解瞭如何對文字進行分詞和序列化,將句子轉換為數字張量,然後將其輸入神經網路。接著,在上一章節中,我們進一步學習了嵌入方法,這是一種讓具有相似意義的單詞聚集在一起以便於計算情感的方式。這種方法效果非常好,正如你在構建諷刺分類器時所看到的那樣。然而,這種方法也有一個侷限性,那就是句子並不僅僅是單詞的集合——通常,單詞出現的順序會決定句子的整體意義。形容詞可以增強或改變它們所修飾名詞的意義。例如,“藍色”(blue)這個詞從情感角度可能毫無意義,“天空”(sky)這個詞亦然,但當你把它們組合成“藍天”(blue sky)時,就傳達出了一種通常是積極的情感。而有些名詞也可能限定其他名詞,比如“雨雲”(rain cloud)、“書桌”(writing desk)、“咖啡杯”(coffee mug)。
為了考慮到像這樣的序列資訊,我們需要一種額外的方法,那就是將迴圈性融入到模型架構中。在接下來的幾節中,我們將瞭解實現這一點的不同方法。我們將探討如何學習序列資訊,以及如何利用這些資訊來構建一種更能理解文字的模型:迴圈神經網路(RNN)。
迴圈的基礎
為了理解迴圈是如何工作的,首先讓我們回顧一下本書迄今為止所使用模型的侷限性。本質上,建立模型的過程有點像圖 7-1 所示。你提供資料和標籤,定義一個模型架構,模型學習將資料與標籤匹配的規則。這些規則隨後變成了一個 API,能夠為未來的資料返回預測標籤。
圖 7-1. 模型建立的高層檢視
不過,你可以看到,資料是被整體塞進去的。沒有涉及到任何細節,也沒有努力去理解資料出現的順序。這意味著,像“blue”(藍色)和“sky”(天空)這樣的詞,在“今天我很沮喪,因為天空是灰色的”(today I am blue, because the sky is gray)和“今天我很開心,有美麗的藍天”(today I am happy, and there’s a beautiful blue sky)這樣的句子中,它們的意義沒有任何區別。對於我們來說,這些詞的用法區別是顯而易見的,但對於一個像這裡所示架構的模型來說,真的沒有區別。
那麼我們該怎麼解決這個問題呢?首先,讓我們探討一下迴圈的本質,從這裡你就能瞭解基本的 RNN 是如何工作的。
考慮一下著名的斐波那契數列。如果你不熟悉它,我在圖 7-2中列出了一些數字。
圖 7-2. 斐波那契數列的前幾個數字
這個數列的理念是,每個數字都是它前面兩個數字的和。所以如果我們從 1 和 2 開始,下一個數字就是 1 + 2,等於 3。再下一個是 2 + 3,等於 5,然後是 3 + 5,等於 8,以此類推。
我們可以把這個過程放到一個計算圖中,得到圖 7-3。
圖 7-3. 斐波那契數列的計算圖表示
在這裡你可以看到,我們將 1 和 2 輸入到函式中,得到輸出 3。我們把第二個引數(2)帶到下一步,並與前一步的輸出(3)一起輸入函式。這次的輸出是 5,然後它與前一步的第二個引數(3)一起輸入函式,產生輸出 8。這個過程無限繼續,每一步的操作都依賴於之前的結果。左上角的 1 可以說是“存活”在整個過程中。它是被輸入到第二次運算的 3 的一部分,也是被輸入到第三次運算的 5 的一部分,等等。因此,1 的某種本質貫穿於整個序列,雖然它對整體數值的影響逐漸減小。
這類似於迴圈神經元的架構。你可以在圖 7-4中看到迴圈神經元的典型表示。
圖 7-4. 一個迴圈神經元
在一個時間步長中,一個值 x 被輸入到函式 F,因此通常標記為 xt。這會在該時間步產生一個輸出 y,通常標記為 yt。它還產生一個值,被前饋到下一步,這由從 F 指向它自己的箭頭表示。
如果你看看迴圈神經元在不同時間步中如何彼此協作,這會更清晰一些,你可以在圖 7-5中看到。
圖 7-5. 時間步中的迴圈神經元
在這裡,x₀ 被操作得到 y₀ 和一個傳遞到下一步的值。下一步獲取那個值和 x₁,產生 y₁ 和一個傳遞到下一步的值。再下一步獲取那個值和 x₂,產生 y₂ 和一個傳遞到下一步的值,就這樣一直下去。這和我們在斐波那契數列中看到的類似,我總覺得這是記住 RNN 工作原理的一個好記憶方法。
將迴圈擴充套件到語言
在上一節中,你看到了一個在多個時間步上執行的迴圈神經網路如何幫助在序列中保持上下文。實際上,RNN 將在本書後面用於序列建模。但是,當涉及到語言時,使用像圖 7-4 和圖 7-5 中那樣的簡單 RNN,可能會錯過一些細微之處。就像之前提到的斐波那契數列例子,被傳遞的上下文量會隨著時間的推移而減小。第 1 步神經元的輸出在第 2 步的影響很大,在第 3 步更小,在第 4 步更小,依此類推。
所以,如果我們有一句像“今天有一片美麗的藍色<…>”這樣的句子,“藍色”這個詞對下一個詞有很大的影響;我們可以猜測它很可能是“天空”。但是,如果上下文來自句子更前面的地方呢?例如,考慮這句話:“我住在愛爾蘭,所以在高中我不得不學習如何說和寫<…>。”
那個 <…> 是蓋爾語,但真正給我們上下文的詞是“愛爾蘭”,它在句子中更靠前的位置。因此,為了能夠識別 <…> 應該是什麼,我們需要一種方法來在更長的距離上保持上下文。RNN 的短期記憶需要變得更長,為此,發明了一種對架構的增強,稱為長短期記憶(LSTM)。
雖然我不會詳細介紹 LSTM 的底層架構是如何工作的,但如圖 7-6 所示的高層圖解傳達了主要觀點。要了解更多關於內部操作的內容,可以檢視 Christopher Olah 關於該主題的優秀博文。
LSTM 架構透過新增一個“細胞狀態”來增強基本的 RNN,這使得上下文不僅可以從一步到下一步保持,還可以在整個步驟序列中保持。記住這些是神經元,以神經元的方式學習,你可以看到這確保了重要的上下文會隨著時間被學習。
圖 7-6. LSTM 架構的高階檢視
LSTM 的一個重要部分是它可以是雙向的——時間步既向前又向後迭代,因此可以在兩個方向上學習上下文。請參見圖 7-7 獲取其高階檢視。
圖 7-7. LSTM 雙向架構的高階檢視
這樣,既進行了從 0 到 number_of_steps 的評估,也進行了從 number_of_steps 到 0 的評估。在每個步驟中,y 的結果是“前向”傳遞和“後向”傳遞的聚合。你可以在圖 7-8 中看到這一點。
圖 7-8. 雙向 LSTM
將每個時間步的每個神經元視為 F₀、F₁、F₂ 等。時間步的方向已顯示,所以在前向方向上對 F₁ 的計算是 F₁(→),在反向方向上是 (←)F₁。這些值被聚合以給出該時間步的 y 值。此外,細胞狀態也是雙向的。這對於管理句子中的上下文非常有用。再次考慮這句話:“我住在愛爾蘭,所以在高中我不得不學習如何說和寫<某物>”,你可以看到 <某物> 被“愛爾蘭”這個上下文詞限定了。但如果反過來呢:“我住在<這個國家>,所以在高中我不得不學習如何說和寫蓋爾語”?你可以看到,透過逆向遍歷句子,我們可以瞭解 <這個國家> 應該是什麼。因此,使用雙向 LSTM 對於理解文字中的情感非常強大(正如你將在第 8 章中看到的,它們對於生成文字也非常強大!)。
當然,LSTM,特別是雙向的,有很多複雜的過程,所以訓練會很慢。這時候,值得投資一個 GPU,或者至少在可能的情況下使用 Google Colab 的託管 GPU。
總結:本節我們介紹了迴圈神經網路(RNN),並探討了如何透過改進使其更好地應用於人類語言處理。下一節中,我們將深入討論 RNN 在自然語言處理中的具體應用及實現方法。