6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

BERTを使った文書分類

Last updated at Posted at 2020-04-21

はじめに

仕事で、慣れないNLP(自然言語処理)の必要が生じたため、これを機に調べたことをまとめます。
Word2Vecが出てきて以来、単語のベクトル化が簡単になり、文(センテンス)のベクトル化も、いろいろと手法が出てきているが、文章・文書(文のかたまり)のベクトル化は、まだまだ難しいだろうと勝手に思い込んでいたのですが、私が勉強不足だっただけで、様々な手法が開発されており、自分で試したところ、想定していたよりいい結果が出たので、まとめることにしました。
手法を開発した先人たちに、深く感謝します。

自分で手を動かす前に、ネットで調べた際に、参考になる優れた記事にたくさん出会いましたが、下記の記事はその中でも、特に感銘を受けました。
https://qiita.com/nekoumei/items/1f5ec09e422a4be99810

やっていることは、各手法のシンプルな比較なのですが、BOWやTF-IDFのような、古典的とも言える手法も含めて、たくさんの手法を比較しておられます。
特に感銘を受けたのは、BOWとTF-IDFが、より新しい手法を凌駕して、圧倒的に優れた結果を出したことです。
このサイトの作者様も書かれていますが、文書分類という検証の性質上、特定の単語を含むかどうかが、大きな意味を持つだろうということを考えれば、当たり前のような気もしますが、実際のデータを使って、具体的な数値で手法間の差を表したことは、(私にとっては)非常に大きい意味を持ちます。
とにかく、BOWとTF-IDFの結果に驚きました。

使われているデータセットは、トピック間の類似度が低いので、もっと類似度の高い(似通った)トピックでの分類の場合は、(他の手法との比較という意味において)また、違った結果になるだろう、ということは想像できますが、文書分類の課題をやる時には、大いに試す価値があると思いました。

検証 1

せっかくなので、上記の記事に、少しだけ追加で検証を行いました。
内容は、下記の通りです。

検証 1-1

分ち書きに使われているMeCabをJuman++に変更して、変化があるかを確認しました。
モデルは、元の記事で、結果が良かったものに絞って実施しました。

結果

BoW

MeCab Juman++
fold 1 0.95658 0.96268
fold 2 0.95725 0.96200
fold 3 0.95858 0.95587
fold 4 0.95247 0.95790
fold 5 0.96062 0.96266

TF-IDF

MeCab Juman++
fold 1 0.96065 0.95929
fold 2 0.94572 0.94436
fold 3 0.94908 0.95247
fold 4 0.95247 0.95247
fold 5 0.94908 0.95587

SWEM-MAX

MeCab Juman++
fold 1 0.92062 0.90976
fold 2 0.92198 0.90637
fold 3 0.90427 0.91174
fold 4 0.90291 0.90563
fold 5 0.92668 0.91785

考察

MeCabからJuman++に変更して、結果が向上したものと劣化したものがあります。
一概に、どちらがいいとは言えなさそうです。
また、どちらにしても、大きな差はなさそうですが、処理時間を考えると、(個人的には)このケースでは、MeCabの方が、総合的には優れていると言えそうです。

検証 1-2

SWEMに、MIN+MAXとMEAN+MAXを追加
(SWEMについては、こちらの記事 https://yag-ays.github.io/project/swem/ が分かりやすいです。)

SWEMにて、MINとMAX(または、MEANとMAX)をconcatしたものを使用します。
MIN、MEAN、MAXの単体では、300次元のベクトルになりますが、300次元のMIN(または、MEAN)と300次元のMAXを結合して、600次元のベクトルとして、分類(LGBM)にかけています。
(fasttextのpretrained modelより、通常のw2vの方が結果が良かったので、そちらを使用しています。)

SWEM-MIN+MAX

結果

MeCab Juman++
fold 1 0.93012 0.92537
fold 2 0.92537 0.91926
fold 3 0.92803 0.92735
fold 4 0.92871 0.92057
fold 5 0.92871 0.92260

考察

BoWやTF-IDFには及びませんが、SWEM MAXよりは、数値が向上しました。
MeCabとJuman++の比較については、MeCabの方が優れた結果となりました。

SWEM-MEAN+MAX

結果

MeCab Juman++
fold 1 0.93283 0.92469
fold 2 0.93147 0.92469
fold 3 0.92124 0.92871
fold 4 0.92803 0.91853
fold 5 0.93754 0.93957

考察

SWEM-MIN+MAXより、わずかに数値が向上しました。
BoWやTF-IDFには及びませんが、かなりいい数値が出ています。
MeCabとJuman++の比較については、MeCabの方が優れた結果となりました。

検証 1-3

ベクトル化された文書を分類するのに使われているLGBMを、SVMに変更して、変化があるかを確認

結果

SWEM-MIN+MAX-MeCab

LGBM SVM
fold 1 0.93012 0.90027
fold 2 0.92537 0.88941
fold 3 0.92803 0.89545
fold 4 0.92871 0.87644
fold 5 0.92871 0.88458

考察

SVMの方は、大きく数値が低下してしまいました。
やはり、LGBM強し、ということでしょうか。

検証2

BERTを使った文書分類

さて、ここからが、いよいよ本題です。
先程までの手法は、あくまで単語のベクトルの集合を元に、文章のベクトル化を行なっていましたが、BERTでは、文をベクトル化することができます。
そこで、そのベクトル化された文の集合から、SWEMを使って、文章のベクトルを生成し、文書分類を行なってみたいと思います。
また、せっかくなので、分かち書きを、MeCabとJuman++のそれぞれで実施します。

こちらの検証を実施するにあたっては、下記のサイトの実装を参考にさせて頂きました。
https://orizuru.io/blog/machine-learning/bert/
https://yag-ays.github.io/project/pytorch_bert_japanese/
深く感謝申し上げます。

まずは、ベクトル化したものをtSNEで可視化します。

MeCab Juman++
SWEM-MAX MeCab_MAX.png Juman_MAX.png
SWEM-MIN MeCab_MIN.png Juman_MIN.png
SWEM-MEAN MeCab_MEAN.png Juman_MEN.png
SWEM-MIN+MAX MeCab_MIN_MAX.png Juman_MIN_MAX.png
SWEM-MEAN+MAX MeCab_avg_max.png Juman_avg_max.png
SWEM-MIN+MEAN+MAX MeCab_min_avg_max.png Juman_min_avg_max.png

正直、どれも、あまり違いがなさそうです。

では、数値を見てみます。

RandamForest

(*ハイパーパラメータはすべて指定なしです。)

MeCab
(1回目)
MeCab
(2回目)
Juman++
(1回目)
Juman++
(2回目)
SWEM-MAX 0.87788 0.87290 0.88150 0.88692
SWEM-MIN 0.87833 0.88421 0.87743 0.87924
SWEM-MEAN 0.87426 0.87788 0.88104 0.89009
SWEM-MIN+MAX 0.88059 0.88421 0.89326 0.88240
SWEM-MEAN+MAX 0.89823 0.90321 0.90909 0.91361
SWEM-MIN+MEAN+MAX 0.90094 0.89733 0.90592 0.90954

考察

精度では、MeCabよりJuman++の方が、わずかに優っています。
このモデルの場合、Juman++、MeCabともに、SWEM-MEAN+MAXが最も数値がいいという結果になりました。

SVM

(*ハイパーパラメータはすべて指定なしです。カーネルはrbfです。)

MeCab
(1回目)
MeCab
(2回目)
Juman++
(1回目)
Juman++
(2回目)
SWEM-MAX 0.93080 0.93939 0.94437 0.94527
SWEM-MIN 0.94301 0.93623 0.94166 0.94754
SWEM-MEAN 0.93668 0.92899 0.93578 0.93894
SWEM-MIN+MAX 0.94889 0.94346 0.94980 0.94211
SWEM-MEAN+MAX 0.94799 0.94392 0.94754 0.94301
SWEM-MIN+MEAN+MAX 0.94708 0.94166 0.95522 0.94889

考察

全体の精度では、やはり、MeCabよりJuman++の方が、わずかに優っていますが、SWEMの方式によって異なるなど、一概には言えない結果です。
このモデルでは、Juman++では、SWEM-MIN+MEAN+MAX(1回目)が最も数字がよく、MeCabでは、SWEM-MIN+MAX(1回目)が最も数字がいいという結果でした。

XGB

(*ハイパーパラメータはすべて指定なしです。)

MeCab
(1回目)
MeCab
(2回目)
Juman++
(1回目)
Juman++
(2回目)
SWEM-MAX 0.90909 0.92266 0.92130 0.92944
SWEM-MIN 0.91407 0.91361 0.91949 0.92266
SWEM-MEAN 0.89688 0.90050 0.90412 0.90683
SWEM-MIN+MAX 0.92854 0.92809 0.92763 0.92583
SWEM-MEAN+MAX 0.93487 0.91633 0.93216 0.93261
SWEM-MIN+MEAN+MAX 0.92402 0.92356 0.92763 0.93894

考察

ここでも、全体の精度では、MeCabよりJuman++の方が、わずかに優っていますが、上記と同様に、SWEMの方式によって異なるなど、一概には言えない結果となりました。
このモデルでは、Juman++では、SWEM-MIN+MEAN+MAX(2回目)が最も数字がよく、MeCabでは、SWEM-MEAN+MAX(1回目)が最も数字がいいという結果になりました。

LGBM

(*ハイパーパラメータはすべて指定なしです。)

MeCab
(1回目)
MeCab
(2回目)
Juman++
(1回目)
Juman++
(2回目)
SWEM-MAX 0.91316 0.90683 0.91633 0.92628
SWEM-MIN 0.91045 0.91633 0.91000 0.90502
SWEM-MEAN 0.90005 0.91045 0.90592 0.91045
SWEM-MIN+MAX 0.90592 0.91995 0.92266 0.92718
SWEM-MEAN+MAX 0.92266 0.92221 0.92537 0.91814
SWEM-MIN+MEAN+MAX 0.92763 0.91949 0.93623 0.93397

考察

やはり、全体の精度では、MeCabよりJuman++の方が、わずかに優っていますが、上記と同様に、SWEMの方式によって異なるなど、一概には言えない結果となりました。
このモデルでは、Juman++では、SWEM-MIN+MEAN+MAX(1回目)が最も数字がよく、MeCabでも、SWEM-MIN+MEAN+MAX(1回目)が最も数字がいいという結果になりました。

総論

BERTを使ったこの検証では、SVMが最も精度が高いという驚くべき結果となりました。
SVMの精度が高いということは、超平面で分離できているということなので、汎用性の高い、(比較的)理解の容易な、優れたモデルができているのではないかと推測します。

また、数値自体も、上記検証1のBoWやTF-IDFに準ずるような非常に高いものが得られていますが、BERTは、BoWやTF-IDFのような単純なモデルではなく、文脈を考慮した文のベクトル化をベースにしているので、より広範囲な状況で、有用な使い方ができるのではないかと思います。
「BERT恐るべし」です。

SWEMの方式としては、SWEM-MIN+MEAN+MAXが、最もいい数値を出すケースが多かったのですが、実施のたびに数値が変わり、必ずしも、SWEM-MIN+MEAN+MAXが最も優れているとも言えないようです。
また、SWEM-MIN+MEAN+MAXでは、次元数が多くなることを考えると、SWEM-MIN+MAXか、SWEM-MEAN+MAXがいい選択肢というケースもありそうです。

また、MeCabとJuman++の比較においては、純粋な精度だけの比較では、Juman++が優れているように見えますが、圧倒的な処理時間の差を考えると、よほど精度にこだわった場合でなければ、個人的には、MeCabの方が総合的に優れいているという印象でした。

以上、最後まで、お読み頂き、有り難うございました。

6
9
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?