データナード

機械学習と自然言語処理についての備忘録 (旧ナード戦隊データマン)

自然言語処理でできること

自然言語処理でできることは何か」という問いは有用性の観点から考えると自然に思えます。自然言語処理を研究して論文で発表したいのではなく、それを現実の機能要件1 に対して利用したい人もいます。ここでは、自然言語処理でできることについて、有用性の観点から整理することを試みます。

TL;DR

  • 自然言語処理でできることには、一定以上の精度が得られているタスクが含まれる。
  • 自然言語処理のタスクをNLP-progressやPapers with Codeなどのサイトで調べれば、何ができるか参考にできる。
  • githubかkaggleでnlp関連のキーワードやタグでコードを調べるのもおすすめ。

自然言語処理とは何か

自然言語処理とは、人間の言語 (自然言語) をコンピュータによって扱う分野です。

自然言語処理の定義はバリエーションがあります。上記の定義の他に、以下を追加するものもあります:

  • 人工知能, 計算言語学, 情報工学の分野の一つである。
  • 自然言語をコンピュータが理解するための分野である。
  • 自然言語のデータを、処理したり、分析するためのプログラムをどう作るかについての分野である。

この記事の中では、最初に挙げた定義に何かを付け加えることはしません。

処理とは何か

コンピュータ上の処理は、少なくとも2つの種類があります:

  • ハードウェアへの命令。
  • データを操作するための処理。

自然言語処理では、概ねデータを操作するための処理を考えます。

基本的なデータの処理は、以下の3つから成ります:

  • 入力
  • 処理
  • 出力

f:id:mathgeekjp:20200424202007j:plain

コンピュータ上での何らかの処理を考えるということは、「ある入力に対して、目的の出力を得るためには、どんな処理(または変換)をすればよいか」を考えることです。

実際には、処理とは複数の処理のまとまりなので、データフローダイアグラムのように階層的に見ることができます。

f:id:mathgeekjp:20200424202036j:plain

ユーザーから見た階層は最も抽象的なレベルですが、エンジニアから見た階層は具体的になっていきます。

入力・出力・処理の3つ以外にも考慮することがあります。

  • 制約条件
  • 評価方法

制約条件とは、その処理に対する制約です。例えば、以下のようなものがあります:

  • アルゴリズム内の変数の取りうる範囲などの制約。
  • ハードウェア上の制約 (メモリ, ストレージ, CPU等)
  • パフォーマンス上の制約 (実行時間, 利用するメモリの量, 等)
  • 処理内部で利用可能なアルゴリズム・ライブラリ等。
  • 利用可能なデータの制約。

一方、評価方法とは、どのようにしてその処理(アルゴリズム)を評価するかです:

  • アルゴリズムが正しい処理をしているということをどう評価するのか。
  • パフォーマンスや精度など、どんなmetricsに対して評価するのか。
  • 評価のために利用できるデータは何か。

「どんな入力に対して、どんな出力を得ることを想定するか。そこに存在する制約条件と評価方法は何か」について定義したものは「タスク」と呼ばれることがあります。

例えば「プレーンテキストを入力すると、文字順で行がソートされたものを出力する。評価方法は、テストデータの正解の順序に一致することと、テストデータにおけるソートの実行時間が0.1秒以下であること」のようになります。

正式なタスクの場合、テストデータの正解ラベルは開発者に公開しないほうが良い場合が多いです。それを公開すると、テストデータだけにしか適用できないアルゴリズムが出来上がる可能性があります。

自然言語処理のタスクとは

自然言語処理でも「タスク」という言葉があります。

自然言語処理における入力や出力には「自然言語」が使われます。これ自体を「自然言語処理」の定義として考えると、産業界では有用な場合があります。考えたいのは、自然言語を処理する必要のある要件にどう対処するかです。

入力, 出力のペアとして以下の例があります:

  • コーパスを入力すると、モデルを生成。(e.g. 教師なし学習)
  • 特徴量とラベルからなる行列を入力すると、モデルを生成。(e.g. 教師あり学習)
  • クエリを入力すると、ドキュメントIDを取得。(e.g. learning to rank)
  • 文を入力すると、トークン列へ変換。(e.g. BPE, 形態素解析)
  • トークン列を入力すると、認識されたエンティティIDとその位置を取得。(エンティティリンキング)
  • 音声を入力すると、音声による返答を出力。(e.g. Google Assistant)

実用的な意味では、タスクを定義してそれを解くことを目的にすることができます。

すでに存在する自然言語処理の公開タスク(あるいはそれに準じたライブラリなど)を利用することによって、機能要件へスムーズに対処できる場合があります。

機能要件の入出力が明確なほど、タスクが見つけやすくなります。そして、その入出力に対応したタスクがすでに存在するかを確認することによって、一から解決策を考えるよりも楽になります。

あるタスクを解くために部分タスクを解く必要が出てくる場合があります。例えば「音声を入力すると、音声による返答を出力する」というタスクは以下のように分割されるかもしれません:

f:id:mathgeekjp:20200423110716j:plain
wav2wav

この場合、音声から直接音声へ変換するための"end2end"な方法を考えることもできますが、困難さなどの理由から部分タスクへ分解されることもあります。部分タスクも同様にすでに公開タスクやライブラリとして存在していることがあります。公開されている解決策について調査・検証することをおすすめします。

公開されているタスクには以下が含まれていることがあります:

  • タスク名
  • タスクの説明
  • 入出力
  • 制約条件
  • 利用可能なデータセット
  • 評価方法
  • ベースライン

タスクに対する解決策は提示された評価方法によって比較されます。ただし実用面では精度の他にも、パフォーマンスの問題、再現可能なコードが公開されているか否か、解決策として提示されている手法がどんなものなのか、などについても考慮することがあります。

自然言語処理の公開タスクと解決策について調べたい場合、以下のようなサイトを使うことができます:

NLP-progressは自然言語処理のタスクを検索できます。タスクの説明やデータセット、これまでに公開された手法の論文などが含まれています。

Papers with Codeは機械学習のタスクを検索できますが、自然言語処理機械学習を使うことが多いため、自然言語処理のタスクを見つけることもできます。

タスクを詳しく調べる

タスクについて詳しく調べることによって、自然言語処理によって現在何ができるのかについての一部を知ることができます。

例えば、機能要件として以下のようなものがあるとします:

  • 検索機能で、ユーザが検索したクエリ内から重要な名詞を見つけて、その名詞に紐づく情報を検索結果に表示したい。
  • 例えば、「イチロー」というクエリが投げられたら、イチローの所属チームや近しい人物を表示したい。

この要件の場合、入力は「クエリ」で出力は「イチローのID」ということになります。

イチローのIDとは、なんらかのシステム内における「イチロー」を示すエンティティIDのことです。エンティティIDがわかれば、エンティティに紐づく情報も取得できます。このようなシステムは「知識ベース」とも呼ばれます。知識ベースの例はWikipediaです。

この要件に近い自然言語処理のタスクは「エンティティリンキング」というものがあることがわかります。

NLP-progressのentity-linkingの情報: http://nlpprogress.com/english/entity_linking.html

例えば、エンティティリンキングには少なくとも2つのタスクが含まれることがわかります:

  • テキスト内のメンションを抽出する。
  • エンティティの曖昧性を解消する。

エンティティの曖昧性解消とは、「パイソン」のようなメンション(テキスト内の抽出対象の語) があった場合、「プログラミング言語python」「モンティパイソン」「コルトパイソン」などの中から、文脈に適したものを選ぶことです。

タスクに着手する際には、使えるデータセットと、それに対応した論文・コードを探すことができます。NLP-progress内ではすでにそれらがまとめてあります。

ただし、公開されたデータセットを使って即座に機能要件に対応できるとは限りません。自前のシステムには自前のデータが必要になることがあるため、データを必要とするアルゴリズムの場合にはデータを集めることも考慮する必要があります。

タスクが一致しない場合

機能要件上のタスクが、自然言語処理におけるタスクと一致しない場合はどうすれば良いでしょうか。

NLP-progressで見つけられないようなタスクや手法はたくさんあるため、ACLやAAAI、あるいはGoogle AIなどから論文を探すこともあります。

ソースコードを読めるなら、kaggleやgithub自然言語処理のコードを探すことは現実的な方法です。NLP-progressをはるかに超える情報量があります。どちらもタグによる検索をサポートしています。

開発者の知識の不足によってタスクを見つけられない場合もあります。つまり、現実の機能要件と一致しているタスクが存在するにもかかわらず、それを認識できないことがあります。

機能要件が自然言語処理上のどのタスクとも一致しないと思った場合、私は以下のような点を考慮することがあります:

  • それは本当に自然言語処理を必要とする要件か。
  • 要件と自然言語処理上のタスクを理解しているか。
  • 要件は明確に定義されているか。入出力や制約条件がわかっているか。
  • その要件は世界のどこかで実現された例が本当に存在しないのか。
  • 要件を抽象化したり、言い換えたり、単純化することによって、既知のタスクに変換できないか。
  • 要件を部分問題へ分割することができるか。
  • 品質要件として定義された精度は現実的なものか。
  • 仮に前例のない要件だったとして、その要件のためにどの程度の時間やリソースを費やせるのか。
  • そのタスクが特定の言語固有のもの (英語では一般的ではないようなタスクなど) ではないか。
  • その要件を実現するためのデータやリソースがあるのか。

単純な経験則として、「"世界で前例のない要件"という認識を持った場合、その要件や認識をちゃんと確認した方が良い」というようなものがあります。例えば、前例がないのではなく、要件の定義が曖昧だったり複雑すぎる場合があります。

自然言語処理に関する知識が増えてくると、Google検索する際により適切なキーワードで検索できることがあります。基本的に、英語で検索したほうが的確な情報が見つかりやすくなります。

Google検索テクニックは以下のようなサイトから見ることができます:

Google Search Operators: http://www.googleguide.com/advanced_operators_reference.html

検索例

sentence embedding site:arxiv.org -bert

意味: sentence embeddingをarxiv.org内から探すが、bertを含むページを除外する。

まとめ

  • 自然言語処理で何ができるかを知る手っ取り早い方法が、タスクを調べること。
  • タスクをまとめたサイト(NLP-progress等) がある。
  • 機能要件上のタスクから自然言語処理のタスクを調べるためには、入出力や制約条件を明確にすると調べやすい。
  • 自然言語処理に関して知識があるほど、適切なキーワードで調べやすい。
  • ggrks

参考


  1. ここでの機能要件は、ある目的のものを作る際に必要な機能(フィーチャー)のことです。