Transformer变体层出不穷,它们都长什么样?
?PaperWeekly 原創 ·?作者|上杉翔二
單位|悠閑會
研究方向|信息檢索
不知不覺 Transformer 已經逐步滲透到了各個領域,就其本身也產生了相當多的變體,如上圖。本篇文章想大致按照這個圖,選一些比較精彩的變體整理,話不多說直接開始。
Transformer-XL
論文標題:
Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context
收錄會議:
ACL 2019
論文鏈接:
https://arxiv.org/abs/1901.02860
代碼鏈接:
https://github.com/kimiyoung/transformer-xl
上圖上標的是“Recurrence”,首先看看這篇文章聚焦的 2 個問題:
雖然 Transformer 可以學習到輸入文本的長距離依賴關系和全局特性,但是!需要事先設定輸入長度,這導致了其對于長程關系的捕捉有了一定限制。
出于效率的考慮,需要對輸入的整個文檔進行分割(固定的),那么每個序列的計算相互獨立,所以只能夠學習到同個序列內的語義聯系,整體上看,這將會導致文檔語意上下文的碎片化(context fragmentation)。
那么如何學習更長語義聯系?
segment-level Recurrence
segment-level 循環機制。如上圖左邊為原始 Transformer,右邊為 Transformer-XL,Transformer-XL 模型的計算當中加入綠色連線,使得當層的輸入取決于本序列和上一個序列前一層的輸出。這樣每個序列計算后的隱狀態會參與到下一個序列的計算當中,使得模型能夠學習到跨序列的語義聯系(看動圖可能更好理解)。
是第 個 segment 的第 n 層隱向量,那么第 r+1 個的第 n 層的隱向量的計算,就是上面這套公式。
其中 SG 是是 stop-gradient,不再對 的隱向量做反向傳播(這樣雖然在計算中運用了前一個序列的計算結果,但是在反向傳播中并不對其進行梯度的更新,畢竟前一個梯度肯定不受影響)。
是對兩個隱向量序列沿長度 L 方向的拼接 。3 個 W 分別對應 query,key 和 value 的轉化矩陣,需要注意的是!k 和 v 的 W 用的是 ,而 q 是用的 ,即 kv 是用的拼接之后的 h,而 q 用的是原始序列的信息。感覺可以理解為以原始序列查拼接序列,這樣可以得到一些前一個序列的部分信息以實現跨語義。
最后的公式是標準的 Transformer。
還有一點設計是,在評估預測模型的時候它是會連續計算前 L 個長度的隱向量的(訓練的時候只有前一個,緩存在內存中)。
即每一個位置的隱向量,除了自己的位置,都跟下一層中前(L-1)個位置的 token 存在依賴關系,而且每往下走一層,依賴關系長度會增加(L-1),這樣能使跨語義更加的深入。
只看看 XL 多頭注意力的 forward 的不同地方吧。
def?forward(self,?w,?r,?r_w_bias,?r_r_bias,?attn_mask=None,?mems=None):#w是上一層的輸出,r是相對位置嵌入(在下一節),r_w_bias是u,r_r_bias是v向量qlen,?rlen,?bsz?=?w.size(0),?r.size(0),?w.size(1)if?mems?is?not?None:?#mems就是前一些序列的向量,不為空cat?=?torch.cat([mems,?w],?0)?#就拼起來if?self.pre_lnorm:?#如果有正則化w_heads?=?self.qkv_net(self.layer_norm(cat))?#這個net是nn.Linear,即qkv的變換矩陣W參數else:w_heads?=?self.qkv_net(cat)#沒有正則就直接投影一下r_head_k?=?self.r_net(r)#也是nn.Linearw_head_q,?w_head_k,?w_head_v?=?torch.chunk(w_heads,?3,?dim=-1)?#復制3份w_head_q?=?w_head_q[-qlen:]?#q的W不要拼接的memselse:#沒有mems,就正常的計算if?self.pre_lnorm:w_heads?=?self.qkv_net(self.layer_norm(w))else:w_heads?=?self.qkv_net(w)r_head_k?=?self.r_net(r)w_head_q,?w_head_k,?w_head_v?=?torch.chunk(w_heads,?3,?dim=-1)klen?=?w_head_k.size(0)#qlen是序列長度,bsz是batch?size,n_head是注意力頭數,d_head是每個頭的隱層維度w_head_q?=?w_head_q.view(qlen,?bsz,?self.n_head,?self.d_head)???????????#?qlen?x?bsz?x?n_head?x?d_headw_head_k?=?w_head_k.view(klen,?bsz,?self.n_head,?self.d_head)???????????#?qlen?x?bsz?x?n_head?x?d_headw_head_v?=?w_head_v.view(klen,?bsz,?self.n_head,?self.d_head)???????????#?qlen?x?bsz?x?n_head?x?d_headr_head_k?=?r_head_k.view(rlen,?self.n_head,?self.d_head)????????????????#?qlen?x?n_head?x?d_head####計算注意力的四個部分#AC是指相對位置的公式里的a和c兩個部分,相對位置在下一節做筆記rw_head_q?=?w_head_q?+?r_w_bias?????????????????????????????????????????#?qlen?x?bsz?x?n_head?x?d_head#愛因斯坦簡記法求和sum,統一的方式表示各種各樣的張量運算AC?=?torch.einsum('ibnd,jbnd->ijbn',?(rw_head_q,?w_head_k))?????????????#?qlen?x?klen?x?bsz?x?n_head#BD是指相對位置的公式里的b和d兩個部分rr_head_q?=?w_head_q?+?r_r_biasBD?=?torch.einsum('ibnd,jnd->ijbn',?(rr_head_q,?r_head_k))??????????????#?qlen?x?klen?x?bsz?x?n_headBD?=?self._rel_shift(BD)#?[qlen?x?klen?x?bsz?x?n_head]attn_score?=?AC?+?BD?#最后的結果attn_score.mul_(self.scale)#進行放縮Relative Position Encodings
相對位置編碼。原始 Transformer 采用了正弦/余弦函數來編碼絕對位置信息。然而因為 Transformer-XL 會有多個句子,所以還是絕對位置,那么兩個句子的相同位置是同樣的編碼。
比如 [0, 1, 2, 3] 在兩個句子 concat 之后就變成了 [0, 1, 2, 3, 0, 1, 2, 3],句子不連續,而且每次拼的句子會不一樣,也不能找到適合的絕對位置編碼。所以這里使用相對位置編碼。
上圖是原始 Transformer 和 Transformer-XL 的比較,其中 E 表示詞的 Embedding,而 U 表示絕對位置編碼。這大一堆看起來奇奇怪怪,實際上 Transformer 的注意力計算是 的分解,即先編碼 Q(當前詞 i)和 K(其他的詞 j)然后算內積,位置編碼是直接 add 在詞嵌入上面的。
而 Transformer-XL 的改變是:
把 j 的絕對位置 U 換成了相對位置 R,該相對位置表示也是一個正弦函數表示(i 和 j 的相對位置向量,j 是之前的序列,所以相減一定是正數)。R 不是通過學習得到的,好處是預測時,可以使用比訓練距離更長的位置向量。
使用兩個可學習參數 u 和 v 替代了中的 query i 的位置映射。這里是由于每次計算 query 向量是固定的,不需要編碼。
每一層的 Attention 計算都要相對位置編碼。Transformer 里面只有 input 的時候會加,而 XL 需要每層。
細細思考,這 attention 的四個部分各有玄機:
a. 基于內容的“尋址”,即沒有添加原始位置編碼的原始向量, 查 。
b. 基于內容的位置偏置,即相對于當前內容的位置偏差, 查 。
c. 全局的內容偏置,用于衡量 key 的重要性,query 固定查 。
d. 全局的位置偏置,根據 query 和 key 之間的距離調整重要性,query 固定查 。
相對位置編碼的代碼為:
class?PositionalEmbedding(nn.Module):def?__init__(self,?demb):super(PositionalEmbedding,?self).__init__()self.demb?=?demb?#編碼維度inv_freq?=?1?/?(10000?**?(torch.arange(0.0,?demb,?2.0)?/?demb))?#間隔頻率def?forward(self,?pos_seq):sinusoid_inp?=?torch.ger(pos_seq,?self.inv_freq)?#序列的位置向量?operation?間隔pos_emb?=?torch.cat([sinusoid_inp.sin(),?sinusoid_inp.cos()],?dim=-1)?#正弦余弦return?pos_emb[:,None,:]?#直接返回R,非學習矩陣R簡單把編碼維度設置為 10,查詢向量也是 10 個,存儲之前的序列也是 10,有以下結果:
>>>?import?torch >>>?inv_freq?=?1?/?(10000?**?(torch.arange(0.0,?10,?2.0)?/?10)) >>>?inv_freq tensor([1.0000e+00,?1.5849e-01,?2.5119e-02,?3.9811e-03,?6.3096e-04]) >>>?pos_seq=torch.arange(20-1,?-1,?-1.0)?#qlen+mlen,即10+10的維度然后逆序 >>>?pos_seq tensor([19.,?18.,?17.,?16.,?15.,?14.,?13.,?12.,?11.,?10.,??9.,??8.,??7.,??6.,5.,??4.,??3.,??2.,??1.,??0.]) >>>?sinusoid_inp?=?torch.ger(pos_seq,inv_freq) >>>?sinusoid_inp tensor([[1.9000e+01,?3.0113e+00,?4.7726e-01,?7.5640e-02,?1.1988e-02],[1.8000e+01,?2.8528e+00,?4.5214e-01,?7.1659e-02,?1.1357e-02],[1.7000e+01,?2.6943e+00,?4.2702e-01,?6.7678e-02,?1.0726e-02],[1.6000e+01,?2.5358e+00,?4.0190e-01,?6.3697e-02,?1.0095e-02],[1.5000e+01,?2.3773e+00,?3.7678e-01,?5.9716e-02,?9.4644e-03],[1.4000e+01,?2.2189e+00,?3.5166e-01,?5.5735e-02,?8.8334e-03],[1.3000e+01,?2.0604e+00,?3.2655e-01,?5.1754e-02,?8.2024e-03],[1.2000e+01,?1.9019e+00,?3.0143e-01,?4.7773e-02,?7.5715e-03],[1.1000e+01,?1.7434e+00,?2.7631e-01,?4.3792e-02,?6.9405e-03],[1.0000e+01,?1.5849e+00,?2.5119e-01,?3.9811e-02,?6.3096e-03],[9.0000e+00,?1.4264e+00,?2.2607e-01,?3.5830e-02,?5.6786e-03],[8.0000e+00,?1.2679e+00,?2.0095e-01,?3.1849e-02,?5.0477e-03],[7.0000e+00,?1.1094e+00,?1.7583e-01,?2.7867e-02,?4.4167e-03],[6.0000e+00,?9.5094e-01,?1.5071e-01,?2.3886e-02,?3.7857e-03],[5.0000e+00,?7.9245e-01,?1.2559e-01,?1.9905e-02,?3.1548e-03],[4.0000e+00,?6.3396e-01,?1.0048e-01,?1.5924e-02,?2.5238e-03],[3.0000e+00,?4.7547e-01,?7.5357e-02,?1.1943e-02,?1.8929e-03],[2.0000e+00,?3.1698e-01,?5.0238e-02,?7.9621e-03,?1.2619e-03],[1.0000e+00,?1.5849e-01,?2.5119e-02,?3.9811e-03,?6.3096e-04],[0.0000e+00,?0.0000e+00,?0.0000e+00,?0.0000e+00,?0.0000e+00]]) >>>?sinusoid_inp.sin() tensor([[?1.4988e-01,??1.2993e-01,??4.5935e-01,??7.5568e-02,??1.1988e-02],[-7.5099e-01,??2.8479e-01,??4.3689e-01,??7.1598e-02,??1.1357e-02],[-9.6140e-01,??4.3251e-01,??4.1416e-01,??6.7627e-02,??1.0726e-02],[-2.8790e-01,??5.6939e-01,??3.9117e-01,??6.3654e-02,??1.0095e-02],[?6.5029e-01,??6.9200e-01,??3.6793e-01,??5.9681e-02,??9.4642e-03],[?9.9061e-01,??7.9726e-01,??3.4446e-01,??5.5706e-02,??8.8333e-03],[?4.2017e-01,??8.8254e-01,??3.2077e-01,??5.1731e-02,??8.2024e-03],[-5.3657e-01,??9.4569e-01,??2.9688e-01,??4.7755e-02,??7.5714e-03],[-9.9999e-01,??9.8514e-01,??2.7281e-01,??4.3778e-02,??6.9405e-03],[-5.4402e-01,??9.9990e-01,??2.4856e-01,??3.9800e-02,??6.3095e-03],[?4.1212e-01,??9.8959e-01,??2.2415e-01,??3.5822e-02,??5.6786e-03],[?9.8936e-01,??9.5448e-01,??1.9960e-01,??3.1843e-02,??5.0476e-03],[?6.5699e-01,??8.9544e-01,??1.7493e-01,??2.7864e-02,??4.4167e-03],[-2.7942e-01,??8.1396e-01,??1.5014e-01,??2.3884e-02,??3.7857e-03],[-9.5892e-01,??7.1207e-01,??1.2526e-01,??1.9904e-02,??3.1548e-03],[-7.5680e-01,??5.9234e-01,??1.0031e-01,??1.5924e-02,??2.5238e-03],[?1.4112e-01,??4.5775e-01,??7.5285e-02,??1.1943e-02,??1.8929e-03],[?9.0930e-01,??3.1170e-01,??5.0217e-02,??7.9621e-03,??1.2619e-03],[?8.4147e-01,??1.5783e-01,??2.5116e-02,??3.9811e-03,??6.3096e-04],[?0.0000e+00,??0.0000e+00,??0.0000e+00,??0.0000e+00,??0.0000e+00]])使用 Transformer-XL 的預訓練模型經典的就是 XLNet 啦,可以更好的處理較長的文本。
然后是關于 Transformer 的復雜度問題進行改進的文章。
Explicit Sparse Transformer
論文標題:
Explicit Sparse Transformer: Concentrated Attention Through Explicit Selection
論文鏈接:
https://arxiv.org/abs/1912.11637
代碼鏈接:
https://github.com/lancopku/Explicit-Sparse-Transformer
標準 Transformer 的復雜度為 ,但是否序列內的所有元素都有必要被關注到,是否有方法可以簡化這個機制?所以本文的“Sparse”重點就體現在只有少量的 token 參與 attention 分布的計算,以提升注意力機制的集中度。
即本來一個詞只和少量的詞有關,但是標準自注意力卻會給所有的詞都分配權重然后聚合,一種很自然的想法就是通過顯式選擇,只讓模型關注少數幾個元素就行。
模型圖如上圖,最左邊是標準計算注意力的路線,中間的是 Sparse 的實現,可以看到區別就在于中間多了一個手工選擇的 Sparsification,最右則是它的執行示意圖。簡單來說就是在算 softmax 分數之前先進行 top-k 選擇出少數的重要元素即可。具體來說先算內積:
然后人工按內積分數過濾 top-k 個元素,即下式中的 M 操作,其他的 P 則直接置為負無窮,這樣強制只讓 k 個元素被關注。
最后再把分數回乘給 V:
通過這種操作,可以使注意力更集中。這種減輕計算量的操作也讓 GPT-3 等模型能夠架得更大更暴力也取得了很好的但是玩不起效果。
Longformer
論文標題:
Longformer: The Long-Document Transformer
論文鏈接:
https://arxiv.org/abs/2004.05150
代碼鏈接:
https://github.com/allenai/longformer
Longformer 也算是一種比較經典的 Sparse 的方法了吧。一共提出了 3 種策略:
Sliding Window:如上圖 (b) 所示,跟 CNN 很像,給定一個固定的窗口大小 w,其兩邊都有個 w/2 個 token 與其做 attention。計算復雜度降為 O(n x w),即復雜度與序列長度呈線性關系。而且如果為每一層設置不同的窗口 size 可以很好地平衡模型效率和表示能力。
Dilated sliding window:如上圖 (c) 所示,類似擴張 CNN,可以在計算復雜度不變的情況下進一步擴大接收域。同樣的,如果在多頭注意力機制的每個頭設置不同的擴張配置,可以關注文章的不同局部上下文,特別是通過這種 Dilated 可以擴張甚至很遠的地方。
Global Attention :如圖 (d) 所示,計算全局 token 可能表征序列的整體特性。比如 BERT 中的 [CLS] 這種功能,復雜度降為 O(n)。
完整內容可以看原文。
Switch Transformer
論文標題:
Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity
論文鏈接:
https://arxiv.org/abs/2101.03961
代碼鏈接:
https://github.com/tensorflow/mesh/blob/master/mesh_tensorflow/transformer/moe.py
相比起 Sparse Attention 需要用到稀疏算子而很難發揮 GPU、TPU 硬件性能的問題。Switch Transformer 不需要稀疏算子,可以更好的適應 GPU、TPU 等稠密硬件。主要的想法是簡化稀疏路由。
即在自然語言 MoE (Mixture of experts)層中,只將 token 表征發送給單個專家而不是多個的表現會更好。模型架構如上圖,中間藍色部分是比價關鍵的部分,可以看到每次 router 都只把信息傳給分數 p 最大的單個 FFN。而這個操作可以大大降低計算量。
然后另一方面,其成功的原因是有一個很秀的并行策略,其同時結合了數據并行 + 模型并行 + expert 并行。具體如下圖:
其實對應模型架構來看,experts 并行是算子間的并行,其對應的 FFN 內部有算子級的模型并行,而整個 experts 在計算圖上又是個多并行 FFN 分支,這是算子間模型并行,所以能夠獲得更低的通信開銷,提高并行的效率。
Routing Transformers
論文標題:
Efficient Content-Based Sparse Attention with Routing Transformers
收錄會議:
TACL 2020
論文鏈接:
https://arxiv.org/abs/2003.05997
代碼鏈接:
https://github.com/google-research/google-research/tree/master/routing_transformer
和前兩篇文章的目標一樣,如何使標準 Transformer 的時間復雜度降低。Routing Transformer 將該問題建模為一個路由問題,目的是讓模型學會選擇詞例的稀疏聚類,所謂的聚類簇是關于每個鍵和查詢的內容的函數,而不僅僅與它們的絕對或相對位置相關。
簡單來說就是,作用差不多的詞是可以變成聚類到一個表示的,這樣來加速計算。
如上圖與其他模型的對比,圖中的每一行代表輸出,每一列代表輸入,對于 a 和 b 圖來說,著色的方塊代表每一個輸出行注意到的元素。對于路由注意力機制來說,不同的顏色代表輸出詞例的聚類中的成員。具體做法是先用一種公共的隨機權重矩陣對鍵和查詢的值進行投影:
然后把 R 中的向量用 k-means 聚類成 k 個簇,然后在每個簇 中加權求和上下文得到嵌入:
最后作者使用了 個簇,所以時間復雜度降維 。詳細可以看原論文和代碼實現。
Linformer
論文標題:
Linformer: Self-Attention with Linear Complexity
論文鏈接:
https://arxiv.org/abs/2006.04768
代碼鏈接:
https://github.com/tatp22/linformer-pytorch
從 到 O(n)!首先作者從理論和經驗上證明了自注意機制所形成的隨機矩陣可以近似為低秩矩陣,所以直接多引入線性投影將原始的縮放點積關注分解為多個較小的關注,也就是說這些小關注組合是標準注意力的低秩因數分解。即如上圖,在計算鍵 K 和值 V 時添加兩個線性投影矩陣 E 和 F,即:
同時還提供三種層級的參數共享:
Headwise: 所有注意力頭共享投影句子參數,即 Ei=E,Fi=F。
Key-Value: 所有的注意力頭的鍵值映射矩陣共享參數同一參數 ,即 Ei=Fi=E。
Layerwise: 所有層參數都共享。即對于所有層,都共享投射矩陣 E。
完整內容可以看原文,原文有理論證明低秩和分析。
Big Bird
論文標題:
Big Bird: Transformers for Longer Sequences
論文鏈接:
https://arxiv.org/abs/2007.14062
也是采用稀疏注意力機制,將復雜度下降到線性,即 O(N)。如上圖,big bird 主要包括三個部分的注意力:
Random Attention(隨機注意力)。如圖 a,對于每一個 token i,隨機選擇 r 個 token 計算注意力。
Window Attention(局部注意力)。如圖 b,用滑動窗口表示注意力計算 token 的局部信息。
Global Attention(全局注意力)。如圖 c,計算全局信息。這些在 Longformer 中也講過,可以參考對應論文。
最后把這三部分注意力結合在一起得到注意力矩陣 A,如圖 d 就是 BIGBIRD 的結果了,計算公式為:
H 是頭數,N(i) 是所有需要計算的 token,這里就是由三部分得來的稀疏部分,QKV 則是老伙伴了。
Transformer 變體未入榜番外篇。
Star-Transformer
論文標題:
Star-Transformer
收錄會議:
NAACL 2019
論文鏈接:
https://arxiv.org/abs/1902.09113
代碼鏈接:
https://github.com/fastnlp/fastNLP
問題:
Transformer 的自注意力機制每次都要計算所有詞之間的注意力,其計算復雜度為輸入長度的平方,結構很重
在語言序列中相鄰的詞往往本身就會有較強的相關性,似乎本來就不需要計算所有詞之間
解決:
Star-Transformer 用星型拓撲結構代替了全連通結構如上圖左邊是 Transformer,而右邊是 Star-Transformer。在右邊的圖中,所有序列中直接相鄰的詞可以直接相互作用,而非直接相鄰的元素則通過中心節點實現間接得信息傳遞,因此,復雜性從二次降低到線性,同時保留捕獲局部成分和長期依賴關系的能力。
Radical connections,捕捉非局部信息。即每兩個不相鄰的衛星節點都是兩跳鄰居,可以通過兩步更新接收非局部信息。
Ring connections,捕捉局部信息。由于文本輸入是一個序列,相鄰詞相連以捕捉局部成分之間的關系。值得注意的是它第一個節點和最后一個節點也連接起來,形成環形連接。
具體實現算法如下:
在初始化階段,衛星節點(周圍的詞節點)的初始值為各自相應的詞向量 ,而中心節點(集成節點)的初始值為所有詞節點詞向量的平均值 。
更新衛星節點。對于某衛星節點 ,先得到它的上下文信息 ,它由相鄰節點 ,中心節點 ,和這個節點對應的 token 詞嵌入 組成。然后多頭注意力更新特征,最后使用層歸一化。
更新中心節點(relay node)。中心節點與上一時刻和所有衛星信息的交互,所以同樣是多頭注意力 ,H 是可學習的位置編碼(它在所有時刻都是一樣的)。
交替更新 T 步,over。
更多閱讀
#投 稿?通 道#
?讓你的論文被更多人看到?
如何才能讓更多的優質內容以更短路徑到達讀者群體,縮短讀者尋找優質內容的成本呢?答案就是:你不認識的人。
總有一些你不認識的人,知道你想知道的東西。PaperWeekly 或許可以成為一座橋梁,促使不同背景、不同方向的學者和學術靈感相互碰撞,迸發出更多的可能性。?
PaperWeekly 鼓勵高校實驗室或個人,在我們的平臺上分享各類優質內容,可以是最新論文解讀,也可以是學習心得或技術干貨。我們的目的只有一個,讓知識真正流動起來。
?????來稿標準:
? 稿件確系個人原創作品,來稿需注明作者個人信息(姓名+學校/工作單位+學歷/職位+研究方向)?
? 如果文章并非首發,請在投稿時提醒并附上所有已發布鏈接?
? PaperWeekly 默認每篇文章都是首發,均會添加“原創”標志
?????投稿郵箱:
? 投稿郵箱:hr@paperweekly.site?
? 所有文章配圖,請單獨在附件中發送?
? 請留下即時聯系方式(微信或手機),以便我們在編輯發布時和作者溝通
????
現在,在「知乎」也能找到我們了
進入知乎首頁搜索「PaperWeekly」
點擊「關注」訂閱我們的專欄吧
關于PaperWeekly
PaperWeekly 是一個推薦、解讀、討論、報道人工智能前沿論文成果的學術平臺。如果你研究或從事 AI 領域,歡迎在公眾號后臺點擊「交流群」,小助手將把你帶入 PaperWeekly 的交流群里。
總結
以上是生活随笔為你收集整理的Transformer变体层出不穷,它们都长什么样?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安装xp系统不能开机怎么办 XP系统安装
- 下一篇: 30万奖金海华AI挑战赛 | 用机器挑战