天天看點

關于Transformer的一些問題總結

一些與Transformer模型相關的問題總結,有不對的歡迎指出。

💡 殘差網絡為何可以解決梯度消失

關于Transformer的一些問題總結

對比1和2可以發現,對于普通網絡,當有幾個偏導很小的時候,梯度會迅速趨近于0;而對于殘差網絡,要趨近于0,條件比較苛刻,要麼前面一部分趨近0,要麼後一部分趨近-1。總的來說,殘差網絡并不是解決了梯度消失問題,而是在一定程度上規避了問題,讓其很難梯度消失。

注意:

1.神經網絡的權重更新是沿着梯度的負方向,當沒有梯度的時候,更新就會停滞,或者當梯度很大的時候,有可能會跳過最優解,這就是梯度消失和梯度爆炸對神經網絡的“危害”

2.殘差網絡使得網絡更深,而更深的網絡擁有更大的感受野,感受野越大,越能捕獲輸入中的細節資訊。殘差網絡是一個雙支路,他可以融合兩個支路的特征,使得融合後的特征圖有更強的表達能力,說白了就是使得融合後的特征圖有更大的感受野!

💡 Transformer解決的是什麼問題,相較傳統seq2seq有什麼優勢?

RNN、LSTM 和 GRU 網絡已在序列模型、語言模組化、機器翻譯等應用中取得不錯的效果。循環結構 (recurrent) 的語言模型和編碼器 - 解碼器體系結構取得了不錯的進展。但是,RNN 固有的順序屬性阻礙了訓練樣本間的并行化,對于長序列,記憶體限制将阻礙對訓練樣本的批量處理。

注意力機制 (attention) 已經成為各類任務中序列模組化 (sequencem modeling) 和轉導模型 (transduction model) 中的組成部分,允許對輸入輸出序列的依賴項進行模組化,而無需考慮它們在序列中的距離。但之前的注意力機制都與 RNN 結合使用。而Transformer,是一種避免循環 (recurrent) 的模型結構,完全依賴于注意力機制對輸入輸出的全局依賴關系進行模組化。因為對依賴的模組化完全依賴于注意力機制,Transformer 使用的注意力機制被稱為自注意力(self-attention)。

Transforme的優點和缺點

(1) 每層計算複雜度更優:Total computational complexity per layer,時間複雜度優于RNN、CNN等。

(2) 一步計算解決長時依賴問題:這裡Path length指的是要計算一個序列長度為n的資訊要經過的路徑長度。CNN需要增加卷積層數來擴大視野,RNN需要從1到n逐個進行計算,而self-attention隻需要一步矩陣計算就可以。是以也可以看出,self-attention可以比RNN更好地解決長時依賴問題。當然如果計算量太大,比如序列長度n>序列次元d這種情況,也可以用視窗限制self-attention的計算數量。

(3) 模型更可解釋:self-attention模型更可解釋,attention結果的分布表明了該模型學習到了一些文法和語義資訊。

實踐上:有些RNN輕易可以解決的問題,transformer沒做到,比如複制string,或者推理時碰到的sequence長度比訓練時更長(因為碰到了沒見過的position embedding)。

💡 Transformer的encoder和decoder有什麼差別?

(1)decoder包含兩個 Multi-Head Attention 層。

(2)decoder第一個 Multi-Head Attention 層采用了 Masked 操作。

(3)decoder第二個 Multi-Head Attention 層的K, V矩陣使用 Encoder 的編碼資訊矩陣C進行計算,而Q使用上一個 Decoder block 的輸出計算。

(4)decoder最後有一個 Softmax 層計算下一個翻譯單詞的機率

💡 Transformer 的 Positional Encoding 是如何表達相對位置關系的?

在任何一門語言中,詞語的位置和順序對句子意思表達都是至關重要的。傳統的RNN模型在處理句子時,以序列的模式逐個處理句子中的詞語,這使得詞語的順序資訊在處理過程中被天然的儲存下來了,并不需要額外的處理。而對于Transformer來說,由于句子中的詞語都是同時進入網絡進行處理,順序資訊在輸入網絡時就已丢失。是以,Transformer是需要額外的處理來告知每個詞語的相對位置的。其中的一個解決方案,就是論文中提到的Positional Encoding,将能表示位置資訊的編碼添加到輸入中,讓網絡知道每個詞的位置和順序。一句話概括,Positional Encoding就是句子中詞語相對位置的編碼,讓Transformer保留詞語的位置資訊。

理想狀态下,編碼方式應該要滿足以下幾個條件:

· 對于每個位置的詞語,它都能提供一個獨一無二的編碼

· 詞語之間的間隔對于不同長度的句子來說,含義應該是一緻的

· 能夠随意延伸到任意長度的句子

一種思路是使用有界的周期性函數。在前面的兩種方法中,我們為了展現某個字在句子中的絕對位置,使用了一個單調的函數,使得任意後續的字元的位置編碼都大于前面的字,如果我們放棄對絕對位置的追求,轉而要求位置編碼僅僅關注一定範圍内的相對次序關系,那麼使用一個sin/cos函數就是很好的選擇,因為sin/cos函數的周期變化規律非常穩定,是以編碼具有一定的平移不變性。transformer采用的位置編碼公式如下:

關于Transformer的一些問題總結
關于Transformer的一些問題總結

選擇這個函數是因為作者假設它将允許模型容易地學習通過相對位置參與,因為對于任何固定的偏移k,PEpos+k可以表示為PEpos的線性函數。

證明如下:

關于Transformer的一些問題總結
class PositionalEncoding(nn.Module):

    def __init__(self, d_model, max_len=5000):
        super(PositionalEncoding, self).__init__()       
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        # 大數之間相除很容易導緻計算結果誤差很大。是以這裡需要使用下面的小技巧
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0).transpose(0, 1)
        #pe.requires_grad = False
        self.register_buffer('pe', pe)

    def forward(self, x):
        return x + self.pe[:x.size(0), :]
           

💡 Transformer 中為何使用Layer Norm 而不是 Batch Norm?

從原理操作上來講,BN針對的是同一個batch内的所有資料,而LN則是針對單個樣本。另外,從特征次元來說,BN是對同一batch内的資料的同一緯度做歸一化,是以有多少次元就有多少個均值和方差;而LN則是對單個樣本的所有次元來做歸一化,是以一個batch中就有batch_size個均值和方差。

NLP中的embedding中的次元是一些基礎特征的組合,比如男的embedding為[0.1,0.2,0.7],基礎特征為:職業、年齡、職位、畢業學校,embedding中的第一個次元則為α1*職業+α2年齡,第二個次元同理,以此類推。這時候如果用BN的手段,那麼embedding中不同的次元就被不同scale的變換,那麼embedding基礎上所有的距離測度就沒有意義了,(也就是說将embedding中語義資訊修改)。是以隻能采用LN的手段。

(形象點來說,假設有一個二維矩陣。行為batch-size,列為樣本特征。那麼BN就是豎着歸一化,LN就是橫着歸一化。LN,BN各有側重點。一般來說,如果你的特征依賴于不同樣本間的統計參數,那BN更有效。因為它抹殺了不同特征之間的大小關系,但是保留了不同樣本間的大小關系。而在NLP領域,LN就更加合适。因為它抹殺了不同樣本間的大小關系,但是保留了一個樣本内不同特征之間的大小關系。對于NLP或者序列任務來說,一條樣本的不同特征,其實就是時序上字元取值的變化,樣本内的特征關系是非常緊密的。)

是以,BN歸一化會抹去同一樣本所有位置特征的原有大小關系,保留的是不同樣本之間的大小關系;而LN則剛好相反,使用LN可以保留同一樣本内部特征的大小關系,是以更有利于Transformer模型(注意力機制)捕捉統一樣本間詞與詞的全局資訊。另外,NLP的文本本質上可以看成一個時間序列,而時間序列是不定長的,長度不同的序列原則上屬于不同的統計對象,是以很難得到穩定的統計量,而得不到穩定的統計量,BN就無法成立。

此外,為什麼必須進行BN或LN的操作呢?這是因為經過BN或LN的操作後,以NLP中的embedding為例,embedding的各個次元會在同一scale上,形狀像一個碗。如果不進行LN或BN,embedding的形狀像橢圓形。那麼在橢圓長的那個次元就需要進行更多的疊代,這就是BN、LN能夠加速訓練的原因

💡 Transformer的 Layer Normalization是怎麼樣做的?

transformer采用的LN的公式如下:

關于Transformer的一些問題總結

N(x)即為在layer中進行歸一化操作的函數(即減去均值,除以方差),同時再額外地學習g和b對數值進行rescale。代碼實作如下:

class LayerNorm(nn.Module):
    "層歸一化"
    def __init__(self, features, eps=1e-6):
        super(LayerNorm, self).__init__()
        self.a_2 = nn.Parameter(torch.ones(features))
        self.b_2 = nn.Parameter(torch.zeros(features))
        self.eps = eps

    def forward(self, x):
        mean = x.mean(-1, keepdim=True)
        std = x.std(-1, keepdim=True)
        return self.a_2 * (x - mean) / (std + self.eps) + self.b_2
           

💡 什麼是Transformer的多頭注意力機制?

在注意力機制計算過程中,我們就是用qi去找相關的ki,但是相關可能會存在很多種,是以我們應該需要有不同的q,然後不同的q去負責捕獲不同的相關性,多頭注意力機制實作的就是這個功能。相比于Self-Attention,其隻是将計算得到的qi和ki進行拆分。先從a乘上矩陣Wq變成q,然後再将q乘上兩個不同的矩陣W(q,1),W(q,2),分别變成兩個不同的向量q1和q2。k和v也是同樣的進行操作。然後的話用q1,k1,v1去按照之前的方法計算出一個b1出來,再用q2,k2,v2去計算出一個b2出來。

關于Transformer的一些問題總結

使用多頭注意力機制,擴充了模型關注不同位置的能力。此外,他給了自注意力層多個“表示子空間”。對于多頭自注意力機制,我們不止有一組Q/K/V權重矩陣,而是有多組(論文中使用8組),是以每個編碼器/解碼器使用8個“頭”(可以了解為8個互不幹擾自的注意力機制運算),每一組的Q/K/V都不相同。然後,得到8個不同的權重矩陣Z,每個權重矩陣被用來将輸入向量投射到不同的表示子空間。

💡 不考慮多頭的原因,self-attention中詞向量不乘QKV參數矩陣,會有什麼問題?

Self-Attention的核心是用文本中的其它詞來增強目标詞的語義表示,進而更好的利用上下文的資訊。

self-attention中,sequence中的每個詞都會和sequence中的每個詞做點積去計算相似度,也包括這個詞本身。

對于 self-attention,一般會說它的 q=k=v,這裡的相等實際上是指它們來自同一個基礎向量,而在實際計算時,它們是不一樣的,因為這三者都是乘了QKV參數矩陣的。那如果不乘,每個詞對應的q,k,v就是完全一樣的。

在相同量級的情況下,qi與ki點積的值會是最大的(可以從“兩數和相同的情況下,兩數相等對應的積最大”類比過來)。

那在softmax後的權重平均中,該詞本身所占的比重将會是最大的,使得其他詞的比重很少,無法有效利用上下文資訊來增強目前詞的語義表示。

而乘以QKV參數矩陣,會使得每個詞的q,k,v都不一樣,能很大程度上減輕上述的影響。

當然,QKV參數矩陣也使得多頭,類似于CNN中的多核,去捕捉更豐富的特征/資訊成為可能。

💡 多頭注意力機制在進行softmax之前需要對attention進行scaled(為什麼除以 d k d_k dk​的平方根)?

縮放的作用是為了防止點積的值過大或過小,導緻 softmax 函數的梯度消失或爆炸。這是因為點積的結果會随着向量次元的增加而增大,而 softmax 函數對輸入的大小非常敏感,如果點積的值過大或過小,softmax 函數的輸出将非常接近于 0 或 1,導緻梯度消失或爆炸。

基本的注意力機制有以下兩種形式,add和mul:

關于Transformer的一些問題總結

在Transformer中,作者使用的是第二種即mul形式的注意力。之是以用這個,作者解釋是mul計算快。但是,當次元升高使得mul性注意力的整體方差變大,進而出現極大值使softmax梯度消失,是以通過scale控制方差,進而穩定梯度流,防止block堆疊時這一情況的惡化。MUL在dk比較大的時候,必須要做scaled。我們知道,對于兩個矩陣在做乘法的時候,會在相乘時引入一次對所有位置的求和,整體分布就會擴大到[0,dk]。而對于add方式,右側被tanh限制,分布在[-1,1],整體分布和dk沒有關系。之是以要除以 d k d_k dk​的平方根,論文裡其實有簡單解釋到:

關于Transformer的一些問題總結

即假設Q和K的是獨立的随機變量,滿足均值為0,方差為1,那麼他們點積的結果為Q·K的均值為0,方差為dk。那麼除以 d k d_k dk​的平方根,點積的方差将拉回1,也就有效地控制了前面提到的梯度消失的問題。

關于Transformer的一些問題總結

那為什麼在分類層(最後一層),使用非scaled的softmax? 事實上,分類層的softmax也沒有兩個随機變量相乘的情況。此外,這一層的softmax通常和交叉熵聯合求導,在某個目标類别i上的整體梯度變為 y i ′ − y i y'_i-y_i yi′​−yi​,即預測值和真值的差。當出現某個極大的元素值,softmax的輸出機率會集中在該類别上。如果是預測正确,整體梯度接近于0,抑制參數更新;如果是錯誤類别,則整體梯度接近于1,給出最大程度的負回報。也就是說,這個時候的梯度形式改變,不會出現極大值導緻梯度消失的情況了.

💡 在計算attention score的時候如何對padding做mask操作?

在 Transformer 中,為了避免對填充符号進行注意力計算,通常會使用掩碼(mask)來遮蔽填充符号。具體來說,假設我們要對一個序列進行注意力計算,其中包含一些填充符号。首先,我們需要将填充符号對應的位置标記出來,然後将這些位置的注意力分數設定為一個非常小的值,比如負無窮。

在 Transformer 中,padding mask 可以通過建立一個大小為 [batch_size, seq_length] 的矩陣來實作,其中元素為 0 的位置表示輸入中的填充符号,元素為 1 的位置表示輸入中的實際标記。然後,這個 mask 矩陣可以與注意力分數矩陣相乘,以将填充符号的注意力分數設定為負無窮。

在代碼實作中,可以使用 TensorFlow 或 PyTorch 中的函數來建立 mask 矩陣,然後在計算注意力分數時使用它來進行掩碼操作。

💡 Bert是基于Transformer結構的,做了什麼針對性的改動?

結構上,BERT采用堆疊Transformer編碼器而形成。主要有兩種變體:

BERT Base: 12層(指transformer blocks), 12個attention head, 以及1.1億個參數 BERT

BERT Large: 24層(指transformer blocks), 16個attention head,以及3.4億個參數

token embedding: 在BERT中,每個詞會被轉換成768維的向量表示。在實際代碼實作中,輸入文本在送入token embeddings 層之前要先進行tokenization處理。此外,兩個特殊的token會被插入到tokenization的結果的開頭 ([CLS])和結尾 ([SEP])

Positional Embeddings: BERT 在輸入層引入了位置嵌入(Positional Embeddings),以便模型能夠正确處理輸入文本的順序資訊。

Segment Embeddings: BERT還可以将句子對作為任務(問答)的輸入。這就是為什麼它學習了第一個和第二個句子的嵌入,以幫助模型區分二者。在上面的例子中,所有标記為EA的标記都屬于句A(EB同理)。

Tokenization: BERT 采用一種基于 WordPiece 的子詞劃分方法,将單詞劃分成子詞,并對每個子詞進行嵌入表示。這個方法可以更好地處理未登入詞和單詞拼寫錯誤的情況,并且可以更好地利用上下文資訊。

💡 Bert訓練任務是什麼?

預訓練方式: BERT 使用了一種新的預訓練方式,即使用大規模無标注文本資料進行預訓練,然後通過微調将模型應用到下遊任務中。這種方式相對于傳統的基于監督學習的方式,能夠更好地捕捉文本資料中的語言規律和模式,并且具有更好的泛化性能。

Masked Language Model(MLM): BERT 在訓練過程中采用了一種新的預測任務,即 Masked Language Model(MLM),這個任務要求模型在輸入文本中随機掩蓋一些單詞,并預測被掩蓋的單詞。這個任務的目的是讓模型學會雙向上下文,即不僅能夠根據單詞的左側上下文進行預測,還能夠根據單詞的右側上下文進行預測。

Sentence Pair Tasks: BERT 還引入了一些針對性的文本對任務,如 Next Sentence Prediction(NSP),該任務要求模型判斷兩個輸入句子是否是連續的。這些任務的目的是讓模型學習處理文本對的能力,進而更好地支援下遊自然語言處理任務,如問答、文本分類和命名實體識别等。

💡 Bert和GPT有什麼差別與聯系

聯系: 都是基于Transformer的二階段訓練模型,都分為Pre-Training與Fine-Tuning兩個階段,都在Pre-Training階段無監督地訓練出一個可通用的Transformer模型,然後在Fine-Tuning階段對這個模型中的參數進行微調,使之能夠适應不同的下遊任務。

差別: 它們的訓練目标和模型結構和使用上還是有着些許的不同

GPT采用的是單向的Transformer,而BERT采用的是雙向的Transformer,也就是不用進行Mask操作;

使用的結構的不同,直接導緻了它們在Pre-Training階段訓練目标的不同;

💡 持續收集ing

繼續閱讀