自然言語処理において、テキストをその意味を考慮しつつ固定長のベクトルに変換する埋め込みモデルは重要です。文の意味をよく表現したベクトルを作ることができれば、テキスト分類や情報検索、文類似度など、さまざまなタスクで役立ちます。本記事では、Googleが開発した多言語の埋め込みモデル「LaBSE」を使って、テキスト分類をする方法を紹介します。単なるテキスト分類では面白くないため、学習には英語のデータセットを使い、評価には日本語とフランス語のデータセットを使います。
記事では要点だけを紹介するので、コードについては以下のノートブックを参照してください。
LaBSE
LaBSEは、Googleが「Language-agnostic BERT Sentence Embedding」という論文で提案したモデルです。109の言語に対応しており、これらの言語を与えることで、文の埋め込み表現を生成できます。モデルは170億の単言語の文と60億の2言語の文ペアによって訓練されています。訓練したモデルを多言語の情報検索タスクで評価したところ、m~USEやLASERといったモデルと比べて良い結果を示すことが明らかになりました。以下は単言語の文と2言語の文ペアの数を表しています。
文類似度
理屈的なところはともかく、実際にLaBSEを試した結果を紹介しましょう。LabseはTensorFlow Hubで公開されているので、まずはこちらを使って、多言語の文類似度を計算してみます。類似度計算には、下記のページ内のコードを利用しています。
以下の英語、イタリア語、日本語文の類似度を計算してみます。日本語と英語のペアを見るのがわかりやすいと思うのですが、各言語の同一インデックスの文は同じ意味を持ちます。たとえば、英語の1番目の文と日本語の1番目の文の意味は同じだとみなしています。したがって、LaBSEで文を埋め込んで類似度を計算した結果が、同じ意味の文は他よりも高い類似度になって欲しいということになります。
english_sentences = [ "dog", "Puppies are nice.", "I enjoy taking long walks along the beach with my dog." ] italian_sentences = [ "cane", "I cuccioli sono carini.", "Mi piace fare lunghe passeggiate lungo la spiaggia con il mio cane." ] japanese_sentences = [ "犬", "子犬はいいです", "私は犬と一緒にビーチを散歩するのが好きです" ]
類似度を計算した結果は以下のようになりました。左から英語と日本語、イタリア語と日本語、英語とイタリア語のペアとなっています。結果を見ると、行列の対角成分の値が他より大きくなっていることがわかります。つまり、同じ意味の文は、たとえ言語が異なっていても、類似度が高くなるように文を埋め込めていることを示唆しています。
テキスト分類
LaBSEで文を埋め込んで類似度を計算できることは確認したので、次はテキスト分類をしてみましょう。今回はAmazon Customer Reviews Datasetを使ってモデルの学習と評価を行います。このデータセットには、Amazonの商品レビューやその評価が含まれています。評価は星1から5までの5段階なのですが、今回は簡単のために、星3のレビューを取り除いた後、星1と2を0に、星4と5を1にマッピングして使うことにします。つまり、2分類です。
モデルのアーキテクチャは以下の通りです。LaBSEの上にDropoutと全結合層を足しただけです。
__________________________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ================================================================================================== input_word_ids (InputLayer) [(None, 128)] 0 __________________________________________________________________________________________________ input_mask (InputLayer) [(None, 128)] 0 __________________________________________________________________________________________________ segment_ids (InputLayer) [(None, 128)] 0 __________________________________________________________________________________________________ keras_layer (KerasLayer) [(None, 768), (None, 470926849 input_word_ids[0][0] input_mask[0][0] segment_ids[0][0] __________________________________________________________________________________________________ dropout (Dropout) (None, 768) 0 keras_layer[0][0] __________________________________________________________________________________________________ dense (Dense) (None, 2) 1538 dropout[0][0] ================================================================================================== Total params: 470,928,387 Trainable params: 470,928,386 Non-trainable params: 1 __________________________________________________________________________________________________
学習データと評価データの数は以下の通りです。冒頭で述べたように、学習データには英語、テストデータには日本語とフランス語を使って評価します。実際のところ、日本語やフランス語のデータの中にも英語のレビューが含まれているので取り除くべきですが、大勢に影響はないと考えられるので、今回はそのまま使うことにしました。ちなみに、2クラスの割合は等分です。
en | fr | ja | |
---|---|---|---|
train | 32000 | ||
test | 8000 | 8000 | 8000 |
実験結果(acc)は以下のようになりました。以下は、何度か試した中での最高値であることに留意してください。英語でしか学習させていないにもかかわらず、フランス語や日本語に対しても、まずまずの予測をすることができています。実験する前は、英語のデータだけでFine-tuneして大丈夫か心配だったのですが、どうやらそれなりには予測できるようです。ここにはLaBSEの重みを固定して使った結果は載せていませんが、学習させた方が良い結果となりました。
en | fr | ja | |
---|---|---|---|
test | 0.9324 | 0.8943 | 0.8506 |
今回はテキスト分類に使いましたが、固有表現認識のような系列ラベリングに使ったらどうなるのかは気になるところです。