ノーマライズと形態素解析
Groongaで学ぶ全文検索 2016-01-29に行って来た。今日は濃かった。その分面白かった。
まずノーマライザーの話をして、その後形態素解析の話をした。
ノーマライザー
ノーマライザーはノーマライズする物。ノーマライズは、半角「カレー」と全角「カレー」、ひらがな「りんご」とかたかな「リンゴ」など、厳密には違う物を同じ物に寄せるという処理。どういう基準でノーマライズするかというのは色々あって、その色々ごとにノーマライザーの種類がある。
インデックスを作る時、インデックスのキーにノーマライズした物を選んでおくと、例えば「りんご」で検索した時に、「りんご」を含む文書と「リンゴ」を含む文書の両方を返すことができる。これがノーマライザーを使う理由。
ただ、この状況下で「リンゴ」で検索すると、インデックスのキーワードには「りんご」しかないので、何もヒットしない(「リンゴ」というキーワードはインデックスを作る時にノーマライズされて「りんご」になっているから、入っていない)。だから、検索時にクエリーの方もノーマライズする。この時にはインデックス作成時と同じノーマライザーを使わないと、キーワードの集合が変わるので、いけない。
(面白い質疑応答二つあった、後で書く。かも。)
形態素解析
形態素解析は、文などを形態素に分ける処理。形態素が何かは各自調べられたい。迂闊なことを言えない。日本語の文を構成する、意味的に分割できる一番小さな単位、とかそんな感じ。全文検索では、インデックスのキーワードをどのように選ぶかというやり方の一つとして、形態素解析器を使う(他にN-gramがあるのは以前書いた通り:日本語文書の全文検索)。
例えばクエリーの中の「りんご」と「リンゴ」を同一視するには、文字単位で見ていって、かたかなを見付ける度に全部ひらがなにしていけばいい。こういうノーマライズは文字単位で処理すればできる。が、「PC」で検索した時に「パソコン」を含む文書を返す、二つを同一視するにはこの方法では不可能。「パソコン」を見つけたら「PC」にする必要がある。この時に
- 「パソコン」が一つの単位になるように、クエリーを分割する方法(形態素に分割する方法)、「パソ」みたいに「パソコン」より細かく分割しないし、「パソコンを」みたいに他の語とくっついた形で大きな粒度で分割しない方法。
- 「パソコン」と「PC」は同じ物だ、という日本語の知識(扱うアプリケーションによる。同じ物と扱いたくないアプリケーションもあるだろう)
の知識が必要になる。
前者が形態素解析と呼ばれる処理。形態素解析器は「『パソコン』というのは名詞である」「『で』というのは助詞である」「『で』は文の最初には現れない」といった知識(辞書)を持っている。この知識を元に文を解析して、日本語としてありそうな切り方を何パターンか出す。その中の一番ありそうな物を結果として返す(それを全文検索エンジンが使う)。
ところで、どのように切るか、というのは、ドメインによって変わる。新聞で使われる言葉、ツイッターで使われる言葉、若者の言葉、年寄りの言葉……。 アプリケーションが扱うドメインが分かっているなら、一般的(?)な切り方でなく、それぞれに適した切り方ができるはずだ。この「それぞれに適した」は、それぞれ用の辞書を使うことで対応する(形態素解析器自体は変えない)。時代とともに検索結果が古びてきたようだと、辞書を新しくする必要も出てくるだろう。
辞書を新しくするということは、インデックスのキーワードの選び方が変わるということだから、その時にはインデックスを作り直す必要がある。
後者、単語(形態素)の同一視は、ノーマライズの前のクエリー展開というフェイズでやっている。そこは辞書を元にクエリーを見て、
「パソコンほしい」 OR 「PCほしい」 OR 「パソコン欲しい」 OR 「PC欲しい」
みたいなクエリーに変換して検索エンジンに投げている。
「パソコン」と「PC」を同一視するには、形態素解析の結果が欲しいところだがクエリー展開はその前なので、ここは独自に頑張ったりする。その場合は「(二重に同じ処理をすることになのるで)トークナイズノーマライズ(勉強会中に発表し、直してもらった)はしないように」といった仕様上の注意が生まれる。
今回は話題が広くて、また勉強会中に公開したいという制約とでまとめられないがこんな感じだった。あとで追記するかも知れない。