Transformer:從入門到精通

學習一個深度學習模型,我們首先需要從理論的角度理解它的構架,進而理解代碼。

Transformer背景

首先我們知道,神經網絡有一個巨大的家族,其中的CNN(卷積神經網絡)源于視覺研究,目標是讓機器自動學習圖像特征,而RNN的出現是源于對記憶和序列建模的需求,目標是處理自然語言、語音等時序數據。循環神經網絡(RNN)的關鍵思想是:不僅考慮當前輸入,它還會記住之前的輸入信息,把歷史信息通過隱藏狀態(hidden state)傳遞到下一步,從而實現“記憶”。所以,RNN可以用于自然語言處理(機器翻譯、文本生成),語音處理(語音識別),時間序列預測(天氣預測)等。

在RNN之前,語言模型主要是采用N-Gram,即預測當前詞是什么的時候,我們只假設它和前面的N個詞相關。顯然這個模型并不靠譜,因為有時候關鍵信息藏在幾句話之前。所以RNN出現了,它理論上可以向前/前后看任意多詞:

雙向循環神經網絡結構

因此,RNN一定程度解決了N-Gram無法處理的問題(RNN詳解見循環神經網絡)。但是RNN也存在自己的不足:

1. RNN在處理長序列問題的時候,反向傳播梯度會變得極小或極大,造成梯度消失或梯度爆炸

2. RNN難以捕捉長距離的依賴關系

3. RNN必須逐步處理輸入,無法并行計算,訓練速度緩慢

針對以上問題,科學家們想到了通過引入單元狀態(cell state)的方法(長短時記憶網絡)。LSTM的輸入包括:當前時刻的輸入值x _t,上一時刻LSTM的輸出值h_{t-1},以及上一時刻的單元狀態c_{t-1}。LSTM的輸出包括:當前時刻輸出值h_t,和當前時刻單元狀態c_t。LSTM的關鍵就是怎樣控制長期狀態c。它引入了三個狀態開關,即三個門:

1. 遺忘門:它決定了上一個時刻的單元狀態c_{t-1}有多少保留到當前時刻單元狀態c_t

2. 輸入門:它決定當前時刻網絡輸入x _t有多少保留到單元狀態c_t

3. 輸出門:它控制單元狀態c_t有多少輸出到LSTM的當前輸出值h_t

LSTM的前向計算

這樣,遺忘門的控制可以保留很早期的信息,輸入門的控制又可以避免當前無關緊要的信息進入記憶,輸出門的控制又可以保證輸出結果中包含早期的記憶。LSTM的引入使RNN能保留長期的依賴信息,緩解了梯度消失/爆炸的問題。后來在LSTM的基礎上還發展出了GRU,Seq2Seq架構。但是,這些模型并沒有本質上解決長距離依賴和訓練效率低的問題。直到Transformer的出現。

(LSTM詳解見長短時記憶網絡(LSTM))

Transformer前言

一、獨熱編碼(One-Hot Encoding)

計算機只能處理0/1編碼,所以在面對文字的時候,我們需要一個詞表來表示詞(Token),即通過0/1將詞表示為高維度稀疏向量(維度高,但大部分元素是0)。但是這樣表示出來的句子無法包含上下文信息,詞與詞之間完全沒有關系。因此在此基礎上,我們引入了詞嵌入。

二、詞嵌入

所謂詞嵌入,就是為詞表中的每個詞分配一個詞向量,將其映射到語義空間中。這里語義空間維度表示詞向量的維度,語義空間維度越高,語義表達能力就越強。詞向量的每個值都是浮點數,詞向量之間的距離也和詞的語義距離有關。例如,我們可以將“紅蘋果”表示為 [0.13, 0.16, -0.89, 0.9] ,“青蘋果”表示為 [0.12, 0.17, -0.88, 0.9] ,兩者十分相似。常見的語義空間維度包括512(Transformer),12288(GPT3)。

三、嵌入矩陣

假設我們通過一個維度為D的語義空間表示了一個大小為V的詞表,則其中的每個Token都是一個維度為D的浮點向量,該詞表也就是一個\mathbb{R}^{V\times D}的矩陣。我們想要表示一個句子,那么在詞表中選擇我們用到的詞組成一個嵌入矩陣即可。例如“紅蘋果不是青蘋果”可以表示為:

X=\begin{bmatrix} 0.13 & 0.16 & -0.89 & 0.9 \\ 0.1 & -0.8 & 0.32 & 0.46 \\ 0.12 & 0.17 & -0.88 & 0.9 \end{bmatrix}

四、位置編碼

在實現通過嵌入矩陣表示一個句子之后,我們如何把每個詞在句子中的位置表示給模型呢,畢竟詞之間的位置差異也會反映詞向量的相關關系。這里,我們就需要用到位置編碼。與詞嵌入相似,位置編碼也是一種將句中位置關系映射到一個向量中的方法。Transformer的位置編碼為:

其中pos表示單詞在句子中的位置(0, 1, 2...),i表示當前維度的下標,即一個詞嵌入的第i個位置,d表示語義空間總維度。

這樣,假設詞向量維度D=4,則對于一個三個Token的句子,它的位置編碼矩陣為:

最后,Transformer再將詞嵌入矩陣與位置編碼矩陣相加,得到文本序列的詞和詞序信息。

至于這個位置編碼是如何設計出來的,可以參考博客:Transformer位置編碼設計原理詳解

自注意力機制

在圖像分類任務中,我們知道判斷圖像類別是通過對圖像的特征進行分析得到的,那么在序列中我們也可以通過觀察句子中特定的詞來理解句子的意思,這種對序列特征的觀察就叫注意力。因此對于一個句子,其中的每個Token都應該有不同的注意力權重,當然,這個權重是相對于任意兩個Token之間的關系來說的。

那么Transformer是怎么做的呢?

首先,假設我們得到了一個句子的兩個詞向量ij,該向量包含了位置編碼信息。現在,我們通過每個Token?x映射出三個向量,表示為:q,query;k,key和v,value。其中這個三個向量的維度可以和詞向量維度不同,v的維度可以和qk不同。這三個向量是如何映射得到的呢:

q=xW_{q}

k=xW_{k}

v=xW_{v}

其中W_{q} W_{k}W{v}為三個可學習的權重矩陣。假設Token的維度為128(1*128),則通過128*64的權重矩陣,我們可以得到一個1*64的q,k,v

接下來,我們計算ij的注意力和ji的注意力:

a_{ij}=q_{i}^{T}k_{j}

a_{ji}=q_{j}^{T}k_{i}

這樣,我們通過將兩個64*1和1*64的向量相乘,會得到兩個結果,當這兩個向量維度較大時,點積的數值幅度會顯著增大,導致訓練時梯度消失。為了解決這個問題,Transformer對點積的結果進行縮放,縮放因子為:\frac{1}{\sqrt{D_{qk}}}D_{qk}為向量維度,即:

a_{ij}=\frac{q_{i}^{T}k_{j}}{\sqrt{D_{qk}}}

a_{ji}=\frac{q_{j}^{T}k_{i}}{\sqrt{D_{qk}}}

當一個序列中有S個Token時,我們兩兩計算其注意力,可以得到一個S\times S的注意力矩陣,表示為:

A=\frac{Q^{T}K}{\sqrt{D_{qk}}}

接下來,我們對這個注意力矩陣進行歸一化,使其等同于概率分布。這里的歸一化是針對注意力矩陣的每一行進行的,即一個句子中的第i個Token(第i行),這樣,我們可以得到第i個Token相對于句子中其它Token的概率分布。

最后一步,我們會用到value矩陣V。假設一個句子有6個Token(S=6),則V矩陣會是一個6*64的結構,每一行表示一個Token的value,將其與A矩陣相乘(6*6):

Attention(Q,K,V) = Softmax(\frac{Q^{T}K}{\sqrt{D_{qk}}})V

可以得到一個6*64的矩陣,這個矩陣就是最終的注意力矩陣。

為什么Transformer要這樣做呢?

首先,Q^{T}K計算了句子中一個Token與另一個Token的匹配程度(注意力分數),矩陣中第i行第j列即表示了iToken對jToken的注意力。Softmax后我們就可以知道哪些位置相對來說更重要。而為了結合具體的語義信息,我們還需要將這個歸一化權重與句子的初始嵌入相乘得到加權詞矩陣,這樣,這個最后的矩陣就是“每個Token的新表示”矩陣,包括了上下文信息的矩陣。

部分內容參考:零基礎入門深度學習(9) - Transformer (2/3)

多頭注意力

多頭注意力機制,按其字面信息,即表示多個參數向量組——多個q,k,v向量。單頭注意力存在一定缺陷,每個序列的Token只能通過一個投影矩陣W_{q},W_{k},W_{v}去學習相關性和信息,但是語言的關系是多樣的(比如語法結構和語義依賴關系是兩種完全不同的語義空間),這樣,我們就需要多個注意力頭在不同的子語義空間計算注意力,關注一個序列的不同面。

為了不增加計算量和模型參數量,通常設置每個注意力頭的維度是原先的1/h,即:D_{hq}=D_{q}/h,D_{hk}=D_{k}/h, D_{hv}=D_{v}/h

計算過程:

首先不同投影矩陣(W_{i}^{Q},W_{i}^{K},W_{i}^{V})把輸入序列映射到多個子空間,每個子空間的維度是D_{hq},D_{hk},D_{hv}

在每個子空間分別計算注意力,得到多個head

拼接所有head的結果(n\times (h\cdot D))n為Token數,h為head數,D為子空間維度

W^{o}投影回原先語義空間維度

因果注意力

與普通的注意力不同,Transformer在生成文本時只能看到該位置之前的Token,因此與用于理解文本的雙向注意力相比,單向注意力機制——因果注意力會有所不同。這種單向注意力機制可以通過掩碼實現。

假設輸入序列的Token數為n,掩碼矩陣定義為:

不難發現,i\geqslant j表示允許當前位置和歷史位置交互,i<j表示禁止與未來位置交互,其中i表示q向量的位置,j表示k向量的位置,即i位置的注意力只能由i位置之前的Token決定。掩碼矩陣M實際上是一個上三角矩陣:

在計算注意力權重時,掩碼矩陣直接通過相加融入注意力矩陣:

Transformer整體架構

Transformer總體上采用編碼器+解碼器的結構:

首先,編碼器負責接收序列輸入inputs,輸出為編碼到語義空間的一系列Token。具體來說,輸入先轉換為詞嵌入,再引入位置嵌入,然后輸入多頭注意力層;接下來,殘差網絡的引入(Add)解決了梯度消失等問題(詳見ResNet);層歸一化(Norm)保證訓練穩定,加速模型收斂;FFN提供非線性變化,同時為Token內各個維度提供了信息整合的渠道,即Token向量內部變換。上述子串構成了一個編碼器層,一個完整的Transformer編碼器包含N個編碼器層。

解碼器負責生成新的序列。解碼序列中有兩個特殊的Token:[start]和[end],表示生成序列的開始與結束。

解碼器的結構和編碼器非常相似,除了兩點不同:第一點不同,解碼器只能根據已經生成的Token去生成新的Token,因此需要使用因果注意力機制,即用Masked Multi-Head Attention替代了編碼器中的Multi-Head Attention

第二點不同,解碼器在生成每個Token時,需要將編碼器的輸出序列也作為輸入序列的一部分,因此需要一個額外的Multi-Head Attention子層實現編碼器和解碼器的交叉注意力機制。具體來說,解碼器根據上一子層Masked Multi-Head Attention的輸出投影q向量,根據編碼器對應層的輸出投影kv向量,再根據注意力公式進行計算,從而使得解碼器輸出的Token可以融合編碼器輸出Token的信息。

一個完整的Transformer解碼器包含N個解碼器層,在Transformer的設計中,編碼器和解碼器層數相同。這樣,每個解碼器層都可以將對應的編碼器層輸出作為輸入,從而可以同步頂層、中層和低層信息。

解碼器最終如何輸出詞表中的詞呢?當解碼器的最后一個Transformer層輸出后,這個輸出經過一次線性變換Linear,將維度從詞向量維度D變為詞表的大小V,再經過Softmax歸一化后,使之產生概率的意義。即最后的輸出Output Probabilities是一個向量,其維度是詞表大小V,這個向量的每個元素對應詞表中的詞的預測概率。對這個概率進行采樣,就可以輸出對應的詞。

(以上內容參考零基礎入門深度學習(10) - Transformer (3/3))

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/94894.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/94894.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/94894.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

FOC開環控制代碼解讀

這段代碼實現了一個開環速度控制系統&#xff0c;用于控制電機轉速。它通過PWM控制器輸出電壓信號&#xff0c;來驅動電機轉動。具體來說&#xff0c;它在指定目標速度下&#xff0c;持續通過電壓信號進行控制。下面是對該代碼詳細流程的逐步解析&#xff1a; 1. 宏定義與變量初…

Ansible Playbook 調試與預演指南:從語法檢查到連通性排查

1&#xff1a;調試 playbook 時&#xff0c;最該先看哪一段輸出&#xff1f; 答&#xff1a;先查看ansible-navigator run的 PLAY RECAP 段落&#xff0c;它能一次性給出每臺受管主機的 ok、changed、unreachable、failed、skipped、rescued、ignored 等計數&#xff0c;快速定…

深入探討可視化技術如何實現安全監測

可視化在安全監測中的作用&#xff0c;遠超越了“美觀的圖表”這一表層概念。它是將抽象、混沌的安全數據轉化為直觀、可理解的視覺信息的過程&#xff0c;其核心價值在于賦能人類直覺&#xff0c;大幅提升認知與決策效率&#xff0c;從而實現對安全態勢的深度感知和快速響應。…

Scikit-learn Python機器學習 - Scikit-learn加載數據集

鋒哥原創的Scikit-learn Python機器學習視頻教程&#xff1a; 2026版 Scikit-learn Python機器學習 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili 課程介紹 本課程主要講解基于Scikit-learn的Python機器學習知識&#xff0c;包括機器學習概述&#xff0c;特征工程(數據…

如何在實際應用中選擇Blaze或Apache Gluten?

Blaze 與 Apache Gluten 深入研究報告&#xff1a;技術實現、性能對比與選型指南 一、項目背景與技術演進 1.1 大數據處理性能瓶頸與 Native 引擎興起 隨著大數據量處理需求的不斷增長&#xff0c;基于 JVM 的 Spark 在 CPU 密集型場景下的性能瓶頸日益凸顯。從 Spark 2.4 版本…

Mysql 學習感悟 Day 1 Mysql架構

Mysql 學習感悟 Day 1簡介具體流程如下&#xff1a;Server 層連接器查詢緩存分析器優化器執行器存儲引擎層更新語句是怎么執行的例子日志redo logbinlogmysql事務的二段提交Mysql官網 mysql安裝教程 Navicat免費安裝親測有用 簡介 大體來說&#xff0c;MySQL 服務端可以分為…

企業為什么需要部署數據防泄露系統?

在數字化轉型的浪潮中&#xff0c;企業核心數據已成為商業競爭的“生命線”。然而&#xff0c;數據泄露事件頻發&#xff0c;不僅可能導致巨額經濟損失&#xff0c;更會嚴重損害企業信譽。據IBM《2023年數據泄露成本報告》顯示&#xff0c;全球平均數據泄露成本已攀升至445萬美…

CPU的MBR寄存器和MDR寄存器

在學習計算機組成原理&#xff0c;特別是學到CPU時&#xff0c;寄存器是必須了解的一些器件&#xff0c;比如說程序計數器&#xff08;PC&#xff09;,指令寄存器&#xff08;IR&#xff09;等寄存器&#xff0c;同時&#xff0c;了解MDR和MBR這兩個寄存器也是必要的&#xff1…

QWidget和QML模式下阻止槽調用的方法總結

目錄 1.背景 2.QWidget中阻止槽函數調用的方法 2.1.臨時阻塞信號發射&#xff08;blockSignals()&#xff09; 2.2.斷開特定信號與槽的連接&#xff08;disconnect()&#xff09; 2.3.在槽函數內通過標志位過濾 2.4.重寫信號發射函數&#xff08;針對自定義信號&#xff…

序列化,應用層自定義協議

我們發的是一個結構化的數據OS內部&#xff0c;協議全部都是傳遞結構體對象。可以直接發送二進制對象嗎&#xff1f;因為CS雙方都能認識這個結構體!!!可以直接發送二進制對象&#xff0c;但是不建議1. 客戶端和服務器說屬于不同的OS&#xff0c;不同的結構體&#xff0c;在不同…

序列化和反序列的學習

一&#xff1a;重談協議1 理解網絡協議&#xff0c;可以把它想象成網絡世界里的“交通規則”和“通用語言”。它是一套預先定義好的規則、標準和約定&#xff0c;使得不同設備、不同系統之間能夠順利地進行通信和數據交換。我們從TCP協議上面理解一下&#xff0c;首先TCP服務是…

計算機畢業設計 java 在線學習系統 基于 Java 的在線教育平臺 Java 開發的學習管理系統

計算機畢業設計 java 在線學習系統fk01a40i &#xff08;配套有源碼 程序 mysql數據庫 論文&#xff09;本套源碼可以先看具體功能演示視頻領取&#xff0c;文末有聯xi 可分享傳統學習模式受時空限制&#xff0c;互動性不足&#xff0c;難以滿足個性化學習需求。為打破限制&…

淘寶利用商品關鍵詞獲取商品信息指南

一、核心API接口選擇接口名稱功能描述適用場景taobao.items.search通過關鍵詞搜索商品&#xff0c;支持分頁、排序&#xff0c;返回商品列表&#xff08;含標題、價格、銷量、圖片等&#xff09;普通商品搜索、競品監控、數據分析taobao.tbk.item.get淘寶客API&#xff0c;返回…

紅黑樹下探玄機:C++ setmultiset 的幕后之旅

目錄 一、關聯式容器 二、鍵值對 三、set 四、set的構造 五、set的iterator 六、set的Operations 七、multiset 一、關聯式容器 序列式容器 &#xff1a; 在初階階段&#xff0c;我們已經接觸過STL中的部分容器&#xff0c;比如&#xff1a;vector、list、deque、forwa…

Spring : 事務管理

1. 基本概念 事務&#xff08;Transaction&#xff09;是一組不可分割的操作單元&#xff0c;這些操作要么全部成功執行&#xff0c;要么全部失敗回滾&#xff0c;不存在部分成功的情況。 事務具有ACID特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事…

C# 一個投資跟蹤程序的設計與實現:面向對象與設計模式的深度解析

在現代金融應用開發中&#xff0c;如何高效、靈活地構建投資跟蹤系統&#xff0c;是每一個金融軟件工程師必須面對的挑戰。本文將圍繞一個投資跟蹤程序的設計與實現過程&#xff0c;深入剖析其背后的設計理念、架構模式以及具體實現細節。我們將通過面向對象編程、設計模式&…

存儲的未來之戰:RustFS如何用ZK框架重構分布式協調?

本篇文章目錄 一、導火索&#xff1a;當數據洪峰撞上分布式協調的天花板 二、技術密碼&#xff1a;ZK框架的三大重構 2.1 一致性哈希環的量子級進化 2.2 動態負載均衡的"神經反射" 2.3 跨云數據同步的"時空折疊" 三、未來戰爭&#xff1a;2026年存儲…

模擬實現STL中的list容器

list前言一、list的節點結構設計二、迭代器設計三、list類的實現3.1 類的成員變量和類型定義3.2 構造函數與析構函數3.3 元素訪問與迭代器接口3.4 插入與刪除操作3.5 其他常用操作四、總結每文推薦前言 在C STL中&#xff0c;list是一個非常常用的容器&#xff0c;它基于雙向循…

Debug-039-el-date-picker組件手動輸入時間日期的問題處理

圖1-外輸入框圖2-內輸入框圖3問題描述&#xff1a;這兩天在迭代功能的時候&#xff0c;基本上碰到的問題都是出自這個“時間日期選擇框”&#xff0c;昨天的bug38也是解決這個組件。如上圖1和2所示&#xff0c;可以把圖1中的輸入框叫外輸入框&#xff0c;圖2中的輸入框叫內輸入…

docker-runc not installed on system

問題 Docker build時Dockerfile有RUN命令執行報錯shim error: docker-runc not installed on system&#xff0c;如下&#xff1a;解決方法 修改/etc/docker/daemon.json&#xff0c;添加正面內容 {"runtimes": {"docker-runc": {"path": "…