1. 圖解什麼是 Transformer
Transformer 是 Google 團隊在 17 年 6 月提出的 NLP 經典之作,
由 Ashish Vaswani 等人在 2017 年發表的論文 Attention Is All You Need 中提出。
Transformer 在機器翻譯任務上的表現超過了 RNN,CNN,只用 encoder-decoder 和 attention 機制就能達到很好的效果,最大的優點是可以高效地並行化。
Transformer 是一種基於 encoder-decoder 結構的模型,
在 Encoder 中,
在 Decoder 中,
下面我們具體看一下其中這幾個概念,這里主要參考 Jay Alammar,他在 The Illustrated Transformer 中給出了很形象的講解。
例如我們要進行機器翻譯任務,輸入一種語言,經過 Transformer,會輸出另一種語言。
Transformer 的 encoder 由 6 個編碼器疊加組成,
decoder 也由 6 個解碼器組成,
在結構上都是相同的,但它們不共享權重。
每一個 encoder 都分為兩個子層:
每一個 decoder 也具有這兩個層,但還有一個注意力或差層,用來幫助解碼器關注輸入句子的相關部分
首先使用嵌入演算法將輸入的 word 轉換為 vector,
最下面的 encoder ,它的輸入就是 embedding 向量,
在每個 encoder 內部,
輸入向量經過 self-attention,再經過 feed-forward 層,
每個 encoder 的輸出向量是它正上方 encoder 的輸入,
向量的大小是一個超參數,通常設置為訓練集中最長句子的長度。
在這里,我們開始看到 Transformer 的一個關鍵性質,
即每個位置的單詞在 encoder 中都有自己的路徑,
self-attention 層中的這些路徑之間存在依賴關系,
然而在 feed-forward 層不具有那些依賴關系,
這樣各種路徑在流過 feed-forward 層時可以並行執行。
Positional Encoding 是一種考慮輸入序列中單詞順序的方法。
encoder 為每個輸入 embedding 添加了一個向量,這些向量符合一種特定模式,可以確定每個單詞的位置,或者序列中不同單詞之間的距離。
例如,input embedding 的維度為4,那麼實際的positional encodings如下所示:
在下圖中,是20個單詞的 positional encoding,每行代表一個單詞的位置編碼,即第一行是加在輸入序列中第一個詞嵌入的,每行包含 512 個值, 每個值介於 -1 和 1 之間,用顏色表示出來。
可以看到在中心位置分成了兩半,因為左半部分的值由一個正弦函數生成,右半部分由餘弦函數生成,然後將它們連接起來形成了每個位置的編碼向量局團扒。
當然這並不是位置編碼的唯一方法,只是這個方法能夠擴展到看不見的序列長度處,例如當我們要翻譯一個句子,這個句子的長度比我們訓練集中的任何一個句子都長時。
例如我們要翻譯:」The animal didn't cross the street because it was too tired」 這句話
這句話中的「it」是指什麼?它指的是 street 還是 animal?
這對人類來說是一個簡單的問題,但對算桐昌法來說並不簡單。
而 Self-Attention 讓演算法知道這里的 it 指的是 animal
當模型在處理每個單詞時,self-attention 可以幫助模型查看 input 序列中的其他位置,尋找相關的線索,來達到更好的編碼效果。它的作用就是將對其他相關單詞的「understanding」融入我們當前正在處理的單詞中。
例如上圖中,在第5層時,我們就知道 it 大概指的是 animal 了。
第一步,為編碼器的每個輸入單詞創建三個向量,
即 Query vector, Key vector, Value vector
這些向量通過 embedding 和三個矩陣相乘得到,
請注意,這些新向量的尺寸小於嵌入向量。它們的維數為64,而嵌入和編碼器輸入/輸出向量的維數為512.它們不一定要小,這是一種架構選擇,可以使多頭注意力計算(大多數)不變。
將x1乘以WQ得到Query向量 q1,同理得到Key 向量 和, Value 向量
這三個向量對 attention 的計算有很重要的作用
第二步,是計算一個得分
假設我們要計算一個例子中第一個單詞 「Thinking」 的 self-attention,就需要根據這個單詞,對輸入句子的每個單詞進行評分,這個分數決定了對其他單詞放置多少關注度。
分數的計算方法是,
例如我們正在考慮 Thinking 這個詞,就用它的 q1 去乘以每個位置的 ki
第三步和第四步,是將得分加以處理再傳遞給 softmax
將得分除以 8(因為論文中使用的 key 向量的維數是 64,8 是它的平方根)
這樣可以有更穩定的梯度,
然後傳遞給 softmax,Softmax 就將分數標准化,這樣加起來保證為 1。
這個 softmax 分數決定了每個單詞在該位置bbei表達的程度。
很明顯,這個位置上的單詞將具有最高的softmax分數,但有時候注意與當前單詞相關的另一個單詞是有用的。
第五步,用這個得分乘以每個 value 向量
目的讓我們想要關注單詞的值保持不變,並通過乘以 0.001 這樣小的數字,來淹沒不相關的單詞
第六步,加權求和這些 value 向量
這就是第一個單詞的 self-attention 的輸出
得到的向量接下來要輸入到前饋神經網路,在實際實現中用矩陣乘法的形式完成
論文中還增加一種稱為 multi-headed 注意力機制,可以提升注意力層的性能
它使得模型可以關注不同位置
雖然在上面的例子中,z1 包含了一點其他位置的編碼,但當前位置的單詞還是佔主要作用, 當我們想知道「The animal didn』t cross the street because it was too tired」 中 it 的含義時,這時就需要關注到其他位置
這個機制為注意層提供了多個「表示子空間」。下面我們將具體介紹,
1. 經過 multi-headed , 我們會得到和 heads 數目一樣多的 Query / Key / Value 權重矩陣組
論文中用了8個,那麼每個encoder/decoder我們都會得到 8 個集合。
這些集合都是隨機初始化的,經過訓練之後,每個集合會將input embeddings 投影到不同的表示子空間中。
2. 簡單來說,就是定義 8 組權重矩陣,每個單詞會做 8 次上面的 self-attention 的計算
這樣每個單詞會得到 8 個不同的加權求和 z
3. 但在 feed-forward 處只能接收一個矩陣,所以需要將這八個壓縮成一個矩陣
方法就是先將8個z矩陣連接起來,然後乘一個額外的權重矩陣WO
下圖顯示了在例句中,it 的不同的注意力 heads 所關注的位置,一個注意力的焦點主要集中在「animal」上,而另一個注意力集中在「tired」,換句話說,it 是 「animal」和「tired」的一種表現形式。
當然如果選了8個層,將所有注意力 heads 都添加到圖片中,就有點難以解釋了。
這里有一個細節,
即在每個 encoders 和 decoders 裡面的 self-attention, ffnn,encoders-decoders attention 層,都有 resial 連接,還有一步 layer-normalization
下面我們看一下 Decoder 部分
1. 輸入序列經過編碼器部分,然後將最上面的 encoder 的輸出變換成一組 attention 向量 K和V
這些向量會用於每個 decoder 的 encoder-decoder attention 層,有助於解碼器聚焦在輸入序列中的合適位置
重復上面的過程,直到 decoder 完成了輸出,每個時間步的輸出都在下一個時間步時喂入給最底部的 decoder,同樣,在這些 decoder 的輸入中也加入了位置編碼,來表示每個字的位置。
2. 解碼器中的 self attention 層與編碼器中的略有不同
在解碼器中,在 self attention 的 softmax 步驟之前,將未來的位置設置為 -inf 來屏蔽這些位置,這樣做是為了 self attention 層只能關注輸出序列中靠前的一些位置。
Encoder-Decoder Attention 層的工作方式與 multiheaded self-attention 類似,只是它用下面的層創建其 Queries 矩陣,從編碼器棧的輸出中獲取 Keys 和 Values 矩陣。
3. 解碼器最後輸出的是一個向量,如何把它變成一個單詞,這就要靠它後面的線性層和 softmax 層
線性層就是一個很簡單的全連接神經網路,將解碼器輸出的向量映射成一個更長的向量。
例如我們有 10,000 個無重復的單詞,那麼最後輸出的向量就有一萬維。
每個位置上的值代表了相應單詞的分數。
softmax 層將這個分數轉換為了概率。
我們選擇概率最大的所對應的單詞,就是當前時間步的輸出。
學習資源:
https://arxiv.org/pdf/1706.03762.pdf
https://jalammar.github.io/illustrated-transformer/
https://ai.googleblog.com/2017/08/transformer-novel-neural-network.html
2. Transformer詳解,輸入部分(詞嵌入、位置編碼)
由圖可知:
inputs和帶標簽的輸入分別進encoder和decoder
Positional Encoding
線性層
softmax層
由N個念渣編碼器堆疊而成
每個編碼器有兩個子層相連接
第一個子層橘好->多頭 自注意力機制 和規范化層以及一個殘差連接
第二個子層->全連接層和規范化層以及一個殘差連接
由N個解碼器堆疊而成
每個編碼器有三個子層相連接
第一個子層->一個多頭 自注意力機制 層和規范化層以及一個殘差連接
第二個子層->多頭 注意力機制 和規范化層以及仔伍悄一個殘差連接
第三個子層->全連接層和規范化層以及一個殘差連接
目的是為了將目標文本的 數字表示 ->向量表示,為了在高維空間捕捉詞彙間的關系
效果如下
在Transformer編碼器中沒有針對詞彙位置信息的處理,故需要在embedding層後加入位置編碼器,將 詞彙位置不同可能會產生不同語義的信息 加入到嵌入張量中(embedding),用來彌補位置信息的缺失。
3. 為何Transformer論文作者聲稱「Attention is all you need」
詳解Transformer (論文Attention Is All You Need). 正如論文的題目所說的,Transformer中拋棄了傳統的CNN和RNN,睜返整個網路悉基飢結構完全是由Attention機制組成。. 更准確地講,Transformer由且鋒悔
4. Swin Transformer
目前transformer從語言到視覺任務的挑戰主要是由於這兩個領域間的差異:
為了解決以上兩點,我們提出了層級Transformer,通過滑動窗口提取特徵的方式將使得 self.attention 的計算量降低為和圖像尺寸的線性相關。
我們觀察到將語言領域遷移到視覺領域的主要問模缺指題可以被總結為兩種:
在源扮耐碼實現中兩個模塊合二為一,稱為 PatchEmbedding 。輸入圖片尺寸為 的RGB圖片,將 4x4x3 視為一個patch,用一個linear embedding 層將patch轉換為任意dimension(通道)的feature。源碼中使用4x4的stride=4的conv實現。->
這是這篇論文的核心模塊。
window partition 分為 regular window partition 和 shift window partition ,對應於 W-MSA 和 SW-MSA 。通過窗口劃分,將輸入的 feature map 轉換為 num_windows*B, window_size, window_size, C ,其中 num_windows = H*W / window_size / window_size 。然後resize 到 num_windows*B, window_size*window_size, C 進行attention。源碼如下:
由 regular window partition 模塊 和 mutil-head self attention 模塊組成。
W-MSA相比於直接使用MSA主要是為了降低計算量。傳統的transformer都是基於全局來計算注意力,因此計算復雜度非常高。但是swin transformer通過對每個窗口施加註意力,從而減少了計算量。attention的主要計算過程如下:
假設每一個 window 的區塊大旦配小為 ,輸入的尺寸為 ,以下為原始的 和 的計算復雜度:
雖然 降低了計算量,但是由於將attention限制在 window 內,因此不重合的 window 缺乏聯系,限制了模型的性能。因此提出了 模塊。在 MSA 前面加上一個 cycle shift window partition
swin transformer中沒有使用 pooling 進行下采樣,而是使用了和yolov5中的 focus 層進行 feature map 的下采樣。 -> ,在使用一個全連接層-> ,在一個stage中將feature map的高寬減半,通道數翻倍。
基準模型結構命名為 Swin-B ,模型大小和計算復雜度和 ViT-B / DeiT-B 相近。同時我們也提出了 Swin-T , Swin-S 和 Swin-L ,分別對應 0.25× , 0.5× 和 2× 倍的模型尺寸和計算復雜度。 Swin-T 和 Swin-S 的計算復雜度分別和 ResNet-50 、 ResNet-101 相近。 默認設置為7。 代表第一層隱藏層的數量。
5. Transformer為什麼適合自動駕駛毫末智行CEO顧維灝親自揭秘
作為在自然語言處理(NLP)領域應用廣泛的深度學習模型,Transformer 近兩年強勢來襲,不僅橫掃 NLP 領域,而且在 CV 上也鋒芒畢露。江湖傳言,Transformer 架構就像是絕世高手的武林秘籍,得秘籍者得天下!
毫末智行作為國內首先大規模使用 Vision Transformer 技術的公司,CEO顧維灝第一時間在內部推動了此項技術的落地,力求在智能駕駛的賽道上能搶佔先機。
Transformer 的殺手鐧
據顧維灝介紹,最初的 Transformer 來自於 NLP,它的出現將 NLP 領域向前推動了一大步。其中的關鍵要素就是Transformer 具備:超強的序列建模能力、全局信息感知能力。
得益於這兩點優勢,Transformer 幾乎取代了基於 RNN 的演算法在 NLP 中的地位,也被引入到 CV 領域。但值得深入思考的是,Transformer 如何利用優勢在視覺領域發揮作用呢?
要知道 NLP 中處理的是語句,句子是天然的序列數據,所以很容易理解 Transformer 是如何處理它們的。可在視覺領域,「序列」的概念並不是顯式的,因此可以從空間和時間兩個維度去理解。
首先是空間維度,靜態圖像從空間上可以被劃分成多個區域(block),一種典型的劃分方式就是按照高和寬進行劃分,例如,一幅圖像的高和寬分別是 H 和 W,如果要求 block 的長寬均為 M,那麼最終會得到 (H/M W/M) 個 block。
其實可以把 block 看成是 NLP 句子中的詞,這里的只不過是「視覺詞」(visual words)。這樣一來,就可以將一幅圖像轉化成一個按照空間順序排列的 block 集合,一方面這樣的視角轉換保證了不丟失視覺信息,另一方面讓應用 Transformer 變得非常容易。
另一種則是通過時間維度去理解視覺中的序列,即視頻。視頻是由靜態的圖像幀組成,把每一幀看成是一個基本單元(同樣可以類別成句子中的詞),那麼就可以很自然地按照時間序列把一個片段組織起來,從而應用 Transformer 進行後續的特徵提取。
圖引自論文《An Image is Worth 16x16 Words Transformer for Image Recognition at scale」》
除了強大的序列建模能力,Transformer 的主要模塊 Multi-Head Self-Attention 可以同時感知到輸入序列的全局信息,這是 Transformer 相比於 CNN 的巨大優勢。在 CNN 中,信息只能從局部開始,隨著層數的增加,能夠被感知到的區域逐步增大。然而 Transformer 從輸入開始,每一層結構都可以看到所有的信息,並且建立基本單元之間的關聯,也意味著Transformer 能夠處理更加復雜的問題。
Transformer 的優化升級
目前處於 Transformer 在視覺中應用的早期,大家使用 Transformer 的方式主要參考了其在 NLP 中的應用經驗。但是,如果直接將 Transformer 應用到視覺上,也會存在一些難題。
其一,核心模塊多頭注意力機制(Multi-Head Self-Attention )的計算量與 block 的個數成正比,因此在視覺中 block 數量要遠多於 NLP 中句子的詞數,這就造成了計算量的陡增。
其二,Transformer 擅長全局關系的學習,對於局部細節信息關注有限,然而視覺中很多任務需要足夠豐富的細節信息做判斷,比如語義分割。
針對上述的問題, 毫末智行人工智慧研發團隊對核心模塊多頭注意力機制(Multi-Head Self-Attention)進行了優化,同時採用了金字塔的結構增強 Transformer 對於細節信息的感知。
圖引自論文《LeViT a Vision Transformer in ConvNet Clothing for Faster Inference》
Transformer 的未來演化
盡管我們在上面提到了 Transformer 的一些不盡如意之處,但隨著研究的深入,大家逐步發現在同一結構中結合 CNN 和 Transformer 各自的優勢,即可做到相互的揚長避短。在未來,把CNN 和 Transformer 進行整合將成為 Transformer 的演化路徑之一。
具體來說,主幹網使用 CNN,Head 使用 Transformer 結構,可以有效提升網路的速度(相比純使用 Transformer);相反,主幹網使用 Transformer 結構,Head 使用 CNN 的結構,可以有效提升結果精度(相比於純使用 CNN)。
其次,核心模塊 Multi-Head Self-Attention 內部也可以通過降低子空間的維度、對輸入 block 進行分組等手段降低其計算量且不至於損失過多精度。
最後,通過控制 block 的粒度,使 Transformer 能夠感知到不同尺度的信息,從而達到局部和全局的信息融合。
毫末智行團隊已經將上述的改進逐步添加到了毫末智行自己的模型中。未來,我們將不斷在提升速度的同時保證出色的精度,讓 Transformer 在實際的業務中生根發芽。
圖引自論文《End to End Object Detection with Transformers》
基於 Transformer 的感知演算法表現出了極強的泛化性和魯棒性,也因此顧維灝堅定認為,Transformer 的優秀特性極有可能在智能駕駛的場景中發揮出傳統 CNN 演算法所不能企及的感知能力。
目前, 毫末智行的人工智慧團隊正在逐步將基於 Transformer 的感知演算法應用到實際的道路感知問題,例如車道線檢測、障礙物檢測、可行駛區域分割、紅綠燈檢測&識別、道路交通標志檢測、點雲檢測&分割等。 未來,相關 Transformer 感知演算法更加和穩定成熟後,逐步替換基於 CNN 的感知演算法。
Transformer 技術的進一步應用,不僅為毫末智行在各條智能駕駛產品線上的視覺演算法落地帶來成倍的效率提升,還能夠讓各項視覺性能指標快速達到業內領先水平。
6. Transformer模型解析記錄
整個Transformer模型由Encoder和Decoder兩部分組成。Encoder負責對輸入數據的編碼,而Decoder負責對編碼後的數據進行解碼。
Encoder由N個結構相同,參數不共享的模塊組成,每個模塊又由多頭自注意力層和全連接層組成,其中多頭自注意力層和全連接層都加上了殘差連接和layer normalization。
Decoder與Encoder結構類似,相比於Encoder,Decoder部分多了一個 Multi-Head Attention ,第一個 Multi-Head Attention 採用Masked操作,第二個 Multi-Head Attention 的 K 和 V 使用Encoder的手輪備輸出,而Q使用上一個Decoder block的輸出。
Decoder的輸出通過一個線性層和softmax輸出下一個翻譯單詞的概率。
Encoder由N個結構相同,參數不共享的的Layer組成(論文中N=6),也即圖1左側的單元,最左邊有個「Nx」。
每個Layer由 Multi-Head Attention 和 Feed-Forward 兩個sub_layer組成。其中每個sub_layer都加了殘差連接(Resial Connect)和歸一化(Normalization)操作。則每個sub_layer的輸出可表示為:
Muti-Head Attention從結構上來看就是通過h個不同的線性變換將輸入 投影到h個不同的 組合,最後將h個不同的Attention結果拼接起來,最後經過一個Liner層得到Muti-Head Attention的輸出。
其中, 、
Muti-Head Attention輸出的維度是
關於Attention的詳細介紹,可以參考之前文檔:
Feed Forward也稱Position-wise feed-forward networks,該層主要提供非線性變換。之所以是position-wise是因為過線性層時每個位置i的變換參數是一樣的。
該層比較簡單,是一個兩層的全連接層,第一層的激活函數為 Relu,第二層不使用激活函數,對應公式為:
問 :Attention輸出之後的結果會和 相乘來進行維度變換,那這里為什麼又要增加一個2層的FFN網路呢?
答 :FFN網路的加入給模型增加了非線性(Relu激活函數),增加了模型的表現能力。當然去掉FFN層也是可以的,只不過效果上會差些。
Decoder是圖1的右半部分,與左半部分的Encoder類似,但又存在一些區別。
Decoder比Encoder多了一個Multi-Head Attention,第一個Multi-Head Attention採用Masked操作,因為在生成任務中,前面的詞語是看不到後面詞語的信息的,因此需要加入Masked來避免信息泄露。第二個Multi-Head Attention輸入的 是根據Encoder的輸出編碼矩陣映射而來,而 是根據上一個Decoder的輸出映射而來。
最後有一個 Softmax 層計算下一個翻譯單詞的概率。
模型在解碼的過程中需要畢毀注意的是訓練和預測不一樣。
在訓練時,解碼桐罩是一次全部decode出來,用上一步的ground truth來預測(mask矩陣也會改動,讓解碼時看不到未來的token);
而預測時,因為沒有ground truth了,需要一個個預測。
上面簡單介紹了 Encoder 和 Decoder 模塊,下面簡單介紹一下Transformer的Position Embedding。
引入Position Embedding主要是為了彌補Transformer模型對位置信息的不足,將Position Embedding與token Embedding相加後,即可保留各個token的位置信息。
論文作者提出了兩種添加位置信息的的方法:
一種方法是直接用不同頻率的正餘弦函數直接計算各個token的位置id,公式如下:
另一種方法是直接學習出一個Position Embedding。
通過實驗發現,兩種方法結果差不多,最後作者選擇了第一種方法。
Transformer 與 RNN 不同,可以比較好地並行訓練。
Transformer 本身是不能利用單詞的順序信息的,因此需要在輸入中添加位置 Embedding,否則 Transformer 就是一個詞袋模型了。
Transformer 的重點是 Self-Attention 結構,其中用到的 Q, K, V矩陣通過輸出進行線性變換得到。
Transformer 中 Multi-Head Attention 中有多個 Self-Attention,可以捕獲單詞之間多種維度上的相關系數 attention score。
Transformer 模型詳解 (推薦)
【NLP】Transformer模型原理詳解
【經典精讀】Transformer模型深度解讀
7. Transformer解讀(附pytorch代碼)
Transformer早在2017年就出現了,直到BERT問世,Transformer開始在NLP大放光彩,目前比較好的推進就是Transformer-XL(後期附上)。這里主要針對論文和程序進行解讀,如有不詳實之處,歡迎指出交流,如需了解更多細節之處,推薦知乎上 川陀學者 寫的。本文程序的git地址在 這里 。程序如果有不詳實之處,歡迎指出交流~
2017年6月,Google發布了一篇論文《Attention is All You Need》,在這篇論文中,提出了 Transformer 的模型尺搭,其旨在全部利用Attention方式來替代掉RNN的循環機制,從而通過實現並行化計算提速。在Transformer出現之前,RNN系列網路以及seq2seq+attention架構基本上鑄就了所有NLP任務的鐵桶江山。由於Attention模型本身就可以看到全局的信息, Transformer實現了完全不依賴於RNN結構僅利用Attention機制,在其並行性和對全局信息的有效處理上獲得了比之前更好的效果。
縱觀圖1整個Transformer的結構,其核心模塊其實就是三個:Multi-Head attention、Feed Forward 以及 Add&Norm。這里關於Multi-Head attention部分只講程序的實現,關於更多細節原理,請移至開頭推薦的知乎鏈接。
Transformer中的attention採用的是多頭的self-attention結構,並且在編碼器中,由於不同的輸入mask的部分不一樣,因此在softmax之前採用了mask操作,並且解碼時由於不能看到t時刻之後的數據,同樣在解碼器的第一個Multi-Head attention中採用了mask操作,但是二者是不同的。因為編碼器被mask的部分是需要在輸入到Transformer之前事先確定好,而解碼器第一個Multi-Head attention被mask的部分其實就是從t=1時刻開始一直到t=seq_len結束,對應於圖2。在圖2中,橫坐標表示解碼器一個batch上的輸入序列長度(也就是t),紫色部分為被mask的部分,黃色部分為未被mask的部分,可以看出,隨著t的增加,被mask的部分逐一減少。而解碼器第二個Multi-Head attention的mask操作和編碼器中是一樣的。
mask+softmax程序如下:
mask操作其實就是對於無效橡困返的輸入,用一個負無窮的值代替這個輸入,這樣在softmax的時候其值就是0。而在attention中(attention操作見下式),softmax的操作出來的結果其實就是attention weights,當attention weights為0時,表示不需要attention該位置的信息。
對於Multi-Head attention的實現,其實梁飢並沒有像論文原文寫的那樣,逐一實現多個attention,再將最後的結果concat,並且通過一個輸出權重輸出。下面通過程序和公式講解一下實際的實現過程,這里假設 , , 的來源是一樣的,都是 ,其維度為[batch_size, seq_len, input_size]。(需要注意的是在解碼器中第二個Multi-Head的輸入中 與 的來源不一樣)
首先,對於輸入 ,通過三個權重變數得到 , , ,此時三者維度相同,都是[batch, seq_len, d_model],然後對其進行維度變換:[batch, seq_len, h, d_model//h]==>[batch, h, seq_len, d]==>[batch×h, seq_len, d],其中d=d_model//h,因此直接將變換後的 , , 直接做DotProctAttention就可以實現Multi-Head attention,最後只需要將DotProctAttention輸出的維度依次變換回去,然後乘以輸出權重就可以了。關於程序中的參數valid_length已在程序中做了詳細的解讀,這里不再贅述,注意的是輸入的valid_length是針對batch這個維度的,而實際操作中由於X的batch維度發生了改變(由batch變成了batch×h),因此需要對valid_length進行復制。
FFN的實現是很容易的,其實就是對輸入進行第一個線性變換,其輸出加上ReLU激活函數,然後在進行第二個線性變換就可以了。
Add&norm的實現就是利用殘差網路進行連接,最後將連接的結果接上LN,值得注意的是,程序在Y的輸出中加入了dropout正則化。同樣的正則化技術還出現在masked softmax之後和positional encoding之後。
positional encoding的實現很簡單,其實就是對輸入序列給定一個唯一的位置,採用sin和cos的方式給了一個位置編碼,其中sin處理的是偶數位置,cos處理的是奇數位置。但是,這一塊的工作確實非常重要的,因為對於序列而言最主要的就是位置信息,顯然BERT是沒有去採用positional encoding(盡管在BERT的論文里有一個Position Embeddings的輸入,但是顯然描述的不是Transformer中要描述的位置信息),後續BERT在這一方面的改進工作體現在了XLNet中(其採用了Transformer-XL的結構),後續的中再介紹該部分的內容。
無論是編碼器還是解碼器,其實都是用上面說的三個基本模塊堆疊而成,具體的實現細節大家可以看開頭的git地址,這里需要強調的是以下幾點:
中出現的程序都在開頭的git中了,直接執行main.ipynb就可以運行程序,如有不詳實之處,還請指出~~~
8. swin transformer理解要點
這是跑通的分類以及分割源碼介紹,大家有需要可以參考一下:
1、 Swin-Transformer分類源碼(已跑通)
2、侍辯滾 Swin-Transformer分割源碼(已跑通)
3、 Swin-Unet(分割改編)
我們假設圖片的大小是224×224的,窗口大小是固定的,7×7。這里每個方框都是一個窗口,每個窗口是固定有7×7個patch,但是patch的大小是不固定的,它會隨著patch merging的操作而發生變化。比如我們看這兒,patch大小是4×4的,那怎麼變成8×8呢?我們把周邊4個窗口的patch拼在一起,相當於patch擴大了2×2倍,從而得到8×8大小的patch。
我們發現經過這一系列的操作之後,patch的數目在變少,最後整張圖只有一個窗口,7個patch。所以我們可以認為降采樣是指讓patch的數量減少,但是patch的大小在變大。
這便是對ViT的一個改進,ViT從頭至尾都是對全局做self-attention,而swin-transformer是一個窗口在放大的過程,然後self-attention的計算是以窗口為單位去計算的,這樣相當於引入了局部聚合的信息,和CNN的卷積過灶瞎程很相似,就像是CNN的步長和卷積核大小一樣,這樣就做到了窗口的不重合,區別在於CNN在每個窗口做的是卷積的計算,每個窗口最後得到一個值,這個值代表著這個窗口的特徵。而swin transformer在每個窗口做的是self-attention的計算,得到的是一個更新過的窗口,然後通過patch merging的操作,把窗口做了個合並,再繼續對這個合並後的窗口做self-attention的計算。
其實這邊困擾了我一小下,因為我們印象中降采樣都是像CNN一樣,會變小,但是swin transformer沒有給我們變小的感覺。其實這就是感受野沒理解到位的問題,CNN到最後,設計適當,最後一個特徵圖的感受野是可以放大到整張圖的,swin transformer最後一個stage也是一個窗口涵蓋了整張圖。
Swin-transformer是怎麼把復雜度降低的呢? Swin Transformer Block這個模塊和普通的transformer的區別就在於W-MSA,而它就是降低復雜度計算的大功臣。
關於復雜度的計算,我簡單的給大家介紹一下,首先是transformer本身基於全局的復雜度計算,這一塊兒講起來有點復雜,感興趣的同學我們可以會後一起探討推導過程。在這里,我們假設已知MSA的復雜度是圖像大小的平方,根據MSA的復雜度,我們可以得出A的復雜度是(3×3)²,最後復雜度是81。Swin transformer是在每個local windows(紅色部分)計算self-attention,根據MSA的復雜度我們可以得出每個紅色窗口的復雜度是1×1的平方,也就是1的四次方。然後9個窗口,這些窗口的復雜度加和,最後B的復雜度為9。
W-MSA雖然降低了計算復雜度,但是不重合的window之間缺乏信息交流,所以想要窗口之間的信息有所交流,那麼就可以把左圖演化成右圖這樣,但是這就產生了一個問題,如此操作,會產生更多的windows,並且其中一部分window小於普通的window,比如4個window -> 9個window,windows數量增加了一倍多。這計算量又上來了。因此我們有兩個目的,Windows數量不能多老余,window之間信息得有交流。
我們看到,原來的圖被劃分了9個窗口,中間的區域A就是信息交流的證明。我們先把左上部分(藍色以外的窗口)移動到右下,然後再用切分四塊的方法去切這個圖片,這時候區域A就被隔出來了,達到了我們想要的效果。
transformer的出現並不是為了替代CNN。因為transformer有著CNN沒有的功能性,它不僅可以提取特徵,還可以做很多CNN做不到的事情,比如多模態融合。而swin transformer就是一個趨勢,將CNN與transformer各自的優勢有效的結合了起來。這是暫時對它的一些細節補充。最近聽說MLP出來了,還沒有細看,時代進展未免也太快了,手裡針對ViT改進的文章還沒投出去,就已經開始要立不住腳了。
希望可以幫助到大家,如果你覺得這篇文章對你有一定的幫助,那就點個贊支持一下吧!如果有什麼問題的話也可以在文章下面評論,我們一起交流解決問題!
以下是我所有文章的目錄,大家如果感興趣,也可以前往查看
👉戳右邊: 打開它,也許會看到很多對你有幫助的文章
9. 為什麼說Transformer的注意力機制是相對廉價的注意力機制相對更對於RNN系列及CNN系列演算法有何優勢
QA形式對自然語言處理中注意力機制(Attention)進行總結,並對Transformer進行深入解析。
二、Transformer(Attention Is All You Need)詳解
1、Transformer的整體架構是怎樣的?由哪些部分組成?
2、Transformer Encoder 與 Transformer Decoder 有哪些不同?
3、Encoder-Decoder attention 與self-attention mechanism有哪些不同?
4、multi-head self-attention mechanism具體的計算過程是怎樣的?
5、Transformer在GPT和Bert等詞向量預訓練模型中具體是怎麼應用的?有什麼變化?
一、Attention機制剖析
1、為什麼要引入Attention機制?
根據通用近似定理,前饋網路和循環網路都有很強的能力。但為什麼還要引入注意力機制呢?
計算能力的限制:當要記住很多「信息「,模型就要變得更復雜,然而目前計算能力依然是限制神經網路發展的瓶頸。
優化演算法的限制:雖然局部連接、權重共享以及pooling等優化操作可以讓神經網路變得簡單一些,有效緩解模型復雜度和表達能力之間的矛盾;但是,如循環神經網路中的長距離以來問題,信息「記憶」能力並不高。
可以藉助人腦處理信息過載的方式,例如Attention機制可以提高神經網路處理信息的能力。
2、Attention機制有哪些?(怎麼分類?)
當用神經網路來處理大量的輸入信息時,也可以借鑒人腦的注意力機制,只 選擇一些關鍵的信息輸入進行處理,來提高神經網路的效率。按照認知神經學中的注意力,可以總體上分為兩類:
聚焦式(focus)注意力:自上而下的有意識的注意力,主動注意——是指有預定目的、依賴任務的、主動有意識地聚焦於某一對象的注意力;
顯著性(saliency-based)注意力:自下而上的有意識的注意力,被動注意——基於顯著性的注意力是由外界刺激驅動的注意,不需要主動干預,也和任務無關;可以將max-pooling和門控(gating)機制來近似地看作是自下而上的基於顯著性的注意力機制。
在人工神經網路中,注意力機制一般就特指聚焦式注意力。
3、Attention機制的計算流程是怎樣的?
Attention機制的實質其實就是一個定址(addressing)的過程,如上圖所示:給定一個和任務相關的查詢Query向量q,通過計算與Key的注意力分布並附加在Value上,從而計算Attention Value,這個過程實際上是Attention機制緩解神經網路模型復雜度的體現:不需要將所有的N個輸入信息都輸入到神經網路進行計算,只需要從X中選擇一些和任務相關的信息輸入給神經網路。
step1-信息輸入:用X= [x1, · · · , xN ]表示N 個輸入信息;
step2-注意力分布計算:令Key=Value=X,則可以給出注意力分布
我們將稱之為注意力分布(概率分布),為注意力打分機制,有幾種打分機制:
step3-信息加權平均:注意力分布可以解釋為在上下文查詢q時,第i個信息受關注的程度,採用一種「軟性」的信息選擇機制對輸入信息X進行編碼為:
這種編碼方式為軟性注意力機制(soft Attention),軟性注意力機制有兩種:普通模式(Key=Value=X)和鍵值對模式(Key!=Value)。
4、Attention機制的變種有哪些?
與普通的Attention機制(上圖左)相比,Attention機制有哪些變種呢?
變種1-硬性注意力:之前提到的注意力是軟性注意力,其選擇的信息是所有輸入信息在注意力 分布下的期望。還有一種注意力是只關注到某一個位置上的信息,叫做硬性注意力(hard attention)。硬性注意力有兩種實現方式:(1)一種是選取最高概率的輸入信息;(2)另一種硬性注意力可以通過在注意力分布式上隨機采樣的方式實現。硬性注意力模型的缺點:
變種2-鍵值對注意力:即上圖右邊的鍵值對模式,此時Key!=Value,注意力函數變為:
變種3-多頭注意力:多頭注意力(multi-head attention)是利用多個查詢Q = [q1, · · · , qM],來平行地計算從輸入信息中選取多個信息。每個注意力關注輸入信息的不同部分,然後再進行拼接:
5、一種強大的Attention機制:為什麼自注意力模型(self-Attention model)在長距離序列中如此強大?
(1)卷積或循環神經網路難道不能處理長距離序列嗎?
當使用神經網路來處理一個變長的向量序列時,我們通常可以使用卷積網路或循環網路進行編碼來得到一個相同長度的輸出向量序列,如圖所示:
從上圖可以看出,無論卷積還是循環神經網路其實都是對變長序列的一種「局部編碼」:卷積神經網路顯然是基於N-gram的局部編碼;而對於循環神經網路,由於梯度消失等問題也只能建立短距離依賴。
(2)要解決這種短距離依賴的「局部編碼」問題,從而對輸入序列建立長距離依賴關系,有哪些辦法呢?
由上圖可以看出,全連接網路雖然是一種非常直接的建模遠距離依賴的模型, 但是無法處理變長的輸入序列。不同的輸入長度,其連接權重的大小也是不同的。
這時我們就可以利用注意力機制來「動態」地生成不同連接的權重,這就是自注意力模型(self-attention model)。由於自注意力模型的權重是動態生成的,因此可以處理變長的信息序列。
總體來說,為什麼自注意力模型(self-Attention model)如此強大:利用注意力機制來「動態」地生成不同連接的權重,從而處理變長的信息序列。
(3)自注意力模型(self-Attention model)具體的計算流程是怎樣的呢?
同樣,給出信息輸入:用X = [x1, · · · , xN ]表示N 個輸入信息;通過線性變換得到為查詢向量序列,鍵向量序列和值向量序列:
上面的公式可以看出,self-Attention中的Q是對自身(self)輸入的變換,而在傳統的Attention中,Q來自於外部。
注意力計算公式為:
自注意力模型(self-Attention model)中,通常使用縮放點積來作為注意力打分函數,輸出向量序列可以寫為:
二、Transformer(Attention Is All You Need)詳解
從Transformer這篇論文的題目可以看出,Transformer的核心就是Attention,這也就是為什麼本文會在剖析玩Attention機制之後會引出Transformer,如果對上面的Attention機制特別是自注意力模型(self-Attention model)理解後,Transformer就很容易理解了。
1、Transformer的整體架構是怎樣的?由哪些部分組成?
Transformer其實這就是一個Seq2Seq模型,左邊一個encoder把輸入讀進去,右邊一個decoder得到輸出:
Transformer=Transformer Encoder+Transformer Decoder
(1)Transformer Encoder(N=6層,每層包括2個sub-layers):
sub-layer-1:multi-head self-attention mechanism,用來進行self-attention。
sub-layer-2:Position-wise Feed-forward Networks,簡單的全連接網路,對每個position的向量分別進行相同的操作,包括兩個線性變換和一個ReLU激活輸出(輸入輸出層的維度都為512,中間層為2048):
每個sub-layer都使用了殘差網路:
(2)Transformer Decoder(N=6層,每層包括3個sub-layers):
sub-layer-1:Masked multi-head self-attention mechanism,用來進行self-attention,與Encoder不同:由於是序列生成過程,所以在時刻 i 的時候,大於 i 的時刻都沒有結果,只有小於 i 的時刻有結果,因此需要做Mask。
sub-layer-2:Position-wise Feed-forward Networks,同Encoder。
sub-layer-3:Encoder-Decoder attention計算。
2、Transformer Encoder 與 Transformer Decoder 有哪些不同?
(1)multi-head self-attention mechanism不同,Encoder中不需要使用Masked,而Decoder中需要使用Masked;
(2)Decoder中多了一層Encoder-Decoder attention,這與 self-attention mechanism不同。
3、Encoder-Decoder attention 與self-attention mechanism有哪些不同?
它們都是用了 multi-head計算,不過Encoder-Decoder attention採用傳統的attention機制,其中的Query是self-attention mechanism已經計算出的上一時間i處的編碼值,Key和Value都是Encoder的輸出,這與self-attention mechanism不同。代碼中具體體現:
4、multi-head self-attention mechanism具體的計算過程是怎樣的?
Transformer中的Attention機制由Scaled Dot-Proct Attention和Multi-Head Attention組成,上圖給出了整體流程。下面具體介紹各個環節:
Expand:實際上是經過線性變換,生成Q、K、V三個向量;
Split heads: 進行分頭操作,在原文中將原來每個位置512維度分成8個head,每個head維度變為64;
Self Attention:對每個head進行Self Attention,具體過程和第一部分介紹的一致;
Concat heads:對進行完Self Attention每個head進行拼接;
上述過程公式為:
5、Transformer在GPT和Bert等詞向量預訓練模型中具體是怎麼應用的?有什麼變化?
GPT中訓練的是單向語言模型,其實就是直接應用Transformer Decoder;
Bert中訓練的是雙向語言模型,應用了Transformer Encoder部分,不過在Encoder基礎上還做了Masked操作;
BERT Transformer 使用雙向self-attention,而GPT Transformer 使用受限制的self-attention,其中每個token只能處理其左側的上下文。雙向 Transformer 通常被稱為「Transformer encoder」,而左側上下文被稱為「Transformer decoder」,decoder是不能獲要預測的信息的。