您當前的位置:首頁 > 舞蹈

BERTTransformer知識點備份

作者:由 sundy 發表于 舞蹈時間:2020-05-27

隨著NLP的不斷髮展,對BERT/Transformer相關知識的研(mian)究(shi)應(ti)用(wen),也越來越細節,下面嘗試用QA的形式深入不淺出BERT/Transformer的細節知識點。

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

2、為什麼BERT選擇mask掉15%這個比例的詞,可以是其他的比例嗎?

3、使用BERT預訓練模型為什麼最多隻能輸入512個詞,最多隻能兩個句子合成?

4、為什麼BERT在第一句前會加一個[CLS]標誌?

5、Self-Attention 的時間複雜度是怎麼計算的?

6、Transformer在哪裡做了權重共享,為什麼可以做權重共享?

7、BERT非線性的來源在哪裡?

8、BERT的三個Embedding直接相加會對語義有影響嗎?

9、Transformer的點積模型做縮放的原因是什麼?

10、在BERT應用中,如何解決長文字問題?

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

Self-Attention的核心是

用文字中的其它詞來增強目標詞的語義表示

,從而更好的利用上下文的資訊。

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

如果不乘QKV引數矩陣,那這個詞對應的q,k,v就是完全一樣的。

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

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

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

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

2、為什麼BERT選擇mask掉15%這個比例的詞,可以是其他的比例嗎?

BERT採用的Masked LM,會選取語料中所有詞的15%進行隨機mask,論文中表示是受到完形填空任務的啟發,但其實

與CBOW也有異曲同工之妙

從CBOW的角度,這裡

p=15\%

有一個比較好的解釋是:在一個大小為

1/p=100/15\approx7

的視窗中隨機選一個詞,類似CBOW中滑動視窗的中心詞,區別是這裡的滑動視窗是非重疊的。

那從CBOW的滑動視窗角度,10%~20%都是還ok的比例。

上述非官方解釋,是來自我的一位朋友提供的一個理解切入的角度,供參考。

3、使用BERT預訓練模型為什麼最多隻能輸入512個詞,最多隻能兩個句子合成一句?

這是Google BERT預訓練模型初始設定的原因,前者對應Position Embeddings,後者對應Segment Embeddings

BERTTransformer知識點備份

在BERT中,Token,Position,Segment Embeddings

都是透過學習來得到的

,pytorch程式碼中它們是這樣的

self。word_embeddings = Embedding(config。vocab_size, config。hidden_size) self。position_embeddings = Embedding(config。max_position_embeddings, config。hidden_size) self。token_type_embeddings = Embedding(config。type_vocab_size, config。hidden_size)

上述BERT pytorch程式碼來自:

https://

github。com/xieyufei1993

/Bert-Pytorch-Chinese-TextClassification

,結構層次非常清晰。

而在BERT config中

“max_position_embeddings”: 512 “type_vocab_size”: 2

因此,在直接使用Google 的BERT預訓練模型時,輸入最多512個詞(還要除掉[CLS]和[SEP]),最多兩個句子合成一句。這之外的詞和句子會沒有對應的embedding。

當然,如果有足夠的硬體資源自己重新訓練BERT,可以更改 BERT config,設定更大max_position_embeddings 和 type_vocab_size值去滿足自己的需求。

4、為什麼BERT在第一句前會加一個[CLS]標誌?

BERT在第一句前會加一個[CLS]標誌,最後一層該位對應向量可以作為整句話的語義表示,從而用於下游的分類任務等。

為什麼選它呢,因為與文字中已有的其它詞相比,這個無明顯語義資訊的符號會

更“公平”地融合文字中各個詞的語義資訊

,從而更好的表示整句話的語義。

這裡補充一下bert的輸出,有兩種:

一種是get_pooled_out(),就是上述[CLS]的表示,輸出shape是[batch size,hidden size]。

一種是get_sequence_out(),獲取的是整個句子每一個token的向量表示,輸出shape是[batch_size, seq_length, hidden_size],這裡也包括[CLS],因此在做token級別的任務時要注意它。

5、Self-Attention 的時間複雜度是怎麼計算的?

Self-Attention時間複雜度:

O(n^2 \cdot d)

,這裡,n是序列的長度,d是embedding的維度。

Self-Attention包括

三個步驟:相似度計算,softmax和加權平均

,它們分別的時間複雜度是:

相似度計算可以看作大小為(n,d)和(d,n)的兩個矩陣相乘:

(n,d)*(d,n)=O(n^2 \cdot d)

,得到一個(n,n)的矩陣

softmax就是直接計算了,時間複雜度為

O(n^2)

加權平均可以看作大小為(n,n)和(n,d)的兩個矩陣相乘:

(n,n)*(n,d)=O(n^2 \cdot d)

,得到一個(n,d)的矩陣

因此,Self-Attention的時間複雜度是

O(n^2 \cdot d)

這裡再分析一下Multi-Head Attention,它的作用類似於CNN中的多核。

多頭的實現不是迴圈的計算每個頭,而是透過 transposes and reshapes,用矩陣乘法來完成的。

In practice, the multi-headed attention are done with transposes and reshapes rather than actual separate tensors。 —— 來自 google BERT 原始碼

Transformer/BERT中把

d ,

也就是hidden_size/embedding_size這個維度做了reshape拆分,可以去看Google的TF原始碼或者上面的pytorch原始碼:

hidden_size (d) = num_attention_heads (m) * attention_head_size (a),也即 d=m*a

並將 num_attention_heads 維度transpose到前面,使得Q和K的維度都是(m,n,a),這裡不考慮batch維度。

這樣點積可以看作大小為(m,n,a)和(m,a,n)的兩個張量相乘,得到一個(m,n,n)的矩陣,其實就相當於m個頭,時間複雜度是

O(n^2 \cdot m^2 \cdot a)=O(n^2 \cdot d \cdot m)

張量乘法時間複雜度分析參見:矩陣、張量乘法的時間複雜度分析

因此Multi-Head Attention時間複雜度就是

O(n^2 \cdot d \cdot m)

,而實際上,張量乘法可以加速,因此實際複雜度會更低一些。

不過,對於做 transposes and reshapes 的邏輯,個人沒有理的很明白,希望大佬看到能留言解答一下,感謝。

6、Transformer在哪裡做了權重共享,為什麼可以做權重共享?

Transformer在兩個地方進行了權重共享:

(1)

Encoder和Decoder間的Embedding層權重共享;

(2)

Decoder中Embedding層和FC層權重共享。

對於(1)

,《Attention is all you need》中Transformer被應用在機器翻譯任務中,源語言和目標語言是不一樣的,但它們可以共用一張大詞表,對於兩種語言中共同出現的詞(比如:數字,標點等等)可以得到更好的表示,而且對於Encoder和Decoder,

嵌入時都只有對應語言的embedding會被啟用

,因此是可以共用一張詞表做權重共享的。

論文中,Transformer詞表用了bpe來處理,所以最小的單元是subword。英語和德語同屬日耳曼語族,有很多相同的subword,可以共享類似的語義。而像中英這樣相差較大的語系,語義共享作用可能不會很大。

但是,共用詞表會使得詞表數量增大,增加softmax的計算時間,因此實際使用中是否共享可能要根據情況權衡。

該點參考:

https://www。

zhihu。com/question/3334

19099/answer/743341017

對於(2)

,Embedding層可以說是透過onehot去取到對應的embedding向量,FC層可以說是相反的,透過向量(定義為 x)去得到它可能是某個詞的softmax機率,取機率最大(貪婪情況下)的作為預測值。

那哪一個會是機率最大的呢?在FC層的每一行量級相同的前提下,理論上和 x 相同的那一行對應的點積和softmax機率會是最大的(可類比本文問題1)。

因此,Embedding層和FC層權重共享,Embedding層中和向量 x 最接近的那一行對應的詞,會獲得更大的預測機率。實際上,Decoder中的

Embedding層和FC層有點像互為逆過程

透過這樣的權重共享可以減少引數的數量,加快收斂。

但開始我有一個困惑是:Embedding層引數維度是:(v,d),FC層引數維度是:(d,v),可以直接共享嘛,還是要轉置?其中v是詞表大小,d是embedding維度。

檢視 pytorch 原始碼發現真的可以直接共享:

fc = nn。Linear(d, v, bias=False)

# Decoder FC層定義

​ weight = Parameter(torch。Tensor(out_features, in_features))

# Linear層權重定義

Linear 層的權重定義中,是按照 (out_features, in_features) 順序來的,實際計算會先將 weight 轉置在乘以輸入矩陣。所以 FC層 對應的 Linear 權重維度也是 (v,d),可以直接共享。

7、BERT非線性的來源在哪裡?

前饋層的gelu啟用函式和self-attention,self-attention是非線性的,感謝評論區指出。

還有幾個問題也非常好,值得重點關注,但網上已經有很好的解答了,如下:

8、BERT的三個Embedding直接相加會對語義有影響嗎?

參考:

https://www。

zhihu。com/question/3748

35153

9、Transformer的點積模型做縮放的原因是什麼?

參考:

https://www。

zhihu。com/question/3397

23385

10、在BERT應用中,如何解決長文字問題?

參考:

https://www。

zhihu。com/question/3274

50789

轉載地址:

https://

zhuanlan。zhihu。com/p/13

2554155

標簽: bert  size  embedding  共享  複雜度