之前寫過(guò)一篇Attention is all you need的論文筆記. 回看時(shí)感覺(jué)內(nèi)容不夠清晰并且存在理解問(wèn)題.
Transformer 主要分為encoder和decoder兩個(gè)部分, 其中主要模塊是multi-head attention層. 這些都是比較廣為人知的了, 這一篇就來(lái)扣一下細(xì)節(jié)吧.
Attention
論文中提到的兩類attention層: dot-product attention 以及?additive attention. 兩者區(qū)別就在于用于得到最后相似度矩陣的K,Q矩陣匹配過(guò)程的計(jì)算方式不同. dot-product 采用的是我們常用的點(diǎn)積, 對(duì)應(yīng)到多個(gè)tokens構(gòu)成的矩陣也就變成了矩陣乘法, 最后得到的是n*n維的score矩陣分別代表不同token之間的兼容性相似性或者說(shuō)匹配性. 同時(shí)softmax操作不改變矩陣的維度, 僅僅是針對(duì)其同一行(dim=1)的值進(jìn)行歸一. additive attention則是利用一層前饋網(wǎng)絡(luò)而非內(nèi)積來(lái)代表兼容性函數(shù) score = f(K, Q)?
根據(jù)論文表述, 兩種方法在token維度較低的時(shí)候效果差距不大, 但是維度變高時(shí)additive會(huì)好一些. 作者認(rèn)為主要原因可能是內(nèi)積中的求和操作使得最終得到的score值的方差隨token維度增加而增加, 從而導(dǎo)致經(jīng)過(guò)softmax后向量中某些值變的很極端接近0和1, 使得最終梯度變的trivial.
那么為了解決作者認(rèn)為的這個(gè)潛在問(wèn)題, 最直觀的方式就是在進(jìn)行softmax前對(duì)score進(jìn)行放縮, 根據(jù)內(nèi)積求和數(shù)等于矩陣K的第二個(gè)維度, 那么只要放縮sqrt(K的channel維)就可以使得方差縮小K的channel維倍, 從而實(shí)現(xiàn)了對(duì)方差大小的一個(gè)限制.
最終這種基于dot-product 和縮放操作的attention稱為scaled dot-product attention.
Multi-attention vs self attention
self attention就是上面所講的attention層, 其參數(shù)主要是從tokens獲得QKV矩陣的線性層中的參數(shù).
而multi-attention和self-attention的關(guān)系就像卷積層和單個(gè)kernel的關(guān)系. 說(shuō)白了就是用不同的attention層處理同一組tokens, 并最后將所得到的多個(gè)新tokens拼接(concatenate)并再過(guò)一個(gè)線性層做維度還原(保持tokens維度在attention層前后一致). 這里其實(shí)論文提了一句:
"Multi-head attention allows the model to jointly attend to information from different representation subspaces at different positions. With a single attention head, averaging inhibits this."
實(shí)際上, 最后得到的多組tokens, 我們按第二個(gè)維度(dim=1)進(jìn)行拼接后, 所經(jīng)過(guò)的線性層實(shí)際上是一個(gè)維度映射(坐標(biāo)系轉(zhuǎn)換), 所以這里的操作和簡(jiǎn)單把不同組tokens求平均是不等價(jià)的, 求平均只是這種變化的一種特例.
Position-wise Feed-Forward Networks
以前看的時(shí)候總覺(jué)得feed forward是最簡(jiǎn)單的, 沒(méi)什么東西, 但是實(shí)際上這里還是有個(gè)細(xì)節(jié)的, 那就是它是position-wise的. Position-wise的意思的就是不同token是分別采用同一個(gè)線性層進(jìn)行計(jì)算的, 這里包含的一個(gè)信息就是并行, 既然不同token計(jì)算過(guò)程不再依賴那么實(shí)際上彼此間也不需要像attention層等待同步. 所以當(dāng)我們attention層通過(guò)矩陣乘法在GPU上并行后, 此處的feed forward仍然可以保留并行屬性.
也就是兩個(gè)線性層中加一個(gè)ReLU, 考慮到和卷積操作的類似, 也可以理解為核大小為1的兩層卷積.
Positional Encoding
目的是考慮到attention并行機(jī)制忽視了tokens的位置和順序信息, 那么為了保留這部分信息, 就需要我們?nèi)藶樘砑舆M(jìn)去. 具體而言, positional encoding信息不管是在transformer的encoder部分還是decoder部分都是在模型輸入處添加進(jìn)去的, 并且設(shè)置維度和tokens在模型中固定的維度也一樣, 僅僅是把這個(gè)encoding值加到原始tokens值中去即可.
計(jì)算positional encoding的方式應(yīng)該有不少, 可學(xué)習(xí)的或者固定函數(shù)生成的. 論文中作者使用的是余弦函數(shù), 且把位置和維度都當(dāng)作參數(shù)輸入了, 維度決定周期, 位置決定相位.
作者表述這種方式可以使得當(dāng)相位差固定的時(shí)候, 兩個(gè)PE函數(shù)之間是線性關(guān)系(其實(shí)就是三角函數(shù)分解最后系數(shù)因?yàn)橄辔徊罟潭▽?dǎo)致得到三角函數(shù)值也固定, 所以就成了線性關(guān)系). 那么這種關(guān)系可能容易被模型所捕獲.
Decoder
那么不得不說(shuō)decoder要想理解還是要看代碼吧.?
decoder首先邏輯上是auto-regression的, 也就是會(huì)把自己的輸出當(dāng)作下一次的輸入, 循環(huán)計(jì)算從而得到最終的序列. 所以每次decoder的輸入都是之前的輸出, 而最開(kāi)始的輸入則是一個(gè)啟動(dòng)標(biāo)記(start).?
架構(gòu)上來(lái)看decoder的單一模塊比encoder的單一模塊中間要多一個(gè)multi-head attention層, 這一層以decoder前一層輸出的tokens計(jì)算Q矩陣, 而利用encoder已經(jīng)計(jì)算得到輸出的tokens計(jì)算K和V.
細(xì)節(jié)上, decoder的multi-head attention層在計(jì)算score的時(shí)候會(huì)有mask操作. 這個(gè)操作就是將我們QK矩陣乘法得到的矩陣中position大于自己的位置設(shè)為負(fù)無(wú)窮(-inf), 這樣經(jīng)過(guò)softmax時(shí)就會(huì)使得這些position對(duì)應(yīng)的值為0, 從而避免經(jīng)過(guò)attention層新得到的token會(huì)被其身后其他tokens所影響.
總結(jié)
transformer大體流程網(wǎng)上一搜就有, 但是具體細(xì)節(jié)對(duì)于理解還是至關(guān)重要.