🙄

Encoder-Decoder/Attention/Transformerの調査

2023/04/13に公開

この記事は先日自分がGPTの背景にあるEncoder-DecoderやらTransformerやらについて雑に調べていたこのメモを元に不足する情報を補完してもらいながらChatGPT(GPT-4)に記事としてまとめてもらったものです。

雑なメモのままで埋もれさせておくよりもある程度体裁の整った文章として残しておいた方が後から見返した際に自分にとっても役に立つだろうという思惑と、単純にChatGPTでどれくらい記事が書けるのか?という実験をする目的で書いています。実験的な意味合いが強いので内容の正確性に問題がある部分もあるかもしれないのでその辺はご容赦ください。また、ChatGPTで中身のない薄っぺらな技術記事を量産しようなどという意図はないのであらかじめご了承ください。

自然言語処理の変遷とEncoder-Decoderモデルの登場

自然言語処理(NLP)は、コンピュータが人間の言語を理解し、生成する技術を研究する分野です。その歴史は、機械翻訳や文法チェックなどのタスクを解決するための様々なアプローチが試みられてきたもので、次のような変遷を辿っています。

ルールベースの手法

NLPの初期の段階では、人間が設定した規則や文法に基づいて言語を処理するルールベースの手法が主流でした。しかし、言語の多様性や曖昧性に対応するためには膨大なルールが必要であり、スケーラビリティに限界がありました。

統計的手法

時代が進むと、コーパス(大量のテキストデータ)を利用した統計的手法が登場しました。これにより、ルールベースの手法の限界を克服し、データから自動的に言語のパターンを学習することが可能になりました。しかし、統計的手法は、長い依存関係や複雑な言語構造を捉えるのに苦労していました。

ニューラルネットワーク

2010年代に入ると、ディープラーニング技術がNLPにも適用されるようになりました。特に、RNN(Recurrent Neural Network)が自然言語処理タスクにおいて高い性能を示すことが明らかになりました。RNNは、シーケンスデータを扱うのに適した構造を持っており、文脈を考慮した言語モデルの構築が可能です。

Encoder-Decoderモデル(Seq2Seq)の登場

2014年に、Sutskeverらによって提案されたEncoder-Decoderモデルは、自然言語処理の分野に大きな変化をもたらしました。このモデルは、入力文を文脈ベクトルにエンコードし、その文脈ベクトルを利用して出力文をデコードする構造を持っています。このモデルは、翻訳や要約、対話システムなどの様々な自然言語処理タスクに適用され、従来の手法を大幅に上回る性能を示しました。特に、長期的な依存関係や文脈を考慮した処理が可能になり、自然言語処理の精度が大きく向上しました。

https://arxiv.org/abs/1409.3215

Attentionメカニズム

2015年に、Bahdanauらによって提案されたAttentionメカニズムは、Encoder-Decoderモデルの性能をさらに向上させました。Attentionメカニズムを利用することで、Decoderは固定長の文脈ベクトルcだけでなく、入力文全体の隠れ状態ベクトルにアクセスできるようになり、必要な情報を動的に取得することができます。これにより、長い入力文や複雑な構造の文に対する処理能力が向上しました。

https://arxiv.org/abs/1409.0473

Transformerモデル

2017年に、Vaswaniらによって提案されたTransformerモデルは、自己注意機構と呼ばれる新たなAttentionメカニズムを導入し、RNNやCNNを一切使用しない全く新しいアーキテクチャを採用しました。これにより、並列処理が容易になり、計算効率が大幅に向上しました。Transformerモデルは、現在の自然言語処理の主要な手法であり、BERTやGPTなどの大規模な事前学習モデルの基盤となっています。

https://arxiv.org/abs/1706.03762

Encoder-Decoderモデルの登場により、自然言語処理の分野は劇的に変化しました。このモデルは、翻訳や要約、対話システムなどの様々なタスクにおいて高い性能を発揮し、自然言語処理の精度や効率が大幅に向上しました。以降、AttentionメカニズムやTransformerモデルなどの進化した技術が登場し、自然言語処理の分野はますます発展しています。

Encoder-Decoderモデル

Encoder-Decoderモデルは、大まかに言うと、入力データを符号化(エンコード)し、その符号化された情報をもとに、目的のデータを生成(デコード)するという2つの部分からなる機構です。ここでは、入力データとして自然言語の文章が与えられることを想定しています。

Encoder(符号化器)

Encoderは、入力された文章を固定長のベクトル(文脈ベクトルc)に変換する役割を果たします。この変換の際、長期的な依存関係を捉えることができるGRU(Gated Recurrent Unit)と呼ばれるRNN(リカレントニューラルネットワーク)の一種が使われることが多いです。GRUは、入力された各単語を効率的に処理し、前の入力までの状態(ht-1)から次の状態(t)を求める際に、適切な情報の選択と更新を行うことができます。

文脈ベクトル

文脈ベクトルは、Encoderが入力文を処理した結果を表す固定長のベクトルです。これは、入力文の意味や構造を網羅するように設計されており、Decoderが適切な出力を生成するために必要な情報が含まれています。

GRUを使ったEncoderの場合、入力文の各単語を順番に処理し、それぞれの単語に対応する隠れ状態ベクトルが生成されます。最後の単語が処理された後、最後の隠れ状態ベクトルが文脈ベクトルとして扱われます。これにより、入力文全体の情報が文脈ベクトルに圧縮されて表現されます。

ただし、文脈ベクトルの長さが固定されているため、長い入力文や複雑な構造の文に対しては、情報の損失が生じる可能性があります。

Decoder(復号化器)

Decoderは、Encoderが生成した文脈ベクトルcを元に、推論したい結果(出力)を生成する役割を果たします。具体的には、文脈ベクトルcと、現在の入力を組み合わせて、次に来るべき単語の確率分布を生成します。この確率分布に基づいて、最適な単語を選択し(例:BeamSearchアルゴリズム等)、結果として得られる文章を生成していきます。この過程を、文章の終わりを意味する「EOS」(End of Sentence)が生成されるまで繰り返します。

具体例

Encoder-Decoderモデルを用いた英日翻訳タスクを例に説明します。以下の英文を日本語に翻訳すると仮定しましょう。

Input: "I love programming."

  1. まず、英文を単語に分割し、Encoderに入力します。
  2. Encoderは、入力された単語を順番に処理し、最終的に固定長の文脈ベクトルcを生成します。
  3. Decoderは、文脈ベクトルcと開始トークン(例: <s>)を受け取り、最初の日本語の単語の確率分布を生成します。
  4. 確率分布から最適な単語(例: "私")を選択し、出力文に追加します。
  5. Decoderは、文脈ベクトルcと現在の出力文(例: "私")を入力として受け取り、次の単語の確率分布を生成します。
  6. 確率分布から最適な単語(例: "は")を選択し、出力文に追加します。
  7. このプロセスを繰り返し行い、終了トークン(例: </s>)が選択されるまで続けます。

最終的に、以下のような日本語の翻訳文が得られるでしょう。

Output: "私はプログラミングが大好きです。"

課題とその対処法

Encoder-Decoderモデルは非常に有用ですが、いくつかの課題が存在します。特に、Encoderが生成する文脈ベクトルcの長さが固定されていることが挙げられます。これにより、学習によって理解できる情報量や複雑度に限界があり、未知の語句や長い文章の推論に弱いという問題が生じます。

この課題への対処法の一つとして、Attentionメカニズムがあります。Attentionメカニズムは、Decoderが出力を生成する際に、Encoderの各時刻の隠れ状態を動的に参照し、必要な情報に重みを付けて利用する仕組みです。これにより、文脈ベクトルcだけでなく、入力文全体の情報を利用して、より精度の高い推論が可能になります。

Attentionメカニズム

Attentionは、EncoderとDecoderを組み合わせたSeq2Seqモデルにおいて、特に効果を発揮します。Encoderは入力文を符号化し、Decoderはそれをデコードして出力文を生成します。従来のseq2seqモデルでは、Encoderは入力文全体を1つのベクトルに圧縮する必要がありましたが、Attentionを用いることで、各単語やフレーズの重要度を考慮しながら、情報の損失を抑えることができます。

Attentionの仕組みは以下の通りです。

  1. AttentionがDecoderの状態 ht と全Encoderの状態 s1, s2, ..., sm を受け取ります。
  2. Attentionは、各Encoderの状態 sk に対して、Decoderの状態 ht との関連性(relevance)を計算します。これをAttentionスコアと呼びます。Attention関数は、1つのDecoder状態と1つのEncoder状態を受け取り、スカラー値のスコア score(ht, sk) を返します。
  3. Attentionは、Attentionスコアに対してsoftmax関数を適用し、確率分布を得ます。これをAttentionウェイトと呼びます。
  4. 最後に、AttentionはEncoder状態とAttentionウェイトの加重和を計算し、Attentionの出力を得ます。

具体例

例として、英語から日本語への翻訳タスクを考えます。入力文が "I have a dog"(私は犬を飼っている)であり、これを日本語に翻訳することを目指します。

  1. Encoderは、入力文の各単語(I, have, a, dog)に対応する状態ベクトルを生成します。
  2. Decoderは、翻訳文を生成するために各ステップで、Attentionメカニズムを使用して、入力文のどの単語が最も関連性が高いかを判断します。
  3. 例えば、Decoderが最初の単語を生成する際、AttentionはEncoderの各状態とDecoderの現在の状態を比較して、関連性のスコアを計算します。この場合、「I」、「have」、「a」、「dog」それぞれの単語がDecoderの最初の単語生成にどれだけ関連しているかを判断します。
  4. 次に、softmax関数を適用して、Attentionウェイトを計算します。これにより、各Encoder状態の重要度が正規化されます。例えば、「I」が0.1、「have」が0.2、「a」が0.1、「dog」が0.6というAttentionウェイトが得られたとします。
  5. Attentionの出力は、Encoder状態とAttentionウェイトの加重和として計算されます。この出力はDecoderに送られ、Decoderはこれをもとに最初の単語を生成します。この例では、「私」が生成されるでしょう。
  6. Decoderは次の単語を生成する際も同様のプロセスを繰り返し、最終的に翻訳文「私は犬を飼っている」を生成します。

このように、Attentionメカニズムは、入力文の各単語の重要度を考慮しながら、出力文を生成することができます。その結果、従来のseq2seqモデルに比べて、より高い翻訳品質が実現されることが期待されます。

Transformerモデル


https://arxiv.org/abs/1706.03762

Transformerの背景

Transformerは、2017年にVaswaniらによって提案されたモデルで、自然言語処理のタスクを効率的に解決するために開発されました。それまでの主流だったリカレントニューラルネットワーク(RNN)や、畳み込みニューラルネットワーク(CNN)とは異なるアーキテクチャを持っており、大規模なデータセットを扱う際に優れた性能を発揮します。

Transformerの構成要素

Transformerは、大きく分けて以下の2つの部分で構成されています。

  • Encoder:入力された文をベクトル表現に変換する役割を持ちます。
  • Decoder:Encoderから受け取ったベクトル表現を元に、出力文を生成する役割を持ちます。

位置エンコーディング(Positional Encoding)

Transformerは、文中の単語の順序を考慮するために、位置エンコーディングを導入しています。これは、各単語ベクトルに位置情報を加えることで、モデルが単語の並びに関する情報を捉えられるようにする役割を果たします。位置エンコーディングは、以下のような手順で計算されます。

  1. 各単語の位置に対して、一定の周期関数(例えば、正弦関数と余弦関数)を用いて位置情報を生成します。
  2. 生成された位置情報を、対応する単語ベクトルに加算します。

このようにして得られた位置エンコーディング付きの単語ベクトルは、自己注意メカニズムに入力されます。

自己注意(Self-Attention)

{Attention}(Q,K,V) = {softmax}(QK^T/\sqrt{d_k})V

Transformerの核となるのは「自己注意」メカニズムです。これにより、文中の各単語が他の単語との関係性を捉えられるようになります。自己注意の計算手順は以下の通りです。

  1. 入力文を単語ごとのベクトルに変換します。
  2. 各単語ベクトルを3つのベクトル(クエリ、キー、バリュー。クエリ、キー、バリューは同じ。)に変換します。
  3. クエリとキーの類似度を計算し、正規化します(これをAttentionスコアと呼びます)。
  4. Attentionスコアに基づいて、バリューの重み付け和を計算し、新しいベクトルを生成します。

Multi-Head Attentionの仕組み

{MultiHead}(Q, K, V) = {Concat}({head}_1, \dots, {head}_n)W_o,
{head}_i={Attention}(QW_Q^i, KW_K^i, VW_V^i)

Multi-Head Attentionは、以下の手順で計算されます。

  1. 入力された単語ベクトルを、指定された数(ヘッド数)の異なるベクトル(クエリ、キー、バリュー)に変換します。
  2. 各ヘッドについて、自己注意メカニズムを適用し、新しいベクトルを生成します。これにより、各ヘッドが異なる表現空間からのアテンションを学習できます。
  3. 生成されたすべてのヘッドのベクトルを連結し、元のベクトルの次元に合わせるために線形変換を行います。

このようにして、Multi-Head Attentionは、複数の視点からの単語間の関係性を同時に捉えることができます。例えば、あるヘッドは文法的な関係性に重きを置く一方、別のヘッドは意味的な関係性に焦点を当てることができます。これにより、モデル全体の表現能力が向上し、より高い性能を発揮することが可能になります。

EncoderとDecoderの積み重ね

TransformerのEncoderとDecoderは、それぞれ複数の層で構成されています。各層は同じ構造を持ち、情報をより精緻に表現できるようになるほど深い層になります。Encoderでは、自己注意と位置エンコーディングを経た単語ベクトルが、次々と積み重ねられたEncoder層に入力されます。Decoderも同様に、複数のDecoder層を経て、最終的な出力文が生成されます。

マスク付き自己注意(Masked Self-Attention)

Decoderでは、未来の情報にアクセスできないようにするために、マスク付き自己注意が用いられます。具体的には、出力文の生成時に、まだ生成されていない単語に対応するAttentionスコアをマスク(無効化)します。これにより、モデルが適切な順序で出力文を生成することが可能になります(カンニング防止)。

まとめ

Encoder-Decoder/Attention/Transformerの基本情報について自分で調べたことを中心にChatGPTを使って記事を書く実験をした。

利用したプロンプトとしては主に下記の3つ。

1つは記事生成用のプロンプト、

あなたは AIの専門家です。
自然言語処理における<XXXXXXX>について詳しく解説する記事をあなたの知識や下記のメモを元に具体例を交えながら書いてください。誤っている箇所を修正したり不足する情報があれば補完してください。数式が必要な場合はTex形式を使わずに書いてください。
この記事を読む読者はAIやニューラルネットワークについてあまり詳しくないがコンピューターサイエンスの技術的な素養は身につけているプログラマーを想定しています。

## メモ
...

もう1つはmermaidのチャートを生成するためのプロンプト、

上記の記事の<XXXX>で行われている<YYYY>の処理を表現するフローチャートをmermaid.jsの記法を用いて作成してください。

あとは途中で生成した文章が途切れたときに続けてもらうプロンプト。

続きを出力してください

生成される記事の精度としてはメモを強く参照しすぎてしまうことがあり微妙だったので何度かやり直したりした。Transformerのようなすでに大量に良解説が存在する事柄についての文章は下手に自前のメモの情報を与えるよりChatGPT自身の知識を使ってもらった方が正確な記述になりやすかった。

記事生成の効率としてどうか?というと内容の正確性の検証のために下記リンクに載せているような他の論文や記事や動画をいくつも参照しないといけなかったりするので結構時間がかかる(というか結局その過程が勉強になる)。

本や論文、会議の議事録作成みたいな要約タスクであれば今すぐにでも実用的なんだろうけど、解説のための文章を生成するタスクでは微妙かも。特に解説系タスクだと良い感じの図を差し込みたかったりするが、その図は簡単には作れない(グラフはmermaidである程度作れるが)。生成した文章から文脈を読み取って理解を捗らせる図をサクッと生成してほしい。

とはいえ調べた内容を雑なメモ書きで残すよりある程度綺麗な文章として残しておくほうが後で参照しやすくなるだろうしそういう意味ではやる価値はあるかなと思う。

あとはChatGPTが生成した文章中で使われていた未知の技術用語なんかをさらに深掘りしてChatGPTに聞くことで理解がより深まっていくという効果はあって、この効果が個人的には一番有益だなと感じた。学びたい概念についての資料を読む->ChatGPTに聞く->資料を読む->ChatGPTに聞くを繰り返して不明な概念を潰していく営みを無限にできるのは楽しい。

ただ、ChatGPTで記事を作ること自体は文章を書くのが楽になるとはいえ、まぁまぁ面倒だしそんなに楽しいもんでもないから今後も頻繁にやるかはわからないな〜と思った。

リンク

Discussion