解析Transformer模型

2021-01-18 磐創AI


轉自 | GiantPandaCV

作者 | zzk

【導讀】GiantPandaCV導語:這篇文章為大家介紹了一下Transformer模型,Transformer模型原本是NLP中的一個Idea,後來也被引入到計算機視覺中,例如前面介紹過的DETR就是將目標檢測算法和Transformer進行結合,另外基於Transformer的魔改工作最近也層出不窮,感興趣的同學可以了解一下。前言

Google於2017年提出了《Attention is all you need》,拋棄了傳統的RNN結構,「設計了一種Attention機制,通過堆疊Encoder-Decoder結構」,得到了一個Transformer模型,在機器翻譯任務中「取得了BLEU值的新高」。在後續很多模型也基於Transformer進行改進,也得到了很多表現不錯的NLP模型,前段時間,相關工作也引申到了CV中的目標檢測,可參考FAIR的DETR模型

引入問題

常見的時間序列任務採用的模型通常都是RNN系列,然而RNN系列模型的順序計算方式帶來了兩個問題

某個時間狀態,依賴於上一時間步狀態,導致模型「不能通過並行計算來加速」RNN系列的魔改模型比如GRU, LSTM,雖然「引入了門機制」(gate),但是對「長時間依賴的問題緩解能力有限」,不能徹底解決

因此我們設計了一個全新的結構Transformer,通過Attention注意力機制,來對時間序列更好的建模。同時我們不需要像RNN那樣順序計算,從而能讓模型更能充分發揮並行計算性能。

模型架構TransFormer模型架構一覽

上圖展示的就是Transformer的結構,左邊是編碼器Encoder,右邊是解碼器Decoder。通過多次堆疊,形成了Transformer。下面我們分別看下Encoder和Decoder的具體結構

Encoder編碼器架構

Encoder結構如上,它由以下sublayer構成

Multi-Head Attention 多頭注意力Self Attention

Multi-Head Attention多頭注意力層是由多個self attention來組成的,因此我們先講解下模型的自注意力機制。

在一句話中,如果給每個詞都分配相同的權重,那麼會很難讓模型去學習詞與詞對應的關係。舉個例子

The animal didn't cross the street because it was too tired

我們需要讓模型去推斷 it 所指代的東西,當我們給模型加了注意力機制,它的表現如下

注意力機制效果

我們通過注意力機制,讓模型能看到輸入的各個單詞,然後它會更加關注於 The animal,從而更好的進行編碼。

論文裡將attention模塊記為「Scaled Dot-Product Attention」,計算如下

自注意力機制一覽

其中 Q, K, V(向量長度為64)是由輸入X經過三個不同的權重矩陣(shape=512x64)計算得來,

經過Embedding的向量X,與右邊三個權重矩陣相乘,分別得到Query,Key,Value三個向量

下面我們看一個具體例子

注意力機制運算過程

以Thinking這個單詞為例,我們需要計算整個句子所有詞與它的score。

X1是Thinking對應的Embedding向量。然後我們與Key向量進行相乘,來計算相關性,這裡記作Score。「這個過程可以看作是當前詞的搜索q1,與其他詞的key去匹配」。當相關性越高,說明我們需要放更多注意力在上面。Softmax後的結果與Value向量相乘,得到最終結果MultiHead-Attention

理解了自注意力機制後,我們可以很好的理解多頭注意力機制。簡單來說,多頭注意力其實就是合併了多個自注意力機制的結果

多頭注意力機制概覽,將多個自注意力機制並在一起

我們以原文的8個注意力頭為例子,多頭注意力的操作如下

分別計算出每個自注意力模塊的結果Z0, Z1, Z2.....Z7

經過一層全連接層,得到最終的輸出最後多頭注意力的表現類似如下

多頭注意力機制效果Feed Forward Neural Network

這個FFN模塊比較簡單,本質上全是兩層全連接層加一個Relu激活

Positional Encoding

摒棄了CNN和RNN結構,我們無法很好的利用序列的順序信息,因此我們採用了額外的一個位置編碼來進行緩解

然後與輸入相加,通過引入位置編碼,給詞向量中賦予了單詞的位置信息

位置編碼

下圖是總Encoder的架構

Encoder的整體結構Decoder

Decoder的結構與Encoder的結構很相似

Decoder結構

「只不過額外引入了當前翻譯和編碼特徵向量的注意力」,這裡就不展開了。

代碼

這裡參考的是TensorFlow的官方實現notebook transformer.ipynb

位置編碼
def get_angles(pos, i, d_model):
  angle_rates = 1 / np.power(10000, (2 * (i//2)) / np.float32(d_model))
  return pos * angle_rates

def positional_encoding(position, d_model):
  angle_rads = get_angles(np.arange(position)[:, np.newaxis],
                          np.arange(d_model)[np.newaxis, :],
                          d_model)
  
  # apply sin to even indices in the array; 2i
  angle_rads[:, 0::2] = np.sin(angle_rads[:, 0::2])
  
  # apply cos to odd indices in the array; 2i+1
  angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])
    
  pos_encoding = angle_rads[np.newaxis, ...]
    
  return tf.cast(pos_encoding, dtype=tf.float32)

這裡就是根據公式,生成位置編碼

Scaled-Dot Attention
def scaled_dot_product_attention(q, k, v, mask):
  """Calculate the attention weights.
  q, k, v must have matching leading dimensions.
  k, v must have matching penultimate dimension, i.e.: seq_len_k = seq_len_v.
  The mask has different shapes depending on its type(padding or look ahead) 
  but it must be broadcastable for addition.
  
  Args:
    q: query shape == (..., seq_len_q, depth)
    k: key shape == (..., seq_len_k, depth)
    v: value shape == (..., seq_len_v, depth_v)
    mask: Float tensor with shape broadcastable 
          to (..., seq_len_q, seq_len_k). Defaults to None.
    
  Returns:
    output, attention_weights
  """

  matmul_qk = tf.matmul(q, k, transpose_b=True)  # (..., seq_len_q, seq_len_k)
  
  # scale matmul_qk
  dk = tf.cast(tf.shape(k)[-1], tf.float32)
  scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)

  # add the mask to the scaled tensor.
  if mask is not None:
    scaled_attention_logits += (mask * -1e9)  

  # softmax is normalized on the last axis (seq_len_k) so that the scores
  # add up to 1.
  attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)  # (..., seq_len_q, seq_len_k)

  output = tf.matmul(attention_weights, v)  # (..., seq_len_q, depth_v)

  return output, attention_weights

輸入的是Q, K, V矩陣和一個mask掩碼向量根據公式進行矩陣相乘,得到最終的輸出,以及注意力權重

MultiheadAttention

這裡的代碼就是將多個注意力結果組合在一起

class MultiHeadAttention(tf.keras.layers.Layer):
  def __init__(self, d_model, num_heads):
    super(MultiHeadAttention, self).__init__()
    self.num_heads = num_heads
    self.d_model = d_model
    
    assert d_model % self.num_heads == 0
    
    self.depth = d_model // self.num_heads
    
    self.wq = tf.keras.layers.Dense(d_model)
    self.wk = tf.keras.layers.Dense(d_model)
    self.wv = tf.keras.layers.Dense(d_model)
    
    self.dense = tf.keras.layers.Dense(d_model)
        
  def split_heads(self, x, batch_size):
    """Split the last dimension into (num_heads, depth).
    Transpose the result such that the shape is (batch_size, num_heads, seq_len, depth)
    """
    x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))
    return tf.transpose(x, perm=[0, 2, 1, 3])
    
  def call(self, v, k, q, mask):
    batch_size = tf.shape(q)[0]
    
    q = self.wq(q)  # (batch_size, seq_len, d_model)
    k = self.wk(k)  # (batch_size, seq_len, d_model)
    v = self.wv(v)  # (batch_size, seq_len, d_model)
    
    q = self.split_heads(q, batch_size)  # (batch_size, num_heads, seq_len_q, depth)
    k = self.split_heads(k, batch_size)  # (batch_size, num_heads, seq_len_k, depth)
    v = self.split_heads(v, batch_size)  # (batch_size, num_heads, seq_len_v, depth)
    
    # scaled_attention.shape == (batch_size, num_heads, seq_len_q, depth)
    # attention_weights.shape == (batch_size, num_heads, seq_len_q, seq_len_k)
    scaled_attention, attention_weights = scaled_dot_product_attention(
        q, k, v, mask)
    
    scaled_attention = tf.transpose(scaled_attention, perm=[0, 2, 1, 3])  # (batch_size, seq_len_q, num_heads, depth)

    concat_attention = tf.reshape(scaled_attention, 
                                  (batch_size, -1, self.d_model))  # (batch_size, seq_len_q, d_model)

    output = self.dense(concat_attention)  # (batch_size, seq_len_q, d_model)
        
    return output, attention_weights

FFN
def point_wise_feed_forward_network(d_model, dff):
  return tf.keras.Sequential([
      tf.keras.layers.Dense(dff, activation='relu'),  # (batch_size, seq_len, dff)
      tf.keras.layers.Dense(d_model)  # (batch_size, seq_len, d_model)
  ])

有了這三個模塊,就可以組合成Encoder和Decoder了,這裡限於篇幅就不展開,有興趣的可以看下官方notebook

總結

Transformer這個模型設計還是很有特點的,雖然本質上還是全連接層的各個組合,但是通過不同的權重矩陣,對序列進行注意力機制建模。並且根據模型無法利用序列順序信息的缺陷,設計了一套位置編碼機制,賦予詞向量位置信息。近年來對Transformer的魔改也有很多,相信這個模型還有很大的潛力去挖掘。

相關資料參考Tensorflow官方notebook transformer.ipynb: ('https://github.com/tensorflow/docs/blob/master/site/en/tutorials/text/transformer.ipynb')illustrated-transformer: (http://jalammar.github.io/illustrated-transformer/) 該作者的圖示很明晰,相對容易理解✄---

看到這裡,說明你喜歡這篇文章,請點擊「在看」或順手「轉發」「點讚」。

歡迎微信搜索「panchuangxx」,添加小編磐小小仙微信,每日朋友圈更新一篇高質量推文(無廣告),為您提供更多精彩內容。

▼  ▼   掃描二維碼添加小編  ▼  ▼  

相關焦點

  • 熱門的模型跨界,Transformer、GPT做CV任務一文大盤點
    模型將其展平並在將其傳遞到 transformer 編碼器之前進行位置編碼補充。然後,transformer 解碼器將少量固定數量的學得位置嵌入作為輸入,稱為對象查詢,並另外參與編碼器的輸出。將解碼器的每個輸出嵌入傳遞到預測檢測(類和邊界框)或無對象類的共享前饋網絡(FFN)。
  • Transformer在CV領域有可能替代CNN嗎?
    網絡的深度有助於模型提取更抽象地高級特徵,網絡的寬度有利於模型提取更豐富的特徵表示。 這種連接主義 (connectionism)本質上是一種解決問題很好的思路,每一層都學習各自簡單的表示,但最後通過連接起來,卻形成了強大的(powerful)的特徵表徵能力!
  • Pipeline 和 Transformer
    因此,在建立機器學習模型時,學習如何有效地使用這些方法是至關重要的。在深入討論之前,我們先從兩個方面著手:Transformer:Transformer是指具有fit()和transform()方法的對象,用於清理、減少、擴展或生成特徵。簡單地說,transformers幫助你將數據轉換為機器學習模型所需的格式。
  • Facebook AI的DETR,一種基於Transformer的目標檢測方法
    目標檢測在計算機視覺中,目標檢測是一項任務,我們希望我們的模型將對象與背景區分開,並預測圖像中存在的對象的位置和類別。當前的深度學習方法試圖解決作為分類問題或回歸問題或綜合兩者的目標檢測任務。例如,在RCNN算法中,從輸入圖像中識別出幾個感興趣的區域。
  • Transformer生成論文摘要方法已出
    如果將這個數據按序列格式化為文檔的不同方面(引言、正文、摘要),那麼就可以讓模型學習生成其中的一個方面。比如,通過在測試時提供相似格式的數據,可讓模型學會解決摘要任務;即語言模型可以基於文檔的引言和之後更長的正文生成一個摘要。具體而言,論文的研究者使用了單個類 GPT 的 transformer 語言模型,並在文檔及其摘要上進行訓練。
  • Transformer在CV領域有可能替代CNN嗎?|卷積|神經網絡|算子|上下文...
    網絡的深度有助於模型提取更抽象地高級特徵,網絡的寬度有利於模型提取更豐富的特徵表示。  這種連接主義 (connectionism)本質上是一種解決問題很好的思路,每一層都學習各自簡單的表示,但最後通過連接起來,卻形成了強大的(powerful)的特徵表徵能力!
  • 深2.5至4倍,參數和計算量卻更少,DeLighT Transformer是怎麼做到的?
    模型壓縮:為了進一步提高序列模型的性能,該研究引入了逐塊縮放,允許每個塊有不同的尺寸,以及更高效地進行參數分配。改進序列模型:與 DeLighT 最接近的工作是 DeFINE 單元,它使用擴展 - 縮減策略學習模型表示。
  • NLP/CV模型跨界,視覺Transformer趕超CNN?
    該研究表明,對 CNN 的依賴不是必需的,當直接應用於圖像塊序列時,transformer 也能很好地執行圖像分類任務。該研究基於大量數據進行模型預訓練,並遷移至多個圖像識別基準數據集(ImageNet、CIFAR-100、VTAB 等),結果表明 Vision Transformer(ViT)模型可以獲得與當前最優卷積網絡相媲美的結果,而其訓練所需的計算資源大大減少。
  • 【TensorFlow2.0】Transformer聊天機器人教程
    通過TensorFlow 2.0,我們可以輕鬆構建複雜的模型。 在這篇文章中,我們將演示如何構建Transformer聊天機器人。;但是,對於更複雜和非順序的模型,需要Functional API和Model子類。
  • 谷歌研究院出品:高效 Transformer 模型最新綜述
    眾所周知,自注意機制存在平方階的時間與存儲複雜度,這在許多情況下都阻礙了模型的可擴展性。近期,為了解決該問題,出現了各種各樣的模型變體。在下文中,我們將這類模型稱為「高效 Transformer」。  在不同的語境下,我們可以對模型的效率有不同的理 解。「效率」可能指的是模型的內存佔用,在運行模型的加速器(如 GPU)的內存時,考慮內存佔用是十分重要的。
  • 人工智慧:使無監督學習適用於視覺語言模型將是一項重要概念突破
    可以解析語言和視覺輸入的AI模型也有非常實際的用途。例如,如果我們要構建機器人助手,則他們需要計算機視覺來在世界中進行導航,需要語言來與人類進行交流。但是,將兩種類型的AI結合起來說起來容易做起來難。這並非簡單地將現有語言模型與現有目標識別系統裝訂在一起。
  • GPT-3:一個令人失望的語言模型
    利益相關:我一直是 GPT-2 的熱心用戶,也寫過很多關於 GPT-2 和 transformer 模型的文章,包括 "human psycholinguists: a critical appraisal" 和 "the transformer … 「explained?」。我還用 GPT-2 作為核心組件做了一個 tumblr bot 。
  • 這六大方法如何讓Transformer輕鬆應對高難度長文本序列?
    在處理長度為 n 的序列時,其 O(n2) 的時間複雜度會使得原始的 Transformer 模型難以處理長文本序列。在過去的兩年裡,已經出現了多種有效的方法來應對多頭注意力機制的複雜度問題,本文將重點討論在模型規模方面很有發展前景的方法。
  • 如何輕鬆檢查你的機器學習模型是否公平?
    世界可能有偏見,因此數據和模型可能會體現這一點。我們提出了一種方法,機器學習工程師可以輕鬆檢查模型是否有偏見。現在我們的公平性工具僅適用於分類模型。案例分析為了表明dalex公平性模塊的功能,我們將使用著名的德國信貸數據集為每個信貸申請者賦予風險。這個簡單的任務可能需要使用可解釋的決策樹分類器。
  • 簡單機械原理模型解析
    寫在前面:最近在做老師培訓,fll選拔整理題目,收集整理了一些簡單機械的知識和原理模型,希望能幫助一些新加入樂高行業的老師們,家長們也可以看看用樂高可以學到些什麼
  • 1.6萬億參數的語言模型:谷歌大腦提出Switch Transformer,預訓練...
    論文連結:https://arxiv.org/pdf/2101.03961.pdf代碼連結:https://github.com/tensorflow/mesh/blob/master/mesh_tensorflow/transformer
  • 萬能 Transformer,你應該知道的一切
    這些模型都屬於 ELMo (Embeddings from Language Models)。但是這些模型仍然一般只作為特徵提取器提取出上下文相關的詞向量。除了這部分工作可以繼承外,下遊任務的其他參數仍需要從頭訓練。BiLSTM 包括前向 LSTM 模型和後向 LSTM 模型。兩個方向的 LSTM 共享部分權重。模型的目標是最大化前向和後向的似然概率和。
  • 手把手教你用Python搭一個Transformer
    上圖是谷歌提出的transformer 架構,其本質上是一個Encoder-Decoder的結構。把英文句子輸入模型,模型會輸出法文句子。模型會把這些向量當作參數進行學習,並隨著梯度下降的每次迭代而調整。給單詞賦予上下文語境:位置編程模型理解一個句子有兩個要素:一是單詞的含義,二是單詞在句中所處的位置。每個單詞的嵌入向量會學習單詞的含義,所以我們需要輸入一些信息,讓神經網絡知道單詞在句中所處的位置。
  • 「中考」初中數學相似模型合集解析16——45°模型講解
    今天講解的是關於「45度模型"的一些基本結論,希望對學生的思維有一定的激發作用,給學生處理問題多一些途徑。45°模型解析原理證明:如圖:ABCD為正方形,∠FCE=45°則△ACG∽△AHCAC=AG AH典型例題:1.如圖,正方形ABCD的邊長為4,點E
  • 華為諾亞方舟開源預訓練模型「哪吒」,4項任務均達到SOTA
    BERT之後,新的預訓練語言模型XLnet、RoBERTa、ERNIE不斷推出,這次,華為諾亞方舟實驗室開源了基於BERT的中文預訓練語言模型NEZHA(哪吒),寓意模型能像哪吒那樣三頭六臂、大力出奇蹟,可以處理很多不同的自然語言任務。