Transformerを勉強する

はじめに

私は「ゼロから作るDeep Learning ❷ ―自然言語処理編 斎藤 康毅」を読んだのですが、Transformerについてもっと知りたかったので、論文を読んでみることにしました。論文を読むにあたって、[1]、[2]、[3]、[4]、[5]、[8]を参考にさせて頂きました。間違っているところがあれば、教えていただけると幸いです。

arxiv.org

Attention Is All You Need

以下に出てくる図表は論文からの転載です。

Abstract

  • 現在、encoderとdecoderを含むRNN、CNNに基づいたモデルが有力とされている
  • 本論文ではRNN、CNNを使用せず、Attentionに基づいたTransformerを提案

Introduction

  • t番目の状態tを求めるために、RNNはt-1番目の状態ht-1とt番目の単語を使うため並列化が難しい
  • TranformerはRNNを使用せず、Attentionに基づいているので、大幅に並列化ができる
  • 入力と出力の間のグローバルな依存関係の構築はAttentionに頼る

Background

  • 逐次計算を減らすという目標はCNNを使ったモデルで達成されてきた
  • しかし、CNNを使ったモデルでは位置間の距離が増加する毎に必要な操作の数が増える。これによって、遠い距離の依存関係を学習するのが難しかった。Transformerではこれを一定数の操作に削減する。
  • Transformerは入力と出力の表現をself-attentionに頼る最初のtransductionモデル

Model Architecture

f:id:maguroHate:20191111212251p:plain

  • encoder、decoder共にN = 6。灰色のブロックをそれぞれ6個スタック
  • 各層のアウトプットはdmodel = 512次元(単語の次元)
  • リークを防ぐためにdecoderの最初のsub-layerでは2種類のMaskをかける
  • Maskには2つある。

MASK

ここでMaskについて見る。Maskは特定のkeyに対して、attention_weightを0にするためにある。attention_weightを0にするのはAttentionがかかるのがおかしい部分にAttentionがかからないようにするためである。2つあるMaskはそれぞれ以下の通りである。

  1. PADを無視する(ある文章が最大長より短い場合、PADで埋め合わせられる)
  2. decoderでのリークを防ぐ

encoderでは1のみを使用する。decoderでは1と2を使用する。

[5]がとてもわかりやすかったです。

 

Layer normalization

各sub-layerの後に配置。residual connection(図でのaddに対応していると思われる)とlayer normalizatonを行う。まとめると以下のようになる。

LayerNorm(x + Sublayer(x))

以下では、sub-layerを一つずつ見ていく。

Attention

f:id:maguroHate:20191111214448p:plain

左側

  • 左側のモデルは「ゼロから作るDeep Learning ❷ ―自然言語処理編 斎藤 康毅」に出てくるAttentionとほとんど同じ(内積注意)。
  • 内積を使って2つのベクトルの類似度を測っている。
  • \sqrt{d_{k}}で除算するところが異なる
  • dkが大きい時、softmaxでの勾配がとても小さくなる。対策として、\sqrt{d_{k}}で除算する

数式で表すと以下のようになる

f:id:maguroHate:20191111225239p:plain

右側

  • h = 8
  • 単一の内積注意を計算するよりも、異なる重み行列で線形写像をh回計算し、h個の内積注意を計算する方が有益だとわかった。
  • dk = dv = dmodel / h = 64
  • そして、連結してまた線形写像する

 

Position-wise-Feed-Forward-Networks

Attention層からの出力を受け取る2層の全結合ニューラルネットワーク。活性化関数はReLU。

 f:id:maguroHate:20191118182935p:plain

 

Positional Encoding

  •  TransformerはRNNやCNNを利用していないため、Positional Encodingにて単語の相対的位置または絶対的位置に関する情報を加える
  • 下にあるembeddingsの出力と同じ次元を持つため、加算できる
  • embeddingsの出力と加算する際、embeddingsの出力の方が小さいので、embeddingsの出力に\sqrt{d_{model}}を掛ける

  • posはその単語が何番目か
  • iは単語の分散ベクトルの何次元目か

f:id:maguroHate:20191119214720p:plain

 

Why Self-Attention

f:id:maguroHate:20191119171843p:plain

  • Layer毎の計算複雑度
  • どれぐらい並列化できるか(必要な順次操作の回数で測定)
  • 最大パスの長さ(短いほど長距離依存について学びやすい)

 

  • Self-Attentionと他のネットワークを比較
  • Self-Attention(restricted)は出力位置を中心として、サイズrの近傍に位置する入力単語のみ考慮する
  • 大抵の場合n < d なので、Self-AttentionはRecurrentより高速

 

Training

  • データはWMT 2014 English-GermanとWMT 2014 English-French
  •  評価軸はBLEUスコアとTraining Cost
  • Adam optimizerを使用
  • 3種類の正規化を使用

f:id:maguroHate:20191119175133p:plain


 

参考

実装

実装は[6]、[7]、[8]が参考になります(PyTorch)。

[6]の実装は以下のようになっています。

各sub-layerをクラスで実装

⬇︎

EncoderLayer、DecoderLayerにまとめる。

⬇︎

Mask + Embedding + Positional Encoding + Encoder or Decoder LayerをN(=6)回生成したものをEncoder、Decoderクラスにまとめる

⬇︎

Encoder、Decoder、LinearをTransformerクラスにまとめる。

torch.nn.CrossEntropyLossの中にsoftmaxの計算があるので、softmaxは書かれていないことに注意。

 

[7]はPyTorchの公式チュートリアル

 

[8]ではレビュー文章のネガポジ分類にTransformerのEncoderを使用している。

  • TransformerのEncoderをクラス分類に使用するにはどうすればいいのかがわかる。
  • モデルがネガポジ分類をする際にどのような単語を着目したのかをある程度把握するために、Self-Attentionを可視化させている。

 

次に読む論文

BERT

arxiv.org

TransformerのEncoderを使用するらしい。

 

A Structured Self-attentive Sentence Embedding

arxiv.org

Self-Attentionの起源

 

参考文献

  1. http://deeplearning.hatenablog.com/entry/transformer
  2. https://www.slideshare.net/DeepLearningJP2016/dlattention-is-all-you-need
  3. https://qiita.com/nishiba/items/1c99bc7ddcb2d62667c6
  4. https://qiita.com/FuwaraMiyasaki/items/239f3528053889847825
  5. https://qiita.com/halhorn/items/c91497522be27bde17ce
  6. https://github.com/graykode/nlp-tutorial/tree/master/5-1.Transformer
  7. https://pytorch.org/tutorials/beginner/transformer_tutorial.html
  8. https://github.com/YutaroOgawa/pytorch_advanced