日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Transformer 详解

發布時間:2025/3/21 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Transformer 详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Transformer 是谷歌大腦在 2017 年底發表的論文?attention is all you need?中所提出的 seq2seq 模型。現在已經取得了大范圍的應用和擴展,而 BERT 就是從 Transformer 中衍生出來的預訓練語言模型

這篇文章分為以下幾個部分

  • Transformer 直觀認識
  • Positional Encoding
  • Self Attention Mechanism
  • 殘差連接和 Layer Normalization
  • Transformer Encoder 整體結構
  • Transformer Decoder 整體結構
  • 總結
  • 參考文章
  • 0. Transformer 直觀認識

    Transformer 和 LSTM 的最大區別,就是 LSTM 的訓練是迭代的、串行的,必須要等當前字處理完,才可以處理下一個字。而 Transformer 的訓練時并行的,即所有是同時訓練的,這樣就大大增加了計算效率。Transformer 使用了位置嵌入 (Positional Encoding) 來理解語言的順序,使用自注意力機制(Self Attention Mechanism)和全連接層進行計算,這些后面會講到

    Transformer 模型主要分為兩大部分,分別是?Encoder?和?DecoderEncoder?負責把輸入(語言序列)隱射成隱藏層(下圖中第 2 步用九宮格代表的部分),然后解碼器再把隱藏層映射為自然語言序列。例如下圖機器翻譯的例子(Decoder 輸出的時候,是通過 N 層 Decoder Layer 才輸出一個 token,并不是通過一層 Decoder Layer 就輸出一個 token)

    本篇文章大部分內容在于解釋?Encoder?部分,即把自然語言序列映射為隱藏層的數學表達的過程。理解了 Encoder 的結構,再理解 Decoder 就很簡單了

    上圖為 Transformer Encoder Block 結構圖,注意:下面的內容標題編號分別對應著圖中 1,2,3,4 個方框的序號

    1. Positional Encoding

    由于 Transformer 模型沒有循環神經網絡的迭代操作,所以我們必須提供每個字的位置信息給 Transformer,這樣它才能識別出語言中的順序關系

    現在定義一個位置嵌入的概念,也就是 Positional Encoding,位置嵌入的維度為?[max_sequence_length, embedding_dimension], 位置嵌入的維度與詞向量的維度是相同的,都是?embedding_dimension。max_sequence_length?屬于超參數,指的是限定每個句子最長由多少個詞構成

    注意,我們一般以為單位訓練 Transformer 模型。首先初始化字編碼的大小為?[vocab_size, embedding_dimension],vocab_size?為字庫中所有字的數量,embedding_dimension?為字向量的維度,對應到 PyTorch 中,其實就是?nn.Embedding(vocab_size, embedding_dimension)

    論文中使用了 sin 和 cos 函數的線性變換來提供給模型位置信息:

    ?

    PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)

    上式中?pos?指的是一句話中某個字的位置,取值范圍是?[0,?max_sequence_length),i?指的是字向量的維度序號,取值范圍是?[0,?embedding_dimension/2),dmodel?指的是?embedding_dimension?的值

    上面有?sin?和?cos?一組公式,也就是對應著?embedding?dimension?維度的一組奇數和偶數的序號的維度,例如?0,1?一組,2,3?一組,分別用上面的?sin?和?cos?函數做處理,從而產生不同的周期性變化,而位置嵌入在?embedding?dimension?維度上隨著維度序號增大,周期變化會越來越慢,最終產生一種包含位置信息的紋理,就像論文原文中第六頁講的,位置嵌入函數的周期從?2π?到?10000?2π?變化,而每一個位置在?embedding?dimension?維度上都會得到不同周期的?sin?和?cos?函數的取值組合,從而產生獨一的紋理位置信息,最終使得模型學到位置之間的依賴關系和自然語言的時序特性

    如果不理解這里為何這么設計,可以看這篇文章?Transformer 中的 Positional Encoding

    下面畫一下位置嵌入,縱向觀察,可見隨著?embedding?dimension?序號增大,位置嵌入函數的周期變化越來越平緩

    • import numpy as np

    • import matplotlib.pyplot as plt

    • import seaborn as sns

    • import math

    • ?
    • def get_positional_encoding(max_seq_len, embed_dim):

    • # 初始化一個positional encoding

    • # embed_dim: 字嵌入的維度

    • # max_seq_len: 最大的序列長度

    • positional_encoding = np.array([

    • [pos / np.power(10000, 2 * i / embed_dim) for i in range(embed_dim)]

    • if pos != 0 else np.zeros(embed_dim) for pos in range(max_seq_len)])

    • ?
    • positional_encoding[1:, 0::2] = np.sin(positional_encoding[1:, 0::2]) # dim 2i 偶數

    • positional_encoding[1:, 1::2] = np.cos(positional_encoding[1:, 1::2]) # dim 2i+1 奇數

    • return positional_encoding

    • ?
    • positional_encoding = get_positional_encoding(max_seq_len=100, embed_dim=16)

    • plt.figure(figsize=(10,10))

    • sns.heatmap(positional_encoding)

    • plt.title("Sinusoidal Function")

    • plt.xlabel("hidden dimension")

    • plt.ylabel("sequence length")

    • plt.figure(figsize=(8, 5))

    • plt.plot(positional_encoding[1:, 1], label="dimension 1")

    • plt.plot(positional_encoding[1:, 2], label="dimension 2")

    • plt.plot(positional_encoding[1:, 3], label="dimension 3")

    • plt.legend()

    • plt.xlabel("Sequence length")

    • plt.ylabel("Period of Positional Encoding")

    2. Self Attention Mechanism

    對于輸入的句子?X,通過 WordEmbedding 得到該句子中每個字的字向量,同時通過 Positional Encoding 得到所有字的位置向量,將其相加(維度相同,可以直接相加),得到該字真正的向量表示。第?t?個字的向量記作?xt

    接著我們定義三個矩陣?WQ,WK.WV,使用這三個矩陣分別對所有的字向量進行三次線性變換,于是所有的字向量又衍生出三個新的向量?qt,kt,vt。我們將所有的?qt?向量拼成一個大矩陣,記作查詢矩陣?Q,將所有的?kt?向量拼成一個大矩陣,記作鍵矩陣?K,將所有的?vt?向量拼成一個大矩陣,記作值矩陣?V(見下圖)

    為了獲得第一個字的注意力權重,我們需要用第一個字的查詢向量?q1?乘以鍵矩陣 K(見下圖)

    • [0, 4, 2]

    • [1, 0, 2] x [1, 4, 3] = [2, 4, 4]

    • [1, 0, 1]

    之后還需要將得到的值經過 softmax,使得它們的和為 1(見下圖)

    • softmax([2, 4, 4]) = [0.0, 0.5, 0.5]

    有了權重之后,將權重其分別乘以對應字的值向量?vt(見下圖)

    • 0.0 * [1, 2, 3] = [0.0, 0.0, 0.0]

    • 0.5 * [2, 8, 0] = [1.0, 4.0, 0.0]

    • 0.5 * [2, 6, 3] = [1.0, 3.0, 1.5]

    最后將這些權重化后的值向量求和,得到第一個字的輸出(見下圖)

    • [0.0, 0.0, 0.0]

    • + [1.0, 4.0, 0.0]

    • + [1.0, 3.0, 1.5]

    • -----------------

    • = [2.0, 7.0, 1.5]

    對其它的輸入向量也執行相同的操作,即可得到通過 self-attention 后的所有輸出

    矩陣計算

    上面介紹的方法需要一個循環遍歷所有的字?xt,我們可以把上面的向量計算變成矩陣的形式,從而一次計算出所有時刻的輸出

    第一步就不是計算某個時刻的?qt,kt,vt?了,而是一次計算所有時刻的?Q,K?和?V。計算過程如下圖所示,這里的輸入是一個矩陣?X,矩陣第?t?行表示第?t?個詞的向量表示?xt

    接下來將?Q?和?KT?相乘,然后除以?dk(這是論文中提到的一個 trick),經過 softmax 以后再乘以?V?得到輸出

    Multi-Head Attention

    這篇論文還提出了 Multi-Head Attention 的概念。其實很簡單,前面定義的一組?Q,K,V?可以讓一個詞 attend to 相關的詞,我們可以定義多組?Q,K,V,讓它們分別關注不同的上下文。計算?Q,K,V?的過程還是一樣,只不過線性變換的矩陣從一組?(WQ,WK,WV)?變成了多組?(W0Q,W0K,W0V)?,(W1Q,W1K,W1V),… 如下圖所示

    對于輸入矩陣?X,每一組?Q、K?和?V?都可以得到一個輸出矩陣?Z。如下圖所示

    Padding Mask

    上面 Self Attention 的計算過程中,我們通常使用 mini-batch 來計算,也就是一次計算多句話,即?X?的維度是?[batch_size, sequence_length],sequence_length?是句長,而一個 mini-batch 是由多個不等長的句子組成的,我們需要按照這個 mini-batch 中最大的句長對剩余的句子進行補齊,一般用 0 進行填充,這個過程叫做 padding

    但這時在進行 softmax 就會產生問題。回顧 softmax 函數?σ(zi)=ezi∑j=1Kezj,e0?是 1,是有值的,這樣的話 softmax 中被 padding 的部分就參與了運算,相當于讓無效的部分參與了運算,這可能會產生很大的隱患。因此需要做一個 mask 操作,讓這些無效的區域不參與運算,一般是給無效區域加一個很大的負數偏置,即

    ?

    Zillegal=Zillegal+biasillegalbiasillegal→?∞

    3. 殘差連接和 Layer Normalization

    殘差連接

    我們在上一步得到了經過 self-attention 加權之后輸出,也就是?Attention(Q,?K,?V),然后把他們加起來做殘差連接

    ?

    Xembedding+Self?Attention(Q,?K,?V)

    Layer Normalization

    Layer Normalization 的作用是把神經網絡中隱藏層歸一為標準正態分布,也就是?i.i.d?獨立同分布,以起到加快訓練速度,加速收斂的作用

    ?

    μj=1m∑i=1mxij

    上式以矩陣的列?(column)?為單位求均值;

    ?

    σj2=1m∑i=1m(xij?μj)2

    上式以矩陣的列?(column)?為單位求方差

    ?

    LayerNorm(x)=xij?μjσj2+?

    然后用每一列每一個元素減去這列的均值,再除以這列的標準差,從而得到歸一化后的數值,加???是為了防止分母為 0

    下圖展示了更多細節:輸入?x1,x2?經 self-attention 層之后變成?z1,z2,然后和輸入?x1,x2?進行殘差連接,經過 LayerNorm 后輸出給全連接層。全連接層也有一個殘差連接和一個 LayerNorm,最后再輸出給下一個 Encoder(每個 Encoder Block 中的 FeedForward 層權重都是共享的)

    4. Transformer Encoder 整體結構

    經過上面 3 個步驟,我們已經基本了解了?Encoder?的主要構成部分,下面我們用公式把一個 Encoder block 的計算過程整理一下:

    1). 字向量與位置編碼

    ?

    X=Embedding?Lookup(X)+Positional?Encoding

    2). 自注意力機制

    ?

    Q=Linear(X)=XWQK=Linear(X)=XWKV=Linear(X)=XWVXattention=SelfAttention(Q,?K,?V)

    3). self-attention 殘差連接與 Layer Normalization

    ?

    Xattention=X+XattentionXattention=LayerNorm(Xattention)

    4). 下面進行 Encoder block 結構圖中的第 4 部分,也就是 FeedForward,其實就是兩層線性映射并用激活函數激活,比如說?ReLU

    ?

    Xhidden=Linear(ReLU(Linear(Xattention)))

    5). FeedForward 殘差連接與 Layer Normalization

    ?

    Xhidden=Xattention+XhiddenXhidden=LayerNorm(Xhidden)

    其中

    ?

    Xhidden∈Rbatch_size???seq_len.???embed_dim

    5. Transformer Decoder 整體結構

    我們先從 HighLevel 的角度觀察一下 Decoder 結構,從下到上依次是:

    • Masked Multi-Head Self-Attention
    • Multi-Head Encoder-Decoder Attention
    • FeedForward Network

    和 Encoder 一樣,上面三個部分的每一個部分,都有一個殘差連接,后接一個?Layer Normalization。Decoder 的中間部件并不復雜,大部分在前面 Encoder 里我們已經介紹過了,但是 Decoder 由于其特殊的功能,因此在訓練時會涉及到一些細節

    Masked Self-Attention

    具體來說,傳統 Seq2Seq 中 Decoder 使用的是 RNN 模型,因此在訓練過程中輸入?t?時刻的詞,模型無論如何也看不到未來時刻的詞,因為循環神經網絡是時間驅動的,只有當?t?時刻運算結束了,才能看到?t+1?時刻的詞。而 Transformer Decoder 拋棄了 RNN,改為 Self-Attention,由此就產生了一個問題,在訓練過程中,整個 ground truth 都暴露在 Decoder 中,這顯然是不對的,我們需要對 Decoder 的輸入進行一些處理,該處理被稱為 Mask

    舉個例子,Decoder 的 ground truth 為 "<start> I am fine",我們將這個句子輸入到 Decoder 中,經過 WordEmbedding 和 Positional Encoding 之后,將得到的矩陣做三次線性變換(WQ,WK,WV)。然后進行 self-attention 操作,首先通過?Q×KTdk?得到 Scaled Scores,接下來非常關鍵,我們要對 Scaled Scores 進行 Mask,舉個例子,當我們輸入 "I" 時,模型目前僅知道包括 "I" 在內之前所有字的信息,即 "<start>" 和 "I" 的信息,不應該讓其知道 "I" 之后詞的信息。道理很簡單,我們做預測的時候是按照順序一個字一個字的預測,怎么能這個字都沒預測完,就已經知道后面字的信息了呢?Mask 非常簡單,首先生成一個下三角全 0,上三角全為負無窮的矩陣,然后將其與 Scaled Scores 相加即可

    之后再做 softmax,就能將 - inf 變為 0,得到的這個矩陣即為每個字之間的權重

    Multi-Head Self-Attention 無非就是并行的對上述步驟多做幾次,前面 Encoder 也介紹了,這里就不多贅述了

    Masked Encoder-Decoder Attention

    其實這一部分的計算流程和前面 Masked Self-Attention 很相似,結構也一摸一樣,唯一不同的是這里的?K,V?為 Encoder 的輸出,Q?為 Decoder 中 Masked Self-Attention 的輸出

    6. 總結

    到此為止,Transformer 中 95% 的內容已經介紹完了,我們用一張圖展示其完整結構。不得不說,Transformer 設計的十分巧奪天工

    下面有幾個問題,是我從網上找的,感覺看完之后能對 Transformer 有一個更深的理解

    Transformer 為什么需要進行 Multi-head Attention?

    原論文中說到進行 Multi-head Attention 的原因是將模型分為多個頭,形成多個子空間,可以讓模型去關注不同方面的信息,最后再將各個方面的信息綜合起來。其實直觀上也可以想到,如果自己設計這樣的一個模型,必然也不會只做一次 attention,多次 attention 綜合的結果至少能夠起到增強模型的作用,也可以類比 CNN 中同時使用多個卷積核的作用,直觀上講,多頭的注意力有助于網絡捕捉到更豐富的特征 / 信息

    Transformer 相比于 RNN/LSTM,有什么優勢?為什么?

  • RNN 系列的模型,無法并行計算,因為 T 時刻的計算依賴 T-1 時刻的隱層計算結果,而 T-1 時刻的計算依賴 T-2 時刻的隱層計算結果
  • Transformer 的特征抽取能力比 RNN 系列的模型要好
  • 為什么說 Transformer 可以代替 seq2seq?

    這里用代替這個詞略顯不妥當,seq2seq 雖已老,但始終還是有其用武之地,seq2seq 最大的問題在于將 Encoder 端的所有信息壓縮到一個固定長度的向量中,并將其作為 Decoder 端首個隱藏狀態的輸入,來預測 Decoder 端第一個單詞 (token) 的隱藏狀態。在輸入序列比較長的時候,這樣做顯然會損失 Encoder 端的很多信息,而且這樣一股腦的把該固定向量送入 Decoder 端,Decoder 端不能夠關注到其想要關注的信息。Transformer 不但對 seq2seq 模型這兩點缺點有了實質性的改進 (多頭交互式 attention 模塊),而且還引入了 self-attention 模塊,讓源序列和目標序列首先 “自關聯” 起來,這樣的話,源序列和目標序列自身的 embedding 表示所蘊含的信息更加豐富,而且后續的 FFN 層也增強了模型的表達能力,并且 Transformer 并行計算的能力遠遠超過了 seq2seq 系列模型

    7. 參考文章

    • Transformer
    • The Illustrated Transformer
    • TRANSFORMERS FROM SCRATCH
    • Seq2seq pay Attention to Self Attention: Part 2

    總結

    以上是生活随笔為你收集整理的Transformer 详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。