はじめに
すでに多くの人がTransformerの解説記事を書いているが、執筆者のバックグラウンドによって説明の重点の置き方は様々である。よって、解説記事はいくらあっても困ることはないはずである。このたび、業務上の必要に迫られてTransformerを本格的に勉強したので、自分の言葉でまとめてみる。
・・と思ったのが、息切れして本記事はTransformerを理解するための下準備で終わった。それでもよければお読みください。
私のバックグラウンド
- TransformerやAttentionという断片的な情報は聞いたことがあり理解した気になっていたが、細かい点は知らなかった。
全体像
新しいモデルを理解するには、入出力、すなわち何を入れて何が出てくるモデルなのかを把握することが理解の第一歩である。
- TransformerはSeq2Seqモデルである。つまり、系列を入れたら何か別の系列を出すモデルである。
具体例
系列は数値の系列だったら何でも良い。例えば・・
- 数値が表すものが文字であれば、Transformerは文字列を別の文字列に変換することになり、それはすなわち翻訳である。
- 入力系列は文字列で、出力系列が音声信号であってもよい。そのようなモデルは読み上げモデルと言えよう。
このように系列→系列というタスクは様々な応用に使うことができるので、Transformerをマスターしておけば、データサイエンティストとしての活躍の場も増えることだろう。
Transformer以前
系列→系列というタスクはその重要性から、Transformer以前から研究がされてきた。典型的な構造がRNNを用いたEncoder-Decoderモデルである。
RNNによるSeq2Seq
I have a penという英文を日本語に翻訳するタスクを描いてみた。図の上側がEncoder、下側がDecoderである。
RNNをたくさん並べて描いているが、たくさんの別々のRNNを使うという意味ではなく、一つのRNNに繰り返し入力するよという意味である。ただ、Encoder内のRNN(水色)とDecoder内のRNN(緑色)は別物である。
Encoderの役割
RNNというものは、何か入力を入れると出力を出すとともに内部状態が変わるコンポーネントであることはご存知だろう。しかし今回出力は特に使わない。移り変わる内部状態に着目する。
I, have, a, penという4単語を順番に入力したあとの内部状態は、"I have a pen"という文章に関する情報を表しているとみなすことができる。
ちなみに、わかりやすくIとかhaveとか描いてあるが、実際は何らかのルールのもと数値表現に直しておかないといけない。愚直には、存在する単語に一意の数字を割り振る。I=1, have=2, ...のように。もしくは、I=[0, 1, 0, 0], have=[0, 0, 1, 0], ...のようなone-hot形式のベクトル表現でもいい。さらには、word2vecのような高度な変換でもよいし、Embeddingレイヤーを使って表現の変換自体もネットワークの一部として学習してもいい。
Decoderの役割
図中のオレンジ色がEncoder RNNの最終内部状態を表しており、これをDecoderに渡すことで、Decoderはそれに相当する日本語を出力するタスクを担う。
Decoder内も中身はRNNである。ただ、Encoder側のRNNと違って出力と内部状態の両方を活用する。
DecoderのRNNには最初、前記Encoder RNNの最終状態がセットされる。その状態で、まずSOS (start-of-sentence)という特殊な単語をRNNに入力する。そうするとRNNは、まず第一声を発そうと「私」という単語を出力する。続いて今度はその「私」をRNNへの入力として与えると、「私」の次の単語を出そうとなって「は」を発す。このようにして「持っている」まで発すると、次はもう発するものがないのでEOS (end-of-sentence)を出して終わる。
RNNによるSeq2Seq + Attention
さて、上記のモデルの弱点は、Encoder RNNの最終状態という小さな器に文章に関するすべての情報を詰め込もうとしている点である。I have a penのような短い文章であれば、十分表せるかもしれないが、もっと長い文では、文章の意味を表すだけの十分な表現力がないだろう。そこで、"I"を読んだあとの内部状態、"have"を読んだあとの内部状態, ..というように内部状態の履歴を全部Decoderに渡すことになった。下図でオレンジ色のベクトルが4つに増えているのはこれを表す。
こうしてDecoderに十分な情報が渡せるようになったが、Decoder側でどう使うかという問題が発生した。それをエレガントに解決したのがAttentionである。近年ディープラーニング界隈でよく聞くAttentionは、別にTransformerでなくても実現できる仕組みであることを強調しておきたい。
Attentionを一言でいえば、次の文字を出すときに注目するのは前記4ベクトルのなかのどれか?である。例えば「私」という文字の次に何を出そうか考えるときと、「は」の次に何を出そうか考えるときでは、前記4ベクトルへの注目具合が異なるはずである。注目という計算イメージ湧かなければ、4ベクトルそれぞれへの重みと思えば良い。計算の流れとしては、「私」から、4ベクトルへの注目(=重み)を計算する。その重みを実際に4ベクトルへ掛け合わせる。それをRNNへの入力とする。注目の仕組みが入った以外は前述の基本的なSeq2Seqと同じである。
Transformer
このように進化したSeq2Seqモデルであるが、RNNの学習が非効率であることが課題感としてあった。そこでRNNフリーな構造を実現するものとして登場したのがTransformerである。
まとめ
長くなったので続きはまた今度とする。