Transformerの理論とコンポーネント

13921 ワード

Transformer


Transformerは2017年にGoogleが発表した論文「Attention is allyou needs」のモデルで、既存のseq 2 seqの構造に従ったエンコーダ-デコーダであり、論文の名前のようにAttentionのみを実現している.
RNNシリーズのモデルは順序学習の構造であり,hidden stateを順番にスキップすることで並列処理ができず,文の長さが長くなるにつれて注意力計算量も増加する.
これらの問題を解決するために,RNNを用いずに,従来の順序演算から脱し,並列処理を実現し,優れた性能を有するコーデック構造に設計した.

Transformer Architecture


Transformerのアーキテクチャは次のとおりです.

左はエンコーダ、右はデコーダです.
同一のコーデック層を繰り返し積み重ねたコーデック構造.

Encoder




エンコーダは、自記および抽出転送から構成される.
エンコーダ内には複数のヘッダ注意とフィードフォワードがあり、add&normを使用します.

Attention


AttentionはQuery,Key,Valueの概念を用い,デコーダの各時点において,非表示状態とすべてのエンコーダとの類似度はscoreに基づいて計算される.
Transformerはself-attention概念を適用し,特定の特徴が同じコンテキストでどのような特徴を参照しているかを計算することで,入力文中の単語間の類似度を得る.
Scaled Dot-Product Attention

Scaled Dot-Product Attentionの構成を以下に示します.
以上の構成は以下のように整理されている.

Input vectorからQuery,Key,Value vectorを生成する.
Query・Key(matrix product)計算により,ある位置の単語と別の単語との関連度が得られる.
ScoreをKeyVector次元の平方根で除算します.
Softmax計算を行い、Value Vectorにsoftmax scoreを乗じ、最終的に注意力結果を生成します.
Multi-Head Attention

マルチヘッドAttentionの構成は以下の通りです.
以上の構成は以下のように整理されている.

マルチヘッドAttentionはh個の異なる初期化パラメータ行列を乗算し,h個の注意結果を得,それをつなぎ合わせて結果を得た.
多点関心実施
class MultiHeadAttention(nn.Module):
    def __init__(self, hid_dim, n_heads):
        super().__init__()
        
        assert hid_dim % n_heads == 0
        
        self.hid_dim = hid_dim 
        self.n_heads = n_heads 
        self.head_dim = hid_dim // n_heads 
        
        self.query = nn.Linear(hid_dim, hid_dim)
        self.key = nn.Linear(hid_dim, hid_dim)
        self.value = nn.Linear(hid_dim, hid_dim)

        self.dropout = nn.Dropout(0.1)
        
        
    def forward(self, hidden_states, attention_mask=None):
      
        print('Hidden States: ', hidden_states.shape) # ADDED

        Q = self.query(hidden_states) #Q : [2,9,768]
        K = self.key(hidden_states) #K : [2,9,768]
        V = self.value(hidden_states) #V : [2,9,768]
       
        batch_size = hidden_states.shape[0] 
               
        Q = Q.view(batch_size, -1, self.n_heads, self.head_dim).permute(0,2,1,3) #Q : [2,12,9,64]
        K = K.view(batch_size, -1, self.n_heads, self.head_dim).permute(0,2,1,3) #K : [2,12,9,64]
        V = V.view(batch_size, -1, self.n_heads, self.head_dim).permute(0,2,1,3) #V : [2,12,9,64]
       
        d_k = self.head_dim # d_k : 64
        #print('transpose k', K.transpose(-2,-1).size()) #transpose k: [2,12,64,9]
        attention_score = torch.matmul(Q, K.transpose(-1,-2)) # Q x K^T
        attention_score = attention_score / math.sqrt(d_k) #[2,12,9,9]
        
        if attention_mask is not None:
          attention_score = attention_score + attention_mask
        
        attention = nn.functional.softmax(attention_score, dim=-1) #softmax attention score: [2,12,9,9]
        
        attention = self.dropout(attention)
        
        output = torch.matmul(attention,V) #score*v: [2,12,9,64]
        
        output = output.permute(0, 2, 1, 3) #permute output: [2,9,12,64]
        
        output = output.reshape(2,9,768) #reshape output: [2,9,768]
        
        return output
        
Input vectorからQuery,Key,Value vectorを生成する.[29768]次元のQ,K,Vを[2,12,9,64]に変換するためにview(batch size,−1,self.n heads,self.head dim)で次元を追加しpermite(0,2,1,3)に変換する.
計算はQuery・Key(matrix product)で行い,ScoreをKeyベクトル次元の平方根に分ける.attention_score: [2,12,9,9]
ソフトmax計算を行い、ソフトmaxスコアに値ベクトルを乗算します.softmax注意score:[2,12,9,9]score*V:[2,12,9,64][2,9,12,64]permite(0,2,1,3)を行い、それを[29768]にするために整形する.

Decoder




デコーダは、自己注意、コーデック注意、フィードフォワードから構成される.構成.
デコーダ内にはFeed Forward,マルチヘッド注意,マルチヘッド注意をマスクしadd&normを使用する.
実装コードgithub
https://github.com/KimHyeYeon41/AISoftware/blob/main/%5BAI_05%5DMulti_Head_Attention.ipynb
EncoderおよびDecoderの実装は、以下の文書で継続します.
https://velog.io/@gpdus41/Transformer-EncoderDecoder-%EA%B5%AC%ED%98%84
reference
https://arxiv.org/pdf/1706.03762.pdf
http://jalammar.github.io/illustrated-transformer/