Opt Technologies Magazine

オプトテクノロジーズ 公式Webマガジン

2年間を振り返った、自然言語処理の難しさ

alt

2年間携わってきたウエブサイトチェックの自動化プロジェクトと自然言語処理の難しさについて、記述させていただきました。

前書き

人間が行っていたウェブサイトの細かいチェックを自動化することを目的にしたプロジェクトに、クロスフィニティ株式会社にて2年間ほど携わっていました。今回はそのプロジェクトについてとりあげますが諸般の事情により、そのプロジェクトの詳細は公開することはできません。そのため技術やサービスの解説ではなく直面した課題と反省点について、アナロジーや例え話を交えてお送りします。

ご了承くださいませ(笑)!

あいさつと自己紹介

こんにちは、Melvin Charles DYです。*1

つい最近まではクロスフィニティ株式会社に所属していましたが、会社間の吸収合併により、現在はOpt TechnologiesのマーケティングR&D部(通称:MRD)に所属しています。仕事の内容は、主に自然言語処理系の開発です。

数年間、コンテンツライター(英語で)をしていたこともありますが、エンジニアとしての職務は色々やってきました。Windowsの顧客情報管理パッケージソフトや顔認識を用いたスマホアプリ、実験的な通話アプリの開発もしてきました。

学部時代には自然言語処理に関わる研究はやっていましたが、それからはかなりのブランクがありました。大した技術力はありませんでしたが、とあるきっかけによって自然言語処理に携わりたいという願望を軸にして転職活動をしていました。

クロスフィニティに中途入社したのは、2017年の10月でした。即戦力になれる機械学習の技術者しか雇わない主流のなかで、チャンスをくれたのはクロスフィニティだったので、とても感謝しています。

2020年元旦から、Opt Technologiesへの転籍することになりました。これからはオプトの一員として頑張ります。

「自然言語処理」と「機械学習」

さて、自己紹介のセクションで、「自然言語処理」と「機械学習」を使い分けたことに違和感を覚えた方もいるかもしれません。

確かに、機械学習(特に深層学習)を用いた自然言語処理は最近の主流です。ですが、機械学習を使うのには膨大な量のデータが必要になります。もちろん、少量のデータであっても学習を試みることはできますが、的確な出力は期待しないほうが賢明だと思います。

少ないデータの中に対象にしている問題におけるパターンが全部含まれている確率は非常に低いです。加えて、ある程度のデータで学習して精度評価において高いスコアができたとしても、学習用データセットにはなかった入力で偽陰性か偽陽性が出るのはおかしくはありません。

では、そもそもデータがそろっていなければ高度な機械学習を行えないから、自然言語処理自体もできないでしょうか?いいえ、機械学習を行わなくても自然言語処理はできます。

自然言語処理においていろんなステップがあります。形態素解析と言うステップで、テキストを分解してもっと処理やすい「トークン」にします。このステップを挟むことによって、自然言語処理における「表記ゆれ」の問題を緩和することができます。

例:「すし」、「寿司」、「鮨」、「スシ」は全部同じものを指しているので、[寿司; 名詞; 体表表記:すし]と言うトークンにしたら、後のステップでは各々の書き方を気にせず「寿司」をターゲットすれば網羅はできます。

そして、機械学習で作った「分類器」が使えない場合でも、正規表現は使うことができます。対象問題の条件によっては正規表現で十分かもしれません。正規表現で作った分類器をシステムに組み込めば、「機械学習」を使わなくても、「自然言語処理」はできます。

とはいえ、数多な出現パターンがある問題に対しては正規表現ではカバーしきれないかもしれません。では、人間のプログラマーが指定しきれないほど複雑な問題だけに機械学習を使えば、と思う人もいると思います。ですが、機械学習をするのには大量かつ良質なデータがなければいけません… 

ある意味、「卵が先か、鶏が先か」の問題です。

試行錯誤

プロジェクトに参加した当初、機械学習がメインになると思っていました。ですが、対象問題の条件を見たら、いくつかの問題には機械学習が必要ないことが判明しました。その対象問題の一つを、詳細を書き換えて共有します。

例えばなんですが、とあるピザ屋が電話番号を変更したので、外部サイトでは電話番号が正しく記載されているかどうかの確認が対象問題だとしましょう。正しく記載されていれば問題ありませんが、間違っていた場合や、まだ新しい番号に更新されていない場合、その情報が載っているサイトの管理人に修正依頼をしないといけません。

古い番号の検知は割と簡単です。電話番号の書き方はいくつかありますがバリエーションはそこまで多くはないはずです。新しい番号の検知も同様です。しかし、間違っている電話番号はどうやって検知すればいいでしょうか。*2 

数字と何種類かの信号(ハイフン、カッコ、など)のx個連続で大丈夫だと思ったら、ピザ屋各社の一覧ページで違う店の情報で偽陽性が起きたり、電話番号の一文字が欠けてから偽陰性になったり、文章中のURLに反応したりします。「○○ピザ屋の電話番号は:<空白>」と言うケースも考えられます。

上記のように問題の要件分析をしましたたが、単純な正規表現だけでは実装ニーズに答えれる仕組みができなさそうでしたので、正規表現の複合体をベースにした分類器を開発しました。この仕組みの概要は、次のセクションで説明します。機械学習が流行っているこの時代には原始的なソリューションにも見えますが、自動車だって単純機械の複合体であります。

加えて、正規表現は人間には読めるし、直接に調整でるので、早い対応ができるというメリットがあります。

例えば、検知器を実装した後、上記のピザ屋が再び電話番号を更新したとしましょう。機械学習を使っていた場合、大変な調整が必要になります。電話番号が更新されたばかりなので正例も負例もまだありません。過去の正例を全部負例にすればいいと思ったら、偽陰性につながる変更もしてしまう可能性はあります。結局、新しい正例・負例のデータセットを作るか、正例の作成をする上に過去の正例を一つずつ確認しながら負例に転換するか、どれもコストがかかる作業です。場合によっては、このデータセットを学習した分類器の精度が前に比べて落ちるかもしれません。

しかし、正規表現で実装した場合、過去の正しい番号をNGルールにして新しい電話番号を正解ルールとして登録すれば、すぐにデプロイはできます。もちろん、テストはしないといけませんので、過去の正例を一つずつ負例に転換する作業は発生します。ただし、機械学習で実装した場合との大きな違いは2つあります:

  • 瞬時の修正とデプロイ
  • 偽陰性・偽陽性の追跡のしやすさ *3

正規表現で造った水切りボウル

単体の正規表現では「あり・なし」の情報しか表せません。捕獲したいパターンにつき、一つの正規表現を定義するのはもちろんできますが、想定外のパターンを逃してしまう可能性があります。

検知が関わればどんな問題でも、偽陰性と偽陽性の価値のバランスを考えないといけません。もちろん、検知器(または分類器)の偽陰性率も偽陽性率もできるだけゼロに近くなるまで改善すべきですが、開発の際に、偽陽性と偽陰性のどれを優先的に抑えるのかを決める必要があります。

このプロジェクトの場合、「偽陽性がちょっと多くても、偽陰性は許せない」というスタンスでした。それから生まれた実装の方針は:

  • 大体のインプットを通しながら、気になるテキストを一回捕獲します。
  • セーフなものは記録してから流します。
  • 明らかにダメなもの、または微妙なものは、NGフラグを付けます。

技術の細かい話をすると結構長くなってしまうため、今回は概要だけを紹介します。

イメージとして、できるだけ広い範囲をカバーする正規表現で様々なテキストに陽性反応して受け止める「鉄板のボウル」を作ります。そうしてから、正規表現パターンで関係ないテキストやセーフと判断できるものに対する陽性反応を緩和して流します。さっきの「鉄板のボウル」に「穴」を空けたような感じです。残るのは、間違っている掲載や疑わしいテキストです。

捕獲用の正規表現も反応を緩和する正規表現も、試行錯誤しながら徐々に追加していくことになりました。頑張っていろんなケースをあらかじめに対応しようと思ったら、次回の実行の結果には想像もしていなかったケースが出てました。このように、手動のチューニングを毎月していました。

機械学習をやってみたかった

手動チューニングの流砂になってしまう可能性は、当初から分っていて、恐れていました。せめて、いくつかの項目だけでも機械学習で実装できれば、その分だけでも後程のメンテナンスが軽減できる、という思いを込めて機械学習を試してみました。

30個もあった項目の中から2個ほどが、特定の数字や固有名詞に依存せずに「意味合い」による監視対象要素を持っていました。もちろん、正規表現系のソリューションでも対処できますが、前述のとおり少しでも自動化したかったので、挑戦しました。

データが少なくて深層学習は無理そうだったので、スパムメール対策にもよく使われていたBayesian filteringを実装してみました。学習させて、テストでは95%以上の正解率を出せるようになって、「いい感じじゃないか」と思いきや、その次の月の入力コーパスを食わせたら50%にまでパフォーマンスが落ちて「なんでやねん!」ということになりました。

各項目の許容範囲はとても狭く、95%から99.5%までに練り上げるためには、まだまだ道の途中だとわかっていましたが、リアルなデータで50%になるのはさすがにちょっと挫折感を味わいました。

ひとまず、一回目はうまくいかなくても、強化学習の理論で毎月のデータを蓄積してコーパス化して再び学習させる、というサイクルを検討しました。しかし、プロジェクトの進歩的にも、自分の目標的にも、この1~2項目にそこまで時間は割けませんでした。結局、正規表現系のソリューションに切り替えてみましたが、プロジェクト全体の方針の変更でこの項目のチューニングは保留することになりました。

The imponderable size of real numbers

機械学習の話のついでに、持っている疑問の一つについて述べたいのです。

このセクションのサブタイトルは 「the imponderable size of real numbers」、すなわち「実数の計り知れない規模」です。

実数は、ある意味、幻です。日常的な視点からすれば、「18」と「18.0」と「18.0000000000001」の違いはなく、全部「17と19の間にある数字である18」と、整数をベースで認識されるでしょう。しかし、分野によっては0.0000000000001の差は重要です。その分野には詳しくない人にとって、あってもなくてもなんとも思わない値ですが、玄人にとっては全宇宙のモデルの礎だったりします。

そして、その「幻」の上に、社会の恣意的なルールを設けるのです。「18」と「18.0」と「18.0000000000001」の文字列としての違いがある上、「記載は少数第n位までではないとダメ」や「逆算したら実際の値は18.000000000001なので、18.0000000000001という掲載はしてはならない」など、ルールはあったりします。こういうルールがあるから、数字の「次元」が多くなり、互換性が利かなくなります。

この複雑さと延々に広がれる次元は、機械学習のおいてどうやって表現・模擬・学習されるでしょうか。単純に文字列として扱ったら、数字の整数部分ごとが「次元」になり、小数部の各値×各書き方(.001 ≠ .00100 ≠ 1.0x10^-3…)の組み合わせごとが「パラメータ」になります。

全宇宙の量子を数えるのには、全宇宙の量子の数自体を含んだうえ、全宇宙の量子の「数」を含める媒体が必要になると言われています。同様、抽象化するステップを入れなければ、全数値×全ての書き方をモデルするのには、対照する範囲の累乗した数のパラメーターが必要になります。

「18」と「18.0」の間に広がるもう一つの宇宙は、どうすれば機械に「理解」させられるのでしょうか。

…哲学めいた話を一回ここで切りましょうか。

Wait / walk

このプロジェクトの中の何項目かには、数値のチェックが必須でしたが、その上に複雑なロジックがありました。例えば、「18%」は小数第1位まで書いていないので判断がNGになりますが、ページのどこかに「18.0%」(正しい記載例)があれば、「少数位の記載」でNGだったものが許容されて、ページ全体の判断がOKになります。

このような高度な推論は機械学習にも厳しいと思います。データが足りない状況ではなおさらです。
――では、正規表現系のソリューションで対応するべきでしょうか…?
――でも、数か月の間にデータを蓄積すれば、使えるレベルの分類器ができるかもしれない…
――だが、使える精度まで学習させられなかったら、「確実に」実装できる正規表現系ソリューションに費やせたかもしれない数か月間が「無駄」になってしまいそう…

このような実装と待機のジレンマは、wait/walk dilemma の一つのケースです。そのwait/walk dilemma (待つか歩くかのジレンマ)*4 はもともとバス停における問題を基づいた思考実験です。

目的地までの距離はそこまで遠くないとしましょう。バス停につきましたが、すぐに乗れるバスがありません。さて、バスを待つか、歩いていくか、どちらのほうが早いでしょうか。

上記の原型からの延長線で、恒星飛行に対する wait calculation もあります。同様に、すぐに宇宙船を作るのか、技術(特に推進のテクノロジー)の進歩の様子を見るのか、対照的かつある程度定量的に比較できる2択問題であります。極端に言えば、SF作にもよく使われるシチュエーションである lightspeed leapfrog (光速馬飛び)は考えられます。そのシチュエーションの概要は、近未来に造られた宇宙船が飛行していた間に、新しい科学技術が発見されて、その新技術で搭載された宇宙船が先発した宇宙船を「馬飛び」のように先を越して目的地に着きます。

この思考実験に、機械学習と正規表現系ソリューションを喩えましょう。バスの役は、「自動で楽」だが「利用できるまで時間がかかる」機械学習ソリューションです。「すぐに利用できる」が、「地道で辛い」のは、まさに正規表現系ソリューションです。このジレンマに迫られた自分は、「確実さ」を選んで主に正規表現で色々実装しましたが、機械学習の方で粘ったら現状よりいい結果を出せたかしらと思うときはあります。

あれ、また哲学的な話になってしまいました。

全体的な反省点

前回のプロジェクトは、2年間ほど携わりました。その間を経て、色々勉強になりました。

まず、対象としていた問題の細かい定義はもっと早い段階でやるべきでした。「常識」と「分野知識」の存在を痛感しました。一見簡単そうに見える項目でも、人間が無意識に関係あるものと関係ないものを分別した結果、簡単に見えます。しかし、機械学習や正規表現いずれも「常識」や「分野知識」を持ってないので、人間の行動を再現するのには対象パターンだけではなく、コンテクストも取り入れないといけません。そして、コンテクストのスケール(対象パターンの直近パラグラフかドキュメント単位か、など)も考えなくてはなりません。

正規表現系のソリューションでは直接チューニングができるので、判断が間違った結果の原因は突き止められますし、手動でチューニングをすれば精度が上がります。その分、精度ばかりを追うようになって、大胆な変更(機械学習に転換するとか)のチャンスを逃してしまったかもしれません。

「チューニングすればいい」という思考が固まるにつれて、毎月の作業フローも固まってしまいました。効率の面で、ある意味それは望ましいことかもしれませんが、作業の量とペースでほとんどの時間が占められて、他の方法を探求する時間がなくなりました。

機械学習は、パターンの学習を自動化したものに過ぎません。魔法ではありません。はじめから理解していましたが、このプロジェクトでは思ったように精度が上がらず、挫折しました。

機械学習においては、アルゴリズムなどよりデータセットの量と質が必要です。この「質」は、サンプルのキレイさや各アノテーションが埋まっているかどうかを指しているだけではなく、付与されたアノテーションがそもそも問題の細かいニュアンスまで表現できているかどうかも疑うべきです。最悪、自らで必要なアノテーションを付けることになります。リソースも覚悟も試されます!

上記の反省点や学んだことを、今後のプロジェクト、いやむしろ、キャリアに活用していきます。

まとめ

この記事は、苦労話より、直面してきた問題とそれから得た知見の共有として見てほしいのです。自然言語処理、特に機械学習を用いたソリューションを作りたい方たちに伝えたい、現場調査の記録のようなものです。

一言で言うなら、すべての問題が機械学習で解決できるとは限りません。求められている精度が100%に近いほど、適合性が低下するかもしれません。ハイブリッドソリューションは検討するべきです。

ちょっと長い記事になりましたが、読んでくれてありがとうございました! 


Opt Technologiesに興味のある方は、こちらから「カジュアル面談希望」と添えてご応募ください!

*1:苗字は「ディ」で、下の名前は「メルヴィン チャールス」。普段は「メルヴィン」か「メルビン」と呼んでもらっています。

*2:Hamming Distanceの応用で何とかできるのではないかと思います。前のプロジェクトでは、似た問題の出現ケース数はそもそも少なかったので、そこまでのニーズがなくて、このアイディアは保留にしました。

*3:機械学習はいまだにブラックボックスに等しいものです

*4:https://en.wikipedia.org/wiki/Wait/walk_dilemma