自然言語処理でBERTまでの流れを簡単に紹介

はじめまして@vimmodeです。普段はMNTSQというリーガルテックの会社で自然言語処理をしています。今回はBERTとBERTまでの流れを簡単に紹介します。

 

自然言語処理で今やデファクトスタンダードとなりつつであるBERT。登場当時はモデルの複雑さに伴う計算環境や計算リソースの確保が難しく気軽に動かせなかったが、ColabやKaggleカーネル環境が整備されたきたおかげで誰でも気軽に使えるようになりました。

また、haggingface社が公開したBERTと関連モデルのラッパーライブラリであるtransformersによりわずか10行程度でBERTモデルを記述できます。

一方、自然言語処理を始めて間もない段階でいきなりBERTを突きつけられても理解の壁が高いと思いますので、今回は数式やコードを使わずにBERTに至るまでの流れを簡単に紹介したいと思います。

※これらはあくまで私の理解であり、自然言語処理の歴史を網羅的に解説しているわけでは無いことをご留意ください。また各手法の説明は概要に留めますので雰囲気を感じ取っていただければ幸いです。

 

コンピュータで自然言語処理

人間は「りんご」という単語を思い浮かべる際に、色や形といった視覚情報や果物や植物であるという構造情報などをまとめて連想していると思います。それらの情報を参照しつつ、文中の単語から必要な情報を取り出し、文脈を理解していると考えられそうです。しかし、人間が文や単語をどのようなデータとして保持し処理するかはまだ研究段階であるため、コンピュータで同様な処理をするために単語や文脈をどのように数値化するか、ということが大きな研究テーマとなっています。今回紹介するBERTはニューラルネットを用いて単語や文を数値化する技術の一つです。

 

ニューラルネット以前の代表的手法

単語や文を数値化する代表的な手法に以下があります

  • 単語の数値化
    • 各単語にユニークIDを付与するID化
    • 単語間の区別だけを目的としたOne-Hot-Encoder
  • 文(文書)の数値化
    • 文書内における各単語の希少性を反映するTF-IDF
    • 前後N個の単語をグループとし、そのグループの出現をカウントするN-gram
    • 文書の構成要素(トピック)を累積して文書の表現を構築するLDA

これらは自然言語処理の長い歴史で洗練されてきたアルゴリズムであり、検索やデータマイニングなど実用的なアプリケーションでも多く使われています。
しかし、計算方法を考えてみれば、これらのアルゴリズムによる単語や文の表現が、意味を記述したものとなっていると考えるのは難しいでしょう。そもそも意味を記述するとはどういうことがあいまいであることも大きな問題でした。

 

単語の意味表現

単語の意味記述に対するアプローチでブレークスルーとなったのはword2vecと呼ばれる技術です。分散表現のアプローチを用いて1つの単語を複数の数値(ベクトル)で表現します。これは現在のニューラル自然言語処理でも根本的な考え方です。

※以降数値化をベクトル化と記載します

 

単語 -> [0.2, -0.1, 0.3, ...]

 

ある色をRGBの3値(3次元)で表現するように、ある単語を任意の数(100~200)の値で表現する考え方です。RGBの3値がそれぞれ三原色を示すのとは異なり、単語の各次元がそれぞれ何を示すかは明示的に指定せず、大量の文書からword2vecが学習していきます。また最終的に獲得したベクトルの各次元の解釈は人間の感覚では理解できません。

word2vecで獲得された表現の解釈は難しいものの、その性質に面白いものがあります。有名なのは単語ベクトルの演算です。

王様 - 男 + 女 = 女王

のように、「王様、男、女」の各単語をword2vecでベクトルに変換し、それらを演算した結果が「女王」のベクトルに最も近いという結果は人間からしても直感的であることから、それらのベクトルは単語の意味を表しているといわれるようになりました。意味の表現とはなにか、という問題に、一つの回答を示したのです。

 

文のベクトル化

単語をベクトル化できたので、そこから文のベクトルを作ることを考えます。

例えば一つの文のすべての単語ベクトルの各次元の平均値や最大値、最小値から文のベクトルを作るアプローチが考えられますが、各種タスクの精度は既存手法と比べさほど芳しくありません。理由はいろいろ考えられますが、単語の出現位置を考慮しないため文脈を捉える事ができないことが主な要因の一つです。

 

文脈を考慮するリカレントニューラルネットワーク(RNN)

人間が文を処理する際に1単語ずつ読み進めながら文を把握していくようにモデルにも単語を1語ずつ入力し、文脈に関する情報を更新していくモデルをリカレントニューラルネットワーク(以降RNN)と呼びます。

図で表すと

f:id:nmoriyama:20200116161832p:plain

 

図の下部は新しく入力されるベクトルであり、その一段上は状態を示すベクトルです。このRNNと呼ばれるモデルでは逐次的に入力されるベクトルを使って状態を更新していきます。

自然言語処理ではこの状態ベクトルを文脈と解釈することができます。逐次的に入力されてくる単語ベクトルを使って文脈情報を更新していき、最後の単語により更新された状態を文全体のベクトルとして利用します。(翻訳や分類などのタスクへの入力として利用できます)

ところがRNNは長文を苦手とする性質を持ちます。学習時に長文を処理する際に勾配消失や勾配爆発といった課題があり、これに対してはモデルを工夫することで一定対応できるようになってきました(LSTMやGRUなど)。

別の視点で課題なのが状態ベクトルの表現力です。上記のように新しい単語を使って文脈を保持しますが、この場合過去入力された単語の影響度は低く、新しく入力される単語に強く影響されてしまいます。

 

Attention機構の導入

長文参照を苦手としながらも、初期のニューラル自然言語処理技術の中ではデファクトスタンダードとして君臨してきたRNNでしたが、、Attentionと呼ばれる技術の登場によって目にする機会が減りました。

Attention Is All You Needという挑発的なタイトルの論文によって提唱されたAttentionは、BERTを始め現在の自然言語処理を支えるメインの技術の一つです。

RNNでは一つの状態ベクトルを更新しながら使いまわしていますが、Attentionでは各単語と文の全単語の関係を考慮して文の情報を付与したベクトルを作ります。

これにより単一の状態ベクトルを使い回す必要はなくなり、入力に応じて動的に文ベクトルを構築することで、距離の離れた単語に対しても同等な参照が可能になります。

Attentionにはいくつか種類があります。ここでは代表的なself-Attentionについ
て記します。Attentionは以下の図のように計算されます。

f:id:nmoriyama:20200116172800p:plain

論文より引用)

 

KとVはそれぞれ文の各単語ベクトルです。Qは入力単語ベクトルです。KとVをそれぞれ2つに分ける理由は計算時にそれぞれ異なる重みを保持するためです。計算フローは以下です。

  1. 入力単語Qと文の各単語Kの類似度を計算することでそれぞれの単語に対する重みを獲得
  2. 獲得された重みをもとに、各単語のVから情報を取り出す

エンジニアの方にわかりやすく言うと、入力文の各単語に対してKとVでkey-value storeを作っているようなものです。
また、複数のAttentionを持たせることで、様々な「視点」を導入できます

f:id:nmoriyama:20200116173826p:plain

論文より引用)

 

各Attentionは異なる重みを持つため、一つの単語に対して関係性が高いと判断する単語も変わってくるためです。

Attentionのメリットとして、上記の計算はRNNのように前の単語の処理に依存しないので、複雑なネットワークを用いること無く、シンプルな全結合ニューラルネットワークで実現できます。これにより計算効率がよく並列化も容易です。

 

Transformer

Attentionを活用したエンコーダーデコーダーがTransformerです。

エンコーダーデコーダとはその名の通りエンコードとデコードを行うモデルです。エンコーダーを通じて文をベクトルに変換(エンコード)し、デコーダーがそのベクトルを使って多言語に翻訳するなど(デコード)のタスクをこなします。

後述のBERTではこのエンコーダー部分を使って単語や文をベクトルに変換します。

f:id:nmoriyama:20200117124756p:plain

論文より引用)

 

一見複雑な構造に見えますが、よく見ると同じパーツを繰り返し使っていることがわかります。入力文と複数の(Multi-head)Attention層と演算する処理が繰り返されています。

ここで文をまとめて入力することにより、単語の語順や文脈を捉えきれていないのではないかという疑問が浮かぶかもしれません。もちろんこれは対処されています。

Attentionの前に全単語に対してPositionalEncodingという処理が加えられます。単語の位置をベクトルとして表現し入力単語に足すことで位置情報を付与します。

 

BERT

いよいよBERTです。複数のタスクで人間を上回る性能を記録したことから画期的なモデルとイメージされがちですが中身はシンプルです。そもそもBERTの名称は Bidirectional Encoder Representations from Transformersの頭文字を取ったものであるように前述のTransformerを複数結合させ、双方向で言語モデルを学習させたものです。

f:id:nmoriyama:20200117180645p:plain

https://ai.googleblog.com/2018/11/open-sourcing-bert-state-of-art-pre.html

上の図はBERTと他のモデルの比較です。BERTの図中で青色の丸がTransformerです。複数を双方向に結合させていることがよくわかりますね。

ここで重要なのは、BERT自体は特定のタスク向けに作られているわけではなく、他のタスク簡単に転用できるようになっているということです。冒頭で述べたように現在の自然言語処理では単語や文を意味を考慮した数値に変換させることが重要です。BERTはここで活躍します。

従来は、それぞれのタスクに対してモデルの構造を工夫していましたが、BERTでは、簡単な処理を追加しただけで多数のタスクで既存の特化したアルゴリズムに比べても高い性能を得られることがわかりました。


f:id:nmoriyama:20200117181904p:plain

  • (a)2つの文が連続するかどうか
    2つの文を結合させて入力し、出力される文のベクトルを使って連続かどうかのラベルを予測
  • (b)文の分類
    文を入力し、文ベクトルを使ってクラスラベルを予測
  • (c)質問応答
    質問文と知識結合させて入力し、知識のどこからどこまでが解答に当たるかを予測(解答の開始と終わりのクラスを予測)
  • (d)固有表現識別(人物、組織、場所など)
    各単語にその固有表現のクラスを予測する

 

BERT以降もGPT2やALBERTなど多くのモデルが研究されていますが、多くがBERTの構造を踏襲していています。
BERT自体の学習は2つのタスクを行います

  1. マスク単語予測
    文中のランダムで選ばれた15%の単語をマスクして、それを予測します
    これにより単語の意味や単語同士の関係性を学習できると期待されます

  2. 連続文予測
    2つの文が連続しているかどうかを予測
    これにより文の構造を学習できることが期待されます

この2つのタスクを学習していくことでBERTのパラメータをチューニングしていきます。BERT以降のモデルではそもそもマスクする単語はランダムでよいのか、連続文の解釈は範囲が広すぎるため工夫できないか、など様々な工夫がされています。

 

まとめ

以上BERTまでの流れを簡単に紹介しました。各手法の詳細なところは説明できていませんので今後ブログで少しずつ紹介できればと思います。

最後となりますが私が勤めているMNTSQでは自然言語処理エンジニアを募集しています。リーガルテックと自然言語処理に関心がある方はぜひまでご連絡ください!