A Day in the Life

gzip + kNN のテキスト分類で BERT 超え論文 "Low-Resource" Text Classification: A Parameter-Free Classification Method with Compressors を実装し試す

最近公開された論文 “Low-Resource” Text Classification: A Parameter-Free Classification Method with Compressors (Jiang et al., Findings 2023) は、gzip で圧縮したデータの長さを活用し、テキスト分類課題で BERTよりも優れたパフォーマンスを発揮すると述べています。面白そうだったので、自分でこの方法を実装して試してみました。その結果、実際に livedoor ニュースコーパス を用いたテキストのカテゴリー分類では、日本語 BERTよりも優れた結果が出ました。

どんな手法なのか

やっていることはシンプルで、まずNCD(Normalized compression distance)を算出します。例では圧縮アルゴリズムに gzip を使っています。

  • 個々のデータxとyを圧縮し、それぞれの圧縮後の長さをC(x)、C(y)とする。
  • 2つのデータを結合したものxyを圧縮し、その圧縮後の長さをC(xy)とする。
  • NCDを計算する
    • NCD(x, y) = [C(xy) - min(C(x), C(y))] / max(C(x), C(y))

これで、情報が似ていればNCD近く(小さく)なります。"Hello world!" と "Hello!" を結合したものは圧縮率が高くNCDが小さそうですが、"Hello world!" と "Good!" は NCD が遠そうですよね。

続いて、この距離で学習元データをソートして、top-k を取り出して、そのtop-k のカテゴリーの中から最も多いカテゴリーを推論結果とします。NCD距離から最近傍のデータk個を使って決定する、つまりkNNですね。

実装する

元論文の実装として https://github.com/bazingagin/npc_gzip が公開されているのですが、やってることは単純なはずなのに利用するにはなかなか難解なコードとなっていたので、sklearn の fit / predict のインターフェイスでサクッと使えるような形で実装してみました。

livedoor ニュースコーパスで試す

これの実装を使って、livedoor ニュースコーパスのカテゴリー分類をやってみましょう。【実装解説】日本語版BERTでlivedoorニュース分類:Google Colaboratoryで(PyTorch)では、testとして1475個(全体の約2割)を推論し、正解率が 0.9261 とのことでした。

今回私は、データセットを train:test で 8:2 に分割し、train: 5894個 test: 1473個のデータに対して分類してみました。

結果の正解率は 0.9457 となり、日本語BERTを超える結果となったようです。単純な仕組みなのにすごい。なお validation 用意しないの?と疑問に思った方もいるかも知れませんが、やっているのはただの距離の計算(NCD)だけで事前学習させているわけではないので、valなデータは作っても意味がないので作っていません。

# 正解率
0.9456890699253224
# 混合行列の結果
[[150   0   0   0   1   1   0   0   0]
 [  0 166   2   2   3   0   0   0   2]
 [  0   1 164   0   0   2   0   0   0]
 [  0   0   1 156   0   0   5   0   0]
 [  5   1   3   2 103   5   0   3   4]
 [  5   0   1   1   5 148   0   4   3]
 [  0   0   0   5   1   0 182   0   0]
 [  1   0   1   0   3   7   0 151   0]
 [  0   0   0   0   0   0   0   0 173]]

MARC-ja で試す

同様に、JGLUEデータセットの MARC-ja を評価しましょう。MARC-ja はポジティブ9割、ネガティブ1割の分類ラベルが付いた、約19万件のデータセットです。なお日本語BERTで正解率 0.958 とのことです。ちなみに全部ポジティブラベルとして判定した場合、正解率は 0.9 ぐらいのデータですね。

NCD Classifier で試した結果、正解率 0.802 でした。圧倒的な悪さ…!最初は悪すぎて実装ミスかと何度も確認したのですが、データセットの分布に大きく偏りがあること、テキスト長が短すぎるデータが多いこと(livedoor ニュース記事などはそこそこの長さがある)で、あまり性能が出ない感じでした。

# 正解率
0.8020870180403255
# 混合行列
[[4077  755]
 [ 364  458]]

AGNews で試す

論文ではAGNewsに対するスコアが 0.937 を達成したと記述されていますが、私の実装では 0.898 程度しか達成できませんでした。この違いについては原因が不明ですが、実装の差異や使ったデータ、データ処理の何らかの違いが考えられます。このへんは私の実装が悪い可能性もあるので、実装に不備がありそうでしたら教えてください。

# 正解率
0.8976315789473684
# 混合行列
[[1718   47   83   52]
 [  20 1838   23   19]
 [  72   31 1635  162]
 [  81   37  151 1631]]

ざっくりまとめ

学習せずにともNCD(gzip) + kNN という単純なテキスト分類で、場合によっては BERT 超えの性能が出ることが出ることが確認されました。論文でも書かれていますが、とりわけ数百件~数千件ぐらい、かつテキスト長がそこそこあるニュース記事のような小さなデータセットに対しては、よい性能が出そうな感じです。今回試した中ではlivedoorニュースコーパスのようなデータセットがまさにですね。

事前学習を必要としないカジュアルなテキスト分類に使える分類器の一つとして、この論文のアプローチのテキスト分類機を使ってみても良さそうですね。実装も簡単ですしね。

ただ論文で書かれている通り計算量がデータが増えれば増えるほど増大します。推論時の計算量は Mをtrainデータ件数、Nをpredictするデータ件数とする場合、ざっくりO(M*N)となるので、データが増えれば増えるほど、predict時の推論コストが掛かります。特徴を学習しているのではなく、ベタにフル計算するので遅いです。例えば、MARC_ja のデータセットは M = 187528, N = 5654 となるので、かなりの計算コストになり、CPU に Ryzen 7950X の仮想32コアをフルで使って5654件を推論させても30分ぐらいかかります。

ともあれ、事前学習を必要としないシンプルなアプローチで、用途に応じては十分な性能が出るという、面白い内容の論文でした。

記事の一覧 >

関連するかもエントリー

AI News の公開と、裏側の OpenAI の活用話
AI News という、AI・データサイエンス(DS)・機械学習(ML)関係の話題を集め、AIで3行に要約して配信するサイトを公開しました。twitter @AINewsDev や Atomフィードでも配信しています。数日前から運用していて、手前味噌ですが便利に情報集めに使えてい...
AI News という、AI・データサイエンス(DS)・機械学習(ML)関係の話題を集め、AIで3行に要約して配信するサイトを公開しました。...
ファインチューンせずに高速に学習できる RAPIDS SVR (SVC) の紹介と MARC-ja の評価
先日参加した Kaggle コンペFeedback Prize - English Language Learningで知った手法、RAPIDS SVR (SVC) が高速に学習でき、回帰や分類タスクでは有益な手法の一つと感じたので、どのようなものかを紹介する。実際にこのコンペの...
先日参加した Kaggle コンペFeedback Prize - English Language Learningで知った手法、RAPI...