NLPからLLMへ: 何が変わったのか?

LLMの極めて高い表現力やAPI化&OSS化が進んで、昔ながらのNLPシステムにとってはおおよその個別タスクが解かれてしまったように思われているところがある。具体的にNLPシステムの設計や構成要素、役割がどのように変わったのか?さらにこれから変わっていくのだろうか?を、過去のシステムと対比する形で考えてみたい。

NLPモジュールの進化発展: 記号システムと機械学習システム

推論器としてのNLPのシステムの進化発展は、入出力データに対する「意味付け」「仮定」が弱まる方向に進化してきたといえる。人間が行なっている自由度の高い自然言語や対話プロトコルに従ったコミュニケーションを再現しようと、機械が意味ある形で処理できるテキスト入出力のパターンを広げてきた歴史として。

最も古くはルールベースの予測システムで、入力がif文のような論理で書き下せる範囲のある表現に収まる限りは、システムが意味的に正しく解釈可能な出力を返すというものだ。論理によるルールは記述長に対する入出力関係の表現力が低いことに加えて、人間がそれを解釈してメンテナンスする必要があるため、現実的に可能な表現力は大きく制約を受け、そのためごく狭い範囲の入出力しかカバーできないシステムとして発展が止まった。記述長に対する入出力関係の表現力が低いことは、「入出力関係の圧縮性能」が低いことだと言い換えられる。この性能が低いことは、ルールベースのシステムの入力形式、ルールの表現形式が離散的な記号ベースの表現であることに起因しており、要は表現として無駄が多いのである。

※以降も一貫して、AI技術におけるモデリングとは入出力変換処理(関数)の情報圧縮技術であるという捉え方をしている。情報圧縮を追求する上で、人間の恣意性はじゃまとなる。

次に現れたのがいわゆる古典的な機械学習、あるいは統計モデリングをベースとした予測システムである。これはNLPの分野では、記号の世界をベクトルに変換すること(ベクトル空間モデル)とセットで立ち現れてきて、入出力関係を純粋な数量表現の変換に還元することを達成した。モデリングの場所が記号空間から数量空間に飛躍した瞬間である。ただしこの時点でのベクトルは、要素(次元)の値が人間にとって理解/解釈できるような表現で与えられており、その表現を設計するのは人間の仕事で、特徴量エンジニアリングと呼ばれた。NLPの特徴量としては単語の出現頻度や単語間の関係の有無(0/1)などがあり、人間が何かを判断するときの"きっかけ"となりそうな定量特徴が、恣意的かつ機械的な抽出ルールで定義されていた。古典的機械学習の予測システムは、「人間が捉えた特徴」同士の組み合わせおよびその数理的変換を通じて表現力を獲得したことで、機械的な入力から非機械的な出力を得ることに成功した。

数量空間における組み合わせと数理的変換の部分を通じて、記号ベースのシステムに比べると遥かに圧縮性能を向上させることに成功した。これは記号ベースのシステムの天井となっていた記述長に対する表現力の限界を大きく引き上げることに成功した。しかし、入力となる特徴量はあくまで人間が捉えた特徴に制限されており、この時点で十分な性能で解くことのできる問題の範囲は大きく限定されていた。例えば、主語の省略解析のような人間が頼りにしている「きっかけ」の傾向が明らかでないようなタスクはまるで解けない状況だった。

また出力についてはスカラーやベクトルで表現されるようにはなったが、その数値表現を記号表現に戻す(decoding)際にはごく限られたラベル表現の範囲に限定されていた。例えば高々数百種類の多クラス分類であったり、数十種類の多クラス系列ラベリングのようなタスクが現実的に解ける範囲であった。

入出力の形式がベクトルという画一的な数理表現に還元されたことで数理手法への展開が広がったものの、入出力に込められた意味付けの表現力(圧縮性能)においてはまだまだ人間が強い仮定を敷いているシステムであったと言えるため、一部を除いてはまだまだ表現力が足りなかったといえる。

このルールベースと機械学習ベースの組み合わせから成るNLPシステム時代は20年ほど続いた。単一の予測器で表現できるタスク範囲が大きく限られていたことから、ある程度認識システムとして高度な処理を実現するには「予測器のパイプライン」型(Piecewise型)のシステムとして全体としての推論器が実現されることが主流となっていた。例えば、ある予測器は入力文字列を単語列に分割し、続く予測器は単語列の間の構文関係を認識し、単語列とその構文関係から文の中にある固有名詞を取り出す、ようなイメージだ。この手のシステムはルールではとても表現できない入出力関係の認識を実現することはあったが、大抵が複雑な予測器の複雑なDAGとしてパイプラインが表現されたため、ロジックのデバッグやテストの複雑さの問題など、ソフトウェアとしての保守性の難しさは未だに残していた。とはいえ、ルールのシステムが変換ロジックそれ自体の記述量が多く可読性が低かったことに比べると、数理的還元を通じたロジック部分の複雑性が大きく減じたことは大きな進展であった。

NLPモジュールの進化発展: 深層学習システムによるE2E化

その後立ち現れてきたのがDeep Learning(DNN)ベースのシステムとなっている。このシステムは入出力をベクトル表現の数理変換として表すという点では機械学習のひとつといえるシステムだが、古典的機械学習との大きな違いは「入出力データに対する意味的/恣意的な仮定が大きく減った点」であるといえる。これは機械学習が入出力関係表現の圧縮性能を向上させた点に進展があったのに対して、「入力データ・出力データの圧縮表現」にも大きく進展が見られたことに支えられている。DNNベースのシステムにおいては、古典的な機械学習システムで人間が考案し与えていたような特徴量は、システムが学習によって自動獲得した入力表現およびその変換部分に圧縮表現されるようになり、入力に人間が明示的に知恵を込める必要が大きく減ることとなった。この圧縮表現のうち、変換部分は古典的機械学習と同様なDNNのモデルパラメタにあたるが、入力データの密ベクトル表現は特にembeddingと呼ばれる。DNNへの入力が単語なら単語embedding、文ならば文embeddingといった次第である。古典的な機械学習NLPシステムの入力が解釈可能な代わりに圧縮率の低い疎ベクトルであったのに対して、Deep Learningで性能を発揮するNLPシステムの入力は解釈困難な代わりに圧縮率の高い密ベクトルに入れ替わった形だ。

NLPシステムのDNN化の帰結としては、「入出力の関係が遠いようなタスク」であっても、単一DNNの認識システムとして実現できるようなことが多く確認されるようになったことがある。言い換えると、piecewiseな複合パイプライン型のNLPシステムが、単一推論器から成るend-to-end型のシステムとして実現できるように進展した。例えば文字列から固有名詞列を取り出すシステムについて対比してみると、古典的機械学習に基づくNLPシステムが、あるピースは文字列入力単語列出力のもので、あるピースは単語列入力単語間構文関係出力のもので、あるピースは単語列および単語間構文関係入力の固有名詞列出力のものから成るようなパイプラインで処理全体を構成していたのに対して、DNNベースのNLPシステムは文字列入力固有名詞列出力一本のモジュールとして著しく簡易に実現できるようになった。ここで興味深いのは、ソフトウェアパイプラインとしては単一推論器に縮約された一方で、推論器の数理表現としての層の深さ/パラメタ数としては一層深さと数を増している点である。人間が情報をプログラムで表現していた部分が、徐々に数理表現に変化していき、処理全体としての圧縮率を上げ続けている点がポイントである。これにより、現実的なサイズや保守性を持って、従来不可能であった入出力関係の表現力の獲得範囲が広がり続けてきた。

DNNベースのシステムについては、数理モデルが原理的に有している表現力が持て余されていた。そもそもDNNの構成要素たるニューラルネットは20年前ほどに一度着目されたが、当時の計算性能とデータ量ではそのポテンシャルをフル活用できなかったことにより手法として注目されなくなっていたという歴史がある。現代の計算性能とデータ分量を以てして、改めてその表現力の活用幅が広がることとなったが、機械学習教師あり学習の枠組みにおいては「教師データを作る人間の介在がボトルネック」となっていた。ルールベースシステムのルール設計、古典的機械学習の特徴量設計、DNNシステムの教師データ、さまざまな点で人間の知識介在がモデル数理表現への圧縮に対してボトルネックとなり続けてきた。実際、深層学習NLPが実用化する上での最初のブレークスルーは、word2vecに代表される単語embeddingを教師なし学習によって低コストで獲得することに成功したことからもたらされた。

基盤モデルによる汎用モジュール化とサンプル効率の向上

人間の知識介在のボトルネックを解消することに大きく成功したのが、教師無し/自己教師あり学習による大規模モデル圧縮の実現である。単語embedding表現獲得の時代からさらなるブレークスルーをもたらしたのが、圧縮性能の非常に高いDNN素子であるTransformerの発明と、Web由来の膨大な言語データセットに内在する文脈情報の大規模な教師なし学習に成功したことである。それまでの機械学習・深層学習の方法論が、教師データを得て初めて関数の学習に成功するような方法論であったために初期開発コストが非常に高かったのに対して、「事前に大規模に教師なし学習をかけておく」ことで「言語データセット一般に内在する文脈情報」をモデルに事前に圧縮しておく(事前学習)ことで、いざ所望の関数を学習するときにごく少ない教師データの供与で済むようになる(Fine-Tuning)というブレークスルーがあった。事前学習とFine-Tuningの発明と進化は、言語の文脈情報の圧縮による汎用モジュール化(Task-agnostic化/マルチタスク化)とサンプル効率の向上(Few-shot学習化)に対して大きな進展を与えた。事前学習により一回性の高コストをかけて獲得されたモデルは "基盤モデル" と呼ばれ、実際の応用時にFine-Tuningをかけることで使いまわされるような応用構成が誕生した。

初期はBERTをはじめとするMasked Language Modelingに代表されるようなEncoder-Decoderベース基盤モデルの手法が成功を収めていた。このモデルは文脈(状況に応じた単語や文の意味)をよく圧縮するようなembedding表現を獲得することで、汎用モジュールの数量表現を与えるような形となった。この時点で、テキストを入力して出力ラベルのスカラーや、テキスト単語に対応する出力スカラー列を予測するようなタスクに対しては人間の認識レベルに匹敵し得る成功を多く収めた。さらに、この過程で獲得されたembeddingは従来の単語embeddingのようなプリミティブな表現だけでなく、人間にとってそれ自体が独立して意味ある情報を与えるような文のような大きなデータ単位に対してもembedding表現を与えることに成功し、この発展は古典的な全文検索システムに対するベクトル意味検索システム技術のきっかけを与えていくことになる。

ここまでくると、(人間が考えうる限りの)まだ解けていないタスクは自由テキスト入力から自由テキスト出力を与えるような「テキスト生成タスク」に限られるようになっていった。これは解空間の非常に広いタスクであり、モデリング性能の改善よりもデータ学習規模や計算資源規模がボトルネックになっていたことが振り返って明らかとなった(スケーリング則)。モデリングの面では、テキスト生成タスクの性能はEncoder-Decoder構成のようにEmbeddingの獲得を必ずしも目的としない、Decoder-only基盤モデルでよく成功を収めるようになっていった。例えばGPTシリーズはその方向性で進化を進めてきた基盤モデルである。Decoder-only基盤モデルは次の単語(トークン)を予測するタスクで表現され、これはngramのような昔からある古典的言語モデル技術のタスク制約を守っているが、ngramのような統計に基づく古典言語モデリングはモデルサイズが膨大で圧縮性能に限界があることは周知されていた。その問題に対してword embeddingやMLMのような中規模の基盤モデルでは、次の単語予測を位置に依存しない予測を行う形にタスク制約緩和することでルースに表現獲得することに成功していた。これは今振り返ってみると単語間の関係性表現(attention)の圧縮がスケール則観点で足りなかったためと解釈されるだろう。実際、テキスト生成ではない古典的なMLタスクに対しては大抵それで十分なことが分かっていった。

次のトークンを予測するタスクを高品質かつ超大量のデータセットで超大規模に事前学習を推し進めることによって、単なるテキスト生成タスクが得意な基盤モデルから、GPT3モデルのような「文脈内学習(In-Context Learning)」が可能な大規模言語モデルが登場することになった。「プロンプト」という非常に自由度の高い形式のデータを与えることによって「Few-shot学習」や「Task-agnostic化/マルチタスク化」への対応がさらに簡単に実現できるようになった。AIの歴史として見ると、このあたりがパンドラの箱を開いてしまった瞬間に思われる。

In-Context Learningの雰囲気はOpenAIのJasonWei氏のブログを参照: https://www.jasonwei.net/blog/some-intuitions-about-large-language-models

LLM:E2Eシステムからエージェントシステムへ

プロンプトプログラミングの非常に強力な汎用性はGPT3の報告あたりから研究界隈では認識されていたが、サービス・アプリケーション開発への普及にはChatGPTの存在が欠かせなかったことは周知の通りである。ChatGPTはAIへのインターフェイスの進化だと呼ばれる。具体的には、次の単語を予測する形に適合したプロンプト形式として事前学習されたモデルを、さまざまなタスクを意図した人間の自然文指示に対して適切な自然文応答を返すような振る舞いにFine-Tuningされたようなモデルとなっている(Instruction Tuning / RLHF)。当初多くの研究者にとっては解けるタスクの幅が広がったようには見えておらず、あくまで人間と話すようにAIに指示を出せるインターフェース調整くらいにしか捉えられていなかったモデル更新だったが、パンドラの箱が開いた状態のAIが直感的に対話できる具体的なアプリケーションとして世の中に晒された結果、歴史上ないレベルの反響が起こった。人間とむき出しのAIとの間で自然なコミュニケーションが可能になった瞬間である。その帰結として、これまで「変換処理(関数)」を圧縮するだけの役割だったAIモデルに、自らが有する情報を引き出すソース・「情報源」としての役割が課されるようになったことも大きな転換点だと言える。深層学習で爛熟期にあった「End-to-Endのテキスト変換処理モジュール」としてのAI部品から、「人間要求から人間を代理する形でサービスアウトカムを提供するエージェント」としてのAIへの躍進である。ソフトウェアスタック要素としてのEnd-to-Endが意味するところの役割に、ライブラリからサービスへのような相転移が起こったタイミングであると考える。

(※ 大規模事前学習の過程で、いつの間にか多言語タスクを解ける状態になっていた状態でリリースされたことも、全世界的な現象となったことを支えている。特に日本語のようなマイナー言語は、英語によるデータセットで獲得できる成果から2-3年遅れて実際のAIモデルにアクセスできるというのが過去の状況だったが、ChatGPT以降はAPI費用を除く初期投資ほぼ無しに、機械学習的AI機能のサービスを受けられるようになったことは開発者には相当な影響を与えている。)

今後の発展に対する期待

ここまでの進化を支えてきたのは、「モデリング(圧縮)アルゴリズム」の発明、「計算資源」の開発、「データ資源」の開発、といった足し算的要素と、「個別要素からE2Eシステムへ」、「開発プロセスに人間が関与する度合いの漸進的削減へ」といった引き算的要素が全体としてかわるがわる発展していくことで成り立ってきた。Transformerあたりからモデリングに頭打ちが起こり、GPUメモリ観点から計算資源に頭打ちが起こり、インターネット上からアクセスできるデータ資源の総量にも頭打ちが起こり、価値のあるE2Eアプリケーションの発明に頭打ちが起こり、AIを開発するエンジニアの総量に頭打ちが起こる、といった制約がある中で、次なる発展はどういった方面になっていくのだろうか。個人的に関心を持っているのは「サービスモデリング」「データ資源」の部分がAIが自律的に解決進化していけるようになっていき、さらなるブレークスルーが近く起こることに期待をしている。同時に、Transformerを著しく超える「モデリングアルゴリズム」の発明と現在のGPUの制約を超えるような「計算資源」の進展は、それらに比べると緩やかな進化に止まりそうだとも考えている。

「サービスモデリング」の自律解決については、人間がナイーブに期待するEnd-to-Endのサービスを、AIに途中過程を考案・繋ぎ合わせてもらうことで自律解決してもらい、人間が享受できるサービスのE2E性にさらなる地平がもたらされることを期待している。OpenAIのGPTsによってその文化は興り始めているし、自動プログラミングの分野でもAIが自律的に構成できるソフトウェアスタックについては今後も広がっていくだろう。

また開発者目線的には「データ資源」の自律解決の方により関心がある。まず思いつくのはLLaMAの出力を使った後続モデルが広く開発されたように、Instruction Tuningの教師信号をLLMによってデータ合成するテクニックが発展していくことがある。そもそもLLMに対する教師データ、特にInstruction Tuningのような自然文入力自然文出力の教師信号を、人間が一貫性のある形で付与すること、それをマニュアル化することは極めて困難に見えているというのがある。過去開発現場で教師あり学習をしてきた経験上、細かいラベル仕様上のズレよりも、作業者による品質が一貫しないことの悪影響の方が大きくなりそうだと直感しているためだ。LLM出力であれば相対的に一貫性を担保しやすいし、仕様がズレていたとしてもプロンプトを調整して再実行すればやり直しが効く。教師ラベル作成フェーズにおいて今後人間が関与すべき場面がどこかは、根本的に見直されるべきだと考えている。

また、強化学習の報酬関数のような元来人間が設計することが非常に困難だった要素をLLMが肩替わりすることで、従来注目が薄かった学習モデリングが適用できるようになっていくことが、プラニングなどの実務応用でも新たなブレークスルーをもたらすかもしれないことを期待している。ここは個人的にあまり経験に紐づく感覚がないので、今後色々試してみたいと感じているポイントだ。上のサービス発明の観点と関連させると、実行環境によって正解不正解が厳密に与えられるようなタスクでLLM技術が無双するようなケースがゲームのような用途以外にも発見されると、非常に面白いように思う(プログラムのドラフティングは、その一つとしてすでに手に馴染むツールとなり始めている)。

※ 記事をちょうど書いている頃にも研究で盛り上がりを見せているのを観測している: https://starling.cs.berkeley.edu/

(ただし今後に対する期待の部分は、書いててそこまでクリアな感情はあまりなく、なんとか捻出してみたものでした…)

(これまでモヤモヤと溜まっていた頭の中のまとまりと振り返った感想を一度吐き出しておきたかった、という方が正直ですね)

固有表現抽出のアノテーションデータについて

自然言語処理技術のなかでも固有表現抽出(Named Entity Recognition; NER)は情報抽出の処理をやろうとするときにとても役立つ。

応用は幅広く、会社名や個人名などの情報抽出処理、個人情報除去などのような抽出した情報に対する処理、代名詞の解析(照応解析・共参照解析)のような文脈解析処理などに用いられる。

最も簡単なNERの方法としては、辞書や形態素解析結果や正規表現などに基づくルールを用いて、単語列にラベリングする方法があるが、会社名など判断が難しいケースについては機械学習によってNERを行うことが有効なことが多い。機械学習ベースの既存の固有表現抽出器を使ってみたい場合には、GiNZAやKNPのようなNERモデルが同梱されているツールを使用してみるのがよい。

しかし公開モデルの性能では満足いかない場合に自分でモデルを構築しようとしても、公開データセットが見つけにくかったりデータ処理が面倒だったりして想像以上に道のりが険しい。

本記事では、機械学習を用いたNERを行う上で必要な、公開データセットおよびその仕様の知識や、自前で教師データを作成する上での要点を概説する。本記事では、モデル開発プロセス、特に具体のフレームワークに準拠した学習・評価・改善に関する情報は触れていない。

アノテーション仕様とデータセット

固有表現抽出モデルを教師あり学習で自分で開発したい場合には、公開されているデータセットを用いて自分で実験することができる。

さらに、固有表現ラベル体系が自分のニーズに合っていない場合など、自前で教師データを構築したい場合には、アノテーション仕様の決定・アノテーション作業環境構築・作成したアノテーションデータの加工処理などが必要となる。

以下ではまず、アノテーションの仕様を構成する固有表現タグ形式と固有表現ラベル体系を説明し、それらに準拠した日本語固有表現抽出の公開データセットを紹介する。さらに続いて、自前でデータセットを作成する際に有用なライブラリやtips、アノテーション作成ツールを紹介する。

固有表現タグ形式

どのフレーズ(文字・単語列)が固有表現にあたるかという教師ラベル情報を表現する形式として、BIOタグ・BILUO(=BIOES, BMEWO)タグという形式が用いられることが多い。この形式では各トークン(≒単語や文字)ごとに固有表現ラベルを予測させるタスクを想定している。

例えばBIOタグ形式は、代表的なNER Shared TaskであるCoNLL-2003のデータセットで採用されている(CoNLL-2003形式ではPOS/名詞句チャンキング/NERの3タスクの教師ラベルが並置されていることに注意)。

https://www.clips.uantwerpen.be/conll2003/ner/

固有表現ラベルPERSON, COMPANY, TIMEをBIO/BILUOタグで記述する例:

トーク BIO BILUO
昨日 B-TIME U-TIME
山田 B-PERSON B-PERSON
太郎 I-PERSON L-PERSON
O O
MNTSQ B-COMPANY B-COMPANY
( I-COMPANY I-COMPANY
モンテスキュー I-COMPANY I-COMPANY
) I-COMPANY I-COMPANY
株式会社 I-COMPANY L-COMPANY
O O
行っ O O
O O
O O

固有表現ラベルの体系

人名や企業名といった固有表現のカテゴリ全体の定義体系をどう策定するかについては、伝統的に固有表現抽出の研究会議において議論されてきた。よく引用される代表的な会議としては、英語だと Message Understanding Conference(MUC), 日本語だと Information Retrieval and Extraction Exercise(IREX) がよく知られている。

これらから派生して、一般ドメインの固有表現ラベルを細分類化したり、化学(BioCreative IV CHEMDNER)や医療(BioCreative V CDR)などのドメイン特化のラベル体系が提唱されるなど、様々なラベル体系が定義されてきている。日本語の一般ドメイン固有表現を細分類化する研究としては、関根の拡張固有表現階層(Extended Named Entity; ENE*1 )が代表的である。

日本語NERで参照されるラベル体系は長らくIREXおよびENEであったが、近年普及してきたモデル同梱のNLPライブラリであるspaCyの影響を主として、OntoNotes5.0コーパスのラベル体系が参照されることも出てきた。日本語NERの公開データセットであるUD Japanese GSDでは、日本語向けに改変されたOntoNotes5.0ラベル体系が採用されている:

https://www.anlp.jp/proceedings/annual_meeting/2020/pdf_dir/P1-34.pdf

 

商用利用可能な日本語NERデータセット

商用利用可能*2なNERモデルを構築する際に、元となるテキストの著作権が問題になる。日本語の信頼できるNERアノテーション済みデータセットとしては以下が代表的である。

データセット コーパス 固有表現ラベル体系 利用形態
UD Japanese GSD wikipedia 日本語向けにOntoNotes5からENEに対応付けられた体系 web公開
KWDLC Webからクローリングしてきた文書本文の先頭3文 IREX web公開
GSK2014-A BCCWJ 関根の拡張固有表現(ENE)階層 有料・申請後DVDにて受領

UD_Japanese-GSD

KWDLC - KUROHASHI-CHU-MURAWAKI LAB

GSK2014-A 拡張固有表現タグ付きコーパス | GSK

有償版 (BCCWJ-DVD)

 

(追記)日本語NER向けにOntoNotes5.0->ENEへの対応付けが施されたデータはMegagon Labs様にて管理されており、以下にて公開されている(Matsuda (@hmtd223) 様、情報提供ありがとうございました!)

https://github.com/megagonlabs/UD_Japanese-GSD/releases/tag/v2.6-NE

論文内でも解説されている、OntoNotes5->ENE の対応表は以下で公開されている:

https://github.com/megagonlabs/UD_Japanese-GSD/blob/master/ene_mapping.xlsx 

アノテーションデータ処理

上記のようなデータセットはそれぞれ個別のデータ記述方式で公開されており、所望のスパンデータやBIOデータ(CoNLL2003-likeなフォーマット)を抽出するまでひと手間かかる。データセット特有のフォーマットの問題はひとまず置いといて、一般論としてアノテーションデータの持ち方にも良し悪しがあるので、ここではこの点の整理を試みたい。

NERにおけるアノテーション記録形式

まず、固有表現抽出ではアノテーション情報の保持の仕方に大きく2種類のやり方がある。

「MNTSQ株式会社(以下、乙とする)」 という文字列に対するアノテーションとして、

形式 値の例 解説
文字列スパン [(0, 9), "COMPANY"] エンティティ出現位置とラベルを保持
名称リスト [("MNTSQ株式会社", "COMPANY")] エンティティ名称とラベルの集合として保持

この整理については、Amazon Comprehend の custom entity recognizer の項に記述がある。

文字列スパン形式は、情報ロスの無い正確性にメリットがあるが、このデータを効率的に作成するには後述するNERアノテーションツールを使う必要がある。また、抽出元のテキスト文字列に対して長さが変わるような加工をしてはならない制約が付いて前処理などを施しづらいなど、データの管理により気を払う必要がある。

名称リスト形式は、エンティティ名称あたり1ラベルであり、正確な出現位置の情報が失われるため、同一名称エンティティが複数箇所に出現した際に該当するエンティティがどれかという情報が復元できない。しかし、スプレッドシートなどでの記録が容易な点、人間に読みやすい点、文字列の加工に対して曖昧マッチで復元できる場合もある点などから採用されることも多い。パターン辞書エントリのマッチングから決め打ちでNER教師データを作成するdistant supervisionのアプローチでは、名称リスト形式の制約がそのまま当てはまる。

いずれにしても、実際に学習に使う段階ではスパン形式に変換する必要がある点には注意する。名称リストからテキスト内のスパン情報を再構成する作業は実用上頻繁に起こるため、その用途に有用なライブラリを後ほど紹介する。

その前に、スパン形式で記録するアノテーション作業を行う上で有用なツールを紹介する。

NERアノテーション作成作業の効率化

文書分類のような1テキストに1ラベルをつけるようなタスクはスプレッドシートでの作業で間に合うことが多い。実際、Googleスプレッドシートなどのオンライン編集サービスを用いることはグループワークを円滑にするなどのメリットがある。

しかし、NERの教師データ作成をスプレッドシートでやろうとする場合、せいぜい名称リスト方式を取らないとアノテーション作業が困難である(もちろん、スプレッドシートで名称リスト形式の抽出をやる場合でも、周辺文字列を同時に保持するなどの妥協の仕方はあり得る)。このような固有表現のスパン記録作業を円滑に行うためのOSSSaaSが開発・提供されている。

フリーのOSSとしてはdoccanoがあり、以下の特徴がある:

doccanoでは1アップロードごとに1MBまでという上限があり、ファイル分割を要することがあるなどの制限があるものの、エンジニアであれば容易に環境構築ができ、把握すべき項目も少ないため、まず試してみたい場合におすすめできる。

https://github.com/doccano/doccano

このようなNERアノテーション上のニーズがツールでどう解消されるかについては有料NERアノテーションSaaSであるLightTagのデモ記事にも詳しく説明されている:

https://www.lighttag.io/help/en/articles/4325761-annotating-entities

 

(以下、やや脱線)

少しアノテーション効率化の研究を調べたことがある人にとっては、能動学習のサポートが欲しくなるかもしれない。能動学習(特にuncertainty samplingという手法)とは、モデルが出力するスコアのうち自信の無いデータに対して優先的にラベルをつけることで、より少ない教師データで高い性能が出るという枠組みを指す

Prodigy*3  というSaaSでは能動学習がサポートされているが、LightTag*4というSaaSでは以下の記事で議論されている論点から現時点ではサポート外と表明されている

https://lighttag.io/blog/active-learning-optimization-is-not-imporvement/

議論の大筋を抜粋・意訳すると

  • uncertainty samplingによる能動学習(≒モデルスコアによる学習データ選択)の成否はモデルがデータ境界を理解できるかに依存
  • しかし、実際に構築されるデータは、特定モデルの表現力の限界に依存したバイアスを孕んでしまう恐れがある 
  • 能動学習の本懐であるアノテーションが高コストである課題点に対して、特定モデルのバイアスにさらされた学習データを構築することは長い目で見て投資対効果が悪い(そのモデルに効いても、データで本来解きたい課題全体に対して有効なアノテーション資産が得られるかは微妙)
  • ただし、uncertainty sampling以外の手法を視野に入れたり、不均衡データに対するデータ探索の手法としては有効な場合もある

アノテーションシステムへ能動学習を導入することを検討したくなることがあるが、個人的な意見としては、純粋にアノテーション効率化の用途というよりも、モデルの挙動把握(probing)を助けるエラー分析のいち手段・追加のデータ収集のための指針の手がかりとするような用途の方が向いているのではないかと感じていたので、この議論は大いに参考になった。

NERで頻出のデータ加工処理

NERでは処理の過程で、

  「文字列+スパン」→「トークン+BIOタグ」→「チャンク+固有表現ラベル」

のような変換を経ることが多々あるが、これらの相互変換性(可逆性)を担保するデータハンドルを心がけないと後悔することがしばしばある。

「文字列+スパン」情報を基点にデータを加工・保持するのが基本だが、CoNLL2003フォーマットのようなトークンごとにBIOタグが振られたデータを作るには形態素解析を経る場合があり、実際の抽出結果を用いる際にはトークン列をタグに沿って結合したチャンクデータに変換することがある。

そしてエラー分析の段階において、観察したチャンクのデータから変換元となるBIOタグやスパンデータを頼りに周辺文字列を確認したい、という必要が生じた場合に変換前のデータ形式に戻れない(可逆性が無い)と困るのである。

 

以下、具体例で説明すると

項目
テキスト文字列 "MNTSQ株式会社(以下、乙とする)。契約当事者: MNTSQ株式会社"
文字列スパン [(0, 9, "COMPANY"), (26, 35, "COMPANY")]
単語BIO [("MNTSQ", "B-COMPANY"), ("株式会社", "I-COMPANY"), ("(", "O"), ..., (":", "O"), ("MNTSQ", "B-COMPANY"), ("株式会社", "I-COMPANY")]
チャンク [ (["MNTSQ", "株式会社"], "COMPANY"), (["MNTSQ", "株式会社"], "COMPANY") ]

これをエラー分析などのために可逆的なデータとするためには、チャンク情報に文字列スパン情報を埋め込むなどの工夫が必要となる。しかし、単語BIOの段階では形態素解析を経てインデックスが単語トークン単位に変わってしまったり、形態素解析のための前処理を経て特定文字が除去されてしまう結果、文字列スパンの情報が位置ズレを起こしてしまうなどの事態が発生しがちである。

データ変換の過程で文字・単語の位置対応を慎重に保持することも可能ではあるが、後述する pytokenizations というライブラリを用いれば前処理などを経た後のトークン対応を復元することができる。似た問題はBERTなどで行われるsubwordベースのNERの際にも発生し、BERT(Transformers)ベースのNERを実現するライブラリ camphr*5 ではこのライブラリを用いてトークン対応復元処理が記述されている。

 

※ NERのような系列抽出のタスクをトークン単位のBIOタグ予測ではなく、スパン形式を直に予測する流儀のモデリングも研究されている。特に機械読解タスクのSQuADはスパンを出力するモデルとして知られているが、関係抽出タスクの一つである意味役割付与(SRL)のタスクなどでもスパン予測の研究が近年見られる。スパンを直に予測する際には当記事で述べた変換処理の一部は不要となるかもしれない。)

NERアノテーションデータ加工に有用なライブラリ

アノテーション名称リストからテキスト内のスパン情報を再構成したり、前処理などを経たテキスト内のトークン対応位置を復元したりするのに便利なライブラリを紹介する。

ライブラリ名 用途
pyahocorasick 高速な厳密マッチ/スパン抽出
regex 柔軟な曖昧スパン抽出
pytokenizations / pytextspan トークン列・文字列どうしのアラインメント

https://pypi.org/project/pyahocorasick/

https://pypi.org/project/regex/

https://pypi.org/project/pytokenizations/

https://pypi.org/project/pytextspan/


pyahocorasick

文字列マッチングアルゴリズムであるAho–Corasickアルゴリズムを計算するライブラリ。オートマトンの事前計算によって厳密マッチおよびスパン抽出を高速に行うことができる。以下、スパン抽出における使用例:

from ahocorasick import Automaton

A=Automaton()
# 
A.add_word("MNTSQ株式会社",("COMPANY","mntsq株式会社"))

A.make_automaton()

text = "MNTSQ株式会社(以下、「乙」とする)"
for item in A.iter(text):
    end = item[0] + 1
    start = end - len(item[1][1])
    print(item, text[start:end]) 
(8, ('COMPANY', 'mntsq株式会社')) MNTSQ株式会社
regex

python標準ライブラリreの拡張。誤り数を許容した正規表現マッチが利用できたりする点で便利。他にも、漢字やひらがななど文字種指定のマッチングができるなど、unicodeの処理が便利になるご利益もある。

上記のpyahocorasick相当の処理:

import regex as re

text = "MNTSQ株式会社(以下、「乙」とする)"
annotation = "MNTSQ株式会社"

for m in re.finditer(annotation, text):
    start, end = m.span()
    print(text[start:end])
MNTSQ株式会社

 

曖昧マッチもできる。詳細はPyPyページ内マニュアルの Approximate “fuzzy” matching 項を参照。: 

import regex as re

text = "MNTSQ 株式会社(以下、「乙」とする)"
annotation = "MNTSQ株式会社"
# 空白文字の挿入を1文字許容したマッチ
fuzzy_pattern = re.compile("(?:%s){i<=1:\s}" % (re.escape(annotation)))

for m in fuzzy_pattern.finditer(text):
    start, end = m.span()
    print(text[start:end])
MNTSQ 株式会社
pytokenizations / pytextspan

2つのトークン列・文字列のアラインメントをとることのできるライブラリ。スパンデータで抽出することができる。元となるトークン列・文字列でスパン情報を記録した後に、前処理などで加工したトークン列・文字列に対して対応するスパンを再構成するといった使い方ができる。他にも、異なる形態素解析器の解析結果の比較、wordとsubwordの対応関係の再構成など系列間対応を取る比較に幅広く使うことができる。

列比較のアルゴリズムとしてはdiffコマンドで使用されるMyersのアルゴリズムを使用して計算されている。また実装内ではNFKDのunicode正規化を行っているため、その範囲で文字が同一視されることに注意する。

前処理のような系統的な加工を経る際にはこのツールが適しているが、一方でOCR誤りのようなエラーが変則的なケースに対しては、前述のregexの許容編集数や誤り許容文字を調整することで曖昧マッチするのが適していることもある。

以下に公式の使用例を拡張した例を示す:

pytokenizations demo (https://github.com/tamuhey/…

 

以上、固有表現抽出の教師データにまつわる論点や処理のtipsについて経験上つまづいた点を中心に概説した。この記事はMNTSQ株式会社の業務時間内に書かれた。

MNTSQ株式会社では契約書の自然言語処理による解析に協力いただける心強い仲間を募集しています。

www.wantedly.com