nikkie-ftnextの日記

イベントレポートや読書メモを発信

素振りの記:BERT-CRFで固有表現認識したい!『大規模言語モデル入門』6章でクイックツアー

はじめに

無敵級ビリーバー3周年👑👑👑 nikkieです。

「お休みの日にしかできないことを」と追求した結果、最近のお休みは開発合宿感があります。
今回は気になっていた技術、BERT-CRFを触りました。

目次

ずっと引っかかっていたBERT-CRF

BERT-CRFという技術は固有表現認識でなかなかよいと聞いていました1
ただずっと「具体的にどう実装すればいいの?」というところがよく分かりませんでした。

2018年に登場した機械学習モデルBERT2
Transformer3というアーキテクチャを使って組み上げられたこのモデルは、1つのモデルで複数の自然言語処理タスクが解けるということで注目を集めていきます4(一つの時代を築きましたね)。

自然言語処理のタスクの1つ、固有表現認識5
これを深層学習モデルで解く場合、CRFを合わせるとよいことが分かっています。

BERT登場以前はLSTMが性能がよいモデルとして知られていましたが、LSTMもCRFと組み合わせると性能が上がります。

BERTの場合も同様で、BERT-CRFとして知られます。

性能がよい手法なら実装できるようになりたいと思い、参考実装を調べたこともあったのですが、私にとってはなかなか壁は高かった感じでした。
情報を求めに行くもピンポイントで見つからなかったり、見つけられても必要な知識が多く要求されて手を動かしきれなかったり...

『大規模言語モデル入門』6章「固有表現認識」

発売されたばかりの『大規模言語モデル入門』。

6章が固有表現認識。
買って詳細目次を見て驚いたのですが、BERTのファインチューニングで固有表現認識タスクを解いた後で(エラー分析をはさんで)BERT-CRFで精度改善までするんですよ!
「この6章を読めば知りたかったことが知られるかも!」とBERT-CRFを触るべく手を動かしました。

ソースコードは公開されています。

ローカルに開発環境を用意しなくてもGoogle Colabで動かせます。

BERT-CRFクイックツアーの感想

写経したノートブックはこちらです(訓練まで)。

一応テストセットに対する評価結果まで出せていて

{'precision': 0.8833580980683506,
 'recall': 0.891972993248312,
 'f1_score': 0.8876446435237028}

(5エポック訓練したものを評価しました。ベストかは見ていないです)

公開ノートブックに載っている性能です。
https://huggingface.co/llm-book/bert-base-japanese-v3-crf-ner-wikipedia-dataset

{'precision': 0.8944610778443114,
 'recall': 0.8964741185296324,
 'f1_score': 0.8954664668415137}

同じコードを繰り返し書きたくなかったので、6.2で作ったoutput_tokens_and_labelsリファクタリングして再利用しました。
Colabではなくローカル環境にスクリプトとして写経してdoctestを書きながら進めました。
モデルに入力するTensorとそれをモデルの中で扱うところが(テストコードが書けず)自信がなかったのですが、訓練できているみたいだからヨシ!

1日で訓練〜評価のすべて理解するのは時間が足りなかった面もあり、評価については「コピペしたのでなんかよくわかんないけど動いた」が半分くらい残っています。

書籍への感想

  • 固有表現認識の理論の説明が非常に丁寧
    • 例:固有表現のタイプにはどんなものがあるか。数例(MUC、IREX、拡張固有表現階層)紹介
    • 参考文献のリンクがめちゃめちゃ充実している
    • これを1冊目で読みたかった感(教科書感がある)
  • そのうえでBERT-CRF(かつてのSOTA)まで連れて行ってくれる
    • 入門と言っているけど、題材はめちゃめちゃ本格的!
  • Hugging Face Hubにデータセットやモデルが公開されている!
  • 知らなかったライブラリをめっちゃ知られた
    • spacy-alignmentspytorch-crf
    • 現状メンテされていないように見えるライブラリもあるのは気になっている
    • 関連:知っていたライブラリもサンプルコードを見て、使い方に学びがあった(クイックツアー感)
  • モデルの選択〜性能評価は、書籍の流れでいいのかな?
    • ストックマークさんのデータセットを使っていて、train / validation / testがある
    • 5エポック訓練。5つのcheckpoint(モデル)をvalidationデータを使って選択。選んだモデルをtestデータに対して汎化性能の評価
    • あれ、validationデータを使って訓練しているぞ?
      • trainデータとvalidationデータ両方をtrainerに渡している
    • 訓練でvalidationデータをevalに使ったうえで、checkpointのモデルのうちvalidationデータへの評価指標で選択するのは、汎化性能最大のモデルの選択と言える?言えない?
      • evalのスコアで早期終了していないから大丈夫?
    • 私は厳密にやるのを好むので、trainを2つに分割して、validationはtrainerには一切渡しません6

サンプルコードへの感想

  • 型ヒント書いてある、めっちゃありがたい!👏
  • 型ヒントには伸びしろありますね
    • 思うに、人向けだけの型ヒント(型を表すコメントに近い)
    • mypy(型チェッカ)は実行していないんじゃないかな。mypy流していたらエラーで落ちます
  • 組み込み関数のanyを型ヒントに使ってはいけません
  • dict[str, Any]という型ヒントに直した上で
  • データサイエンスのコードでよく見かける、複数の返り値の関数
    • 書きたい気持ちめちゃ分かるんですが、複数返り値あると関数がまず大きいですし、再利用もしづらくなるんですよね
    • 今回は手元で容赦なくリファクタリングしました(単一責務にしていく練習)
    • 例えばoutput_tokens_and_labelsという(tokens, labels)を返す関数はtokensを返す関数とlabelsを返す関数にバラします
      • スコープ小さくなって私としてはスッキリ。doctestも書きやすい

終わりに

『大規模言語モデル入門』のおかげで、ずっと気になっていたBERT-CRFを訓練できました。
なるほど、こんな感じになるのか〜

  • 理論面を詳しく、transformersなどのライブラリは最小限で押さえて、BERT-CRFまで実装できました
  • 書籍内のPythonの型ヒントの書き方は伸び代あり。誤った型ヒントもあるので、型ヒントはどこか別で学ぶのをオススメします
    • 型ヒントについて意味分からないけど写経するというのは、間違えて身に着けてしまうリスクが高いので、私はオススメしません

BERT-CRFについてはストックマークさんの本でも取り上げられていたのですが、

『大規模言語モデル入門』がタイミングやとっつきやすさがあって、今の自分にピタッとハマった感覚です。
BERT-CRFを学ぶための題材が実は他にも手元にあった(積読していた)と認識したので、活用して理解度を上げていくぞ!


  1. [1810.04805] BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
  2. 理解が深まった勉強会
  3. NLP2022のチュートリアルがとってもオススメです。コンビニで例えられるBERT。
  4. 深層学習までは使わずCRFで素振りした例
  5. resbt氏の論文を参照しています
  6. TypedDictはマジでよいです!