輕鬆理解 Transformers (3): Feed-Forward Layer 部分
編者按:隨著人工智慧技術的不斷髮展Transformer架構已經成為了當今最為熱門的話題之一。前饋層作為Transformer架構中的重要組成部分,其作用和特點備受關注。本文透過淺顯易懂的語言和生活中的例子,幫助讀者逐步理解Transformers中的前饋層。
本文是Transformers系列的第三篇。作者的觀點是:前饋層在Transformer架構中扮演著至關重要的角色,它能夠有效地提高計算效率,同時也是集體智慧的體現。
文章作者首先介紹了前饋層的基本結構,它由全連線層組成,進行線性變換和線性計算。但也存在侷限性,不能進行復雜的非線性變換。所以前饋層需要啟用函式(如ReLU)進行非線性轉換,增強網路的表達能力。為防止模型僅記憶資料特徵而不具備推理能力,需要使用正則化技術如dropout。相信透過本文的閱讀,讀者將對Transformer中的前饋層有更深入的理解。
隨著深度學習在語音、影像、自然語言處理等領域取得突破,人工智慧或許正向著真正的通用人工智慧邁進。但要培養通用人工智慧,我們還需不斷深入理解其中的原理和相關機制。
以下是譯文,enjoy!
本節將介紹前饋層(Feed-Forward layer),這是大多數深度學習架構中的基礎元素。在有關深度學習的常見話題交流時,一般都會強調它們在構造 Transformer 架構中的重要作用。
原論文中的圖片[1]
前饋全連線層(feed-forward linear layer)基本上就是一堆神經元,每個神經元都與其他神經元相連線。請看下圖,其中a、b、c和d是神經元。這些神經元包含了一些 input(即一些我們想要理解的資料(畫素值(pixels)、詞嵌入(word embeddings)等))。它們與編號為1的神經元相連。每兩個神經元之間的連線都有不同的連線權重值(connection strength)。例如,a-1是0.12,b-1是-0.3,等等。實際上,左列中的所有神經元都與右列中的所有神經元相連。但是為了清晰起見,我沒有在影像中展示全部的連線,你需要了解這一情況。就像圖中有a-1一樣,還應該有a-2、b-2、c-2、d-3等。兩個神經元之間的每個連線都有不同的“連線權重”。
該圖由原文作者繪製
該架構有兩點值得注意:
-
如前所述,每個節點(神經元)都與其他節點相連。所有的a、b、c、d都與其他神經元(1、2、3)相連。可以將這幅影像看作是一條軍隊指揮鏈。1、2、3是指揮官。他們從士兵a、b、c、d那裡得到情報。a知道某件事情的一些細節,但它的情報不夠全面。1知道的就更多了,因為它能夠從a、b、c和d那裡同時得到情報。2和3也是指揮官,同樣從a、b、c、d那裡獲取情報。這些指揮官(1、2、3)也會向更上層的指揮官傳遞報告。在他們之後的指揮官既從a、b、c、d那裡得到情報,也從1、2、3那裡得到情報,因為下一層(每列神經元為一層)也是以完全相同的方式進行全連線的。因此,首先要明白的是, 1 的情報比 a 更全面,而下一層指揮官的情報也比 1 更全面。
-
第二點需要注意的是,每個節點與下一層的每個其他節點之間的連線權重是不同的。a-1是0.12,b-1是-0.3。我在這裡給出的數字顯然是虛構的,但它們也是在合理的範圍內,並且它們都是自動學習調整的引數(learned parameters)(例如,它們在訓練過程中會發生變化)。把這些數字看作是 1 對 a、b 等的影響程度。從1號指揮官的角度來看,a的情報有一定的可信度。但不應該想當然地相信他說的每一句話,可以選擇性地相信他說的某些話。b則截然不同。這個節點通常會低估它接收到的輸入(情報)的重要性,就像一個悠閒的人一樣。“這是一隻tiger嗎?不,只是一隻big cat。” 這是對發生的事情的過度簡化,但重要的是要注意這一點: 每個神經元都掌握著一些input(無論是原始輸入還是經過處理的input)並進行處理後將其傳遞下去。
你知道“傳話遊戲”嗎?你和其他 10 個人坐成一排,然後你向下一個人耳語一個詞,比如說“Pizza”。第 2 個人聽成了類似“Pazza”的詞,於是他們把“Pazza”傳給了第 3 個人。第 3 個人聽成了 “Lassa”(畢竟是耳語),於是他把 “Lassa”傳給了第 4 個人。第 4 個人聽成了 “Batata”,於是他又轉述了 “Batata”,以此類推。當你問第 10 個人他聽到了什麼?結果他回答“Shambala”,我們是怎麼從“Pizza”到“Shambala”的?這個遊戲與神經網路的區別在於,每個人都會對資訊進行處理。第二個人不會說 “Pazza”,他會說“Pazza 是義大利菜,很好吃”。第三個人會說:“Lassa是一道義大利菜,在全世界都很常見”,等等。每個人(層)都會補充一些他們希望有用的東西。
基本情況就是這樣。 每個神經元獲得輸入,處理輸入,然後繼續傳遞。 為了與全連線層(fully connected layer)相匹配,我建議對這個遊戲進行升級:從現在開始,在遊戲中引入多行人,每個人都可以對每一行中的其他人說悄悄話。從每一行的第 2 位開始,每個人都會收到很多人的悄悄話,他們需要了解每個人說的話語的“權重”(重要性),這就是前饋層(Feed Forward Layer)。
為什麼我們要使用前饋層?因為它們使我們的計算能夠更加有效,可以將其類比為集體智慧的體現。 講一個關於“猜測一頭牛重量”的故事吧!1906年,在英國的某個地方,有人把一頭牛帶到一個展覽會上。主持人隨機挑選了 787 名觀覽者,請他們猜測這頭牛的重量。你認為他們猜測的結果會是多少?這頭牛的實際體重是多少呢?
他們猜測的平均值是 1197 磅(542 公斤)。這些都是隨機抽取的群眾對牛體重的估計。這個平均猜測值離真實重量相差多遠呢?只有1磅差距,也就是450克。這頭牛的重量是1198磅。這個故事來自這裡[2],我不確定細節是否準確,但回到本文的主題,我們可以把線性層 (譯者 注:此處即本文所說的前饋層) 看作是在做類似的事情。透過增加更多的引數、更多的計算(更多的猜測),就可以得到更準確的結果。
照片由 Larry Costales[3] 在 Unsplash[4] 上釋出
讓我們試著想象一個真實的使用場景。給神經網路輸入一張圖片,讓它判斷圖片裡的是蘋果還是橙子。這種架構基於卷積神經網路(CNN)層,本文不會深入討論這個知識點,因為其超出了本系列文章的範圍。但該層是一個能夠學習和識別影像中特定模式(specific patterns)的計算層。 (譯者注:這些特定模式的識別有助於網路進行更準確的分類和判斷,例如判斷影像中是蘋果還是橙子。) 每一層都能識別更復雜的模式。例如,第一層幾乎不能識別出任何東西,該層只是傳遞原始畫素,第二層就能夠識別出垂直線條。如果下一層同時接收到有垂直線條的資訊,並從其他神經元那裡聽說還有非常接近的垂直線條。它會將兩者綜合起來進行計算、分析,然後思考:不錯!這是一個角落。這就是從多個來源獲取輸入資訊的好處。
我們可能會認為,進行計算的次數越多,得到的結果就越好。但事實上,並非完全是這樣,但確實有一定的道理。如果我們做更多的計算,諮詢更多人(神經元)的意見,通常就能得出更好的結果。
01 啟用函式 Activation Function
接下來將介紹深度學習中另一個非常重要的基本概念的關鍵組成部分——啟用函式,並探討它與Transformer的關係,以便更好地理解兩者之間的關聯。
儘管全連線層(Fully connected layers)的使用非常廣泛,但也存在一個很大的缺點—— 它們是線性層(linear layers),只能進行線性變換和線性計算。全連線層可以進行加法和乘法運算,但無法以“創造性”的方式轉換輸入(input)。有時候,僅僅增加計算量是不夠的,需要以完全不同的思考方式來解決問題。
如果我每天工作10個小時,每天賺10美元,如果我想更快地存下1萬美元,我可以每週工作更多天,或者每天工作更多小時。但是肯定還有其他解決方案,對吧?有很多人不需要他們擁有的錢(我可以更好地利用它),或者我可以找到更高薪的工作等等。解決辦法並不總是千篇一律。
同理,在本文的情況下,啟用函式可以來提供幫助。啟用函式能夠幫助我們進行非線性變換(non-linear transformation)。例如,將一個數字列表[1, 4, -3, 5.6]轉換為機率分佈,就是Softmax啟用函式的作用。該啟用函式能夠將這些數字轉換為[8.29268754e-03, 1.66563082e-01, 1.51885870e-04, 8.24992345e-01]這樣的輸出。這5個數字相加等於1。雖然這些數字看起來有些混亂,但 e-03 表示第一個數字(8)在小數點後3個零開始(例如0.00,然後是82926。實際上該數字是0.00829268754)。 這個Softmax啟用函式將整數轉換為0到1之間的浮點數,轉換後的浮點數仍然保持了原始整數之間的相對大小關係。這種保持相對大小關係的特性在統計學中非常有用。
還有其他型別的啟用函式,其中最常用的之一是ReLU(修正線性單元)。這是一種非常簡單(同時也非常有用)的啟用函式,它能夠將任何負數轉化為0,而非負數保持不變。非常簡單且實用。如果我將列表[1, -3, 2]輸入ReLU函式,會得到[1, 0, 2]。
在介紹完複雜的Softmax之後,你可能會期望一些更復雜的東西,但有人曾經告訴我“Luck is useful”。有了啟用函式後,我們就走運了。
我們之所以需要這些啟用函式,是因為非線性關係(nonlinear relationship)無法透過線性計算(全連線層)來表示。如果我每工作一小時就能得到 10 美元,那麼收入就是線性關係。如果我每連續工作 5 個小時,接下來的 5 個小時就能增加 10%,那麼這種關係就不再是線性的了。我的工資不再是工作小時數乘以固定的小時工資。 在文字生成等更復雜的任務中使用深度學習,就是因為我們要建模的關係高度非線性。 在“我喜歡”之後能出現的詞並不是固定的。
ReLU 的一大優勢,也許可以解釋它為何被廣泛使用,就是 對大量資料進行計算的成本非常低。 當神經元數量較少時(比方說幾萬個),計算量並不重要。但是當像大語言模型那樣使用數千億個神經元時,一種更高效的計算方式會帶來巨大差異。
02 正則化 Regularization
在解釋Transformer中如何實現正則化(非常簡單)之前,我們將介紹最後一個概念——dropout,這是一種正則化技術。由於演算法是基於資料的,並且它們的任務是儘可能逼近訓練目標,所以對於一個大腦聰明的人來說,有時僅僅記住一點點東西就足夠了。正如我們在學校中所受到的教育,學習複雜的邏輯並不總是有用的,我們有時只需記住我們所見過的,或者記住與之接近的東西。第二次世界大戰是什麼時候發生的?嗯...它受到了第一次世界大戰、經濟危機、人民憤怒等等因素的影響...大約是1917年左右...所以我們就說是1928年吧。記住確切的日期可能更好。
可以想象,這對機器學習來說並不是好事。如果我們需要的是已經有答案的問題的答案,我們就不需要這些複雜的技術了。我們需要一個聰明的演算法,因為我們無法記住所有的東西。我們需要它進行實時推理,進行思考。 正則化(Regularization)是讓演算法僅學習不記憶的一系列技術的總稱。在這些正則化技術中,一種常用的技術就是dropout。
03 Dropout
dropout可以說是一種相當簡單的技術。還記得我們說過全連線層(fully connected layers)是完全連線的嗎?dropout打破了這種邏輯。dropout技術將“連線權重(connection strength)”設定為0,這意味著該連線不會產生任何影響。對於1號指揮官來說,連線到士兵“a”的輸入變為 0 時,“a”傳遞的情報會變得完全無用。不回答,不肯定,也不否定。 我們在每一層中使用dropout技術時,會隨機選擇一定數量的神經元(由開發者配置),並將它們與其他神經元的連線權重設為0。 每次指揮官會被迫忽略不同計程車兵,因此無法記住其中任何一個士兵,因為下次可能不會再遇到它們傳遞情報。
04 回到Transformer!
現在我們已經掌握了理解Transformer中前饋層工作原理所需的所有基礎知識。接下來解釋實現過程就會非常簡單了。It will now be very simple.
圖片來自 Vaswani, A. 等人的論文[5]
在原論文中的架構圖中,前饋線性層只做了四件事情:
-
對文字中的每個位置(用向量表示),進行逐位置的線性計算。
-
對線性運算的輸出應用ReLU函式。
-
對上一步驟ReLU運算的輸出進行再一次線性運算。
-
最後,將其新增到第 3 層的輸出中。
就是這樣。如果你有深度學習領域的相關經驗,那麼理解這一部分對你來說可能很容易。如果你沒有經驗,可能稍顯吃力,但你已經理解了深度學習中一個極為重要的組成部分。
在下一部分,我們將介紹Transformer中的解碼器(Decoder)部分相關知識!
END
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70018536/viewspace-2992992/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 輕鬆理解 Transformers(2):Attention部分ORM
- 輕鬆理解 Transformers (4) :Decoder 和 Output 部分ORM
- 輕鬆理解 Spring AOPSpring
- 看動畫輕鬆理解「 堆 」動畫
- 輕鬆理解分庫分表
- 輕鬆理解HTTP快取策略HTTP快取
- 看圖輕鬆理解計數排序排序
- 【動畫】看動畫輕鬆理解「Trie樹」動畫
- 看圖輕鬆理解最小(大)堆
- 輕鬆理解JVM的分代模型JVM模型
- 輕鬆學習 JavaScript——第 3 部分:函式中的預設引數JavaScript函式
- 幾張圖輕鬆理解String.intern()
- 兩個案例輕鬆理解MyBatis中的TypeHandler!MyBatis
- 輕鬆理解建構函式和原型物件函式原型物件
- 輕鬆理解 Java 靜態代理/動態代理Java
- 輕鬆學習 JavaScript——第 8 部分:JavaScript 中的類JavaScript
- 輕鬆學習 JavaScript——第 1 部分:瞭解 let 語句JavaScript
- 輕鬆學習 JavaScript——第 6 部分:JavaScript 箭頭函式JavaScript函式
- 輕鬆學習 JavaScript——第 5 部分:簡化函式提升JavaScript函式
- Java 輕鬆理解深拷貝與淺拷貝Java
- 看動畫輕鬆理解時間複雜度(二)動畫時間複雜度
- 看動畫輕鬆理解時間複雜度(一)動畫時間複雜度
- 4個角度輕鬆理解 Flink中的Watermark
- 輕鬆使用“Explain Shell”指令碼來理解 Shell 命令AI指令碼
- 輕鬆學習 JavaScript——第 7 部分:物件屬性描述符JavaScript物件
- 輕鬆學習 JavaScript——第 4 部分:函式中的 arguments 物件JavaScript函式物件
- 看動畫輕鬆理解「遞迴」與「動態規劃」動畫遞迴動態規劃
- Kafka 架構圖-輕鬆理解 kafka 生產消費Kafka架構
- 5分鐘搞懂Kubernetes:輕鬆理解所有元件元件
- 看圖輕鬆理解資料結構與演算法系列(2-3樹)資料結構演算法
- 3D 穿梭效果?使用 CSS 輕鬆搞定3DCSS
- 辦公室革命,教你輕鬆搞定輕鬆玩轉ExcelExcel
- 輕鬆學習 JavaScript——第 2 部分:函式中的 Rest 引數JavaScript函式REST
- 輕鬆理解JS函式節流和函式防抖JS函式
- Pandas缺失值處理 | 輕鬆玩轉Pandas(3)
- 輕鬆理解UML用例圖時序圖類圖的教程時序圖
- 輕鬆Scrum之旅(下)Scrum
- 輕鬆Scrum之旅(上)Scrum