Drupalの日本語検索を改善!自然言語処理を活用したSearch API Japanese Tokenizerモジュールの紹介


こんにちは。スタジオ・ウミの大野です。この記事は、前回の「Drupalの日本語検索、ちゃんと動いてる?N-gramの課題と自然言語処理での改善策」の続きです。DrupalコアやSearch APIの標準機能を使った日本語検索の課題について詳しく知りたい方は、ぜひ前回の記事をご覧ください。
前回の記事では、Drupalの日本語検索におけるN-gram方式の課題について解説しました。今回は、それを解決するために開発したSearch API Japanese Tokenizerモジュールを紹介します。
Search API Japanese Tokenizer
モジュールとは
Search API Japanese Tokenizerは自然言語処理を用いて文章を解析し、適切な単語単位で検索用のインデックスを作成することで、検索性能を向上させることができるモジュールです。
本モジュールは、外部の自然言語処理ライブラリやソフトウェアを活用し、文章を適切に解析して検索性能を向上させます。利用するソフトウェアによって、インストールの手間や検索精度が異なるため、それぞれの特徴を比較します。
TinySegmenter | MeCab | Sudachi | |
---|---|---|---|
方法 | 機械学習 | 形態素解析 | 形態素解析 |
品詞解析 | なし | あり | あり |
速度 | 速め | 速い | 遅い |
精度 | 低い | 普通 | 高い |
正規化機能 | なし | あり (動詞の原型化) | あり |
外部インストール | 不要 | 必要 | 必要 |
TinySegmenterはJavaScriptで書かれたライブラリですが、本モジュールはPHPに移植したTinySegmenter PHP
を利用します。外部アプリケーションのインストールが不要なため手軽です。
MeCabやSudachi
はPHPアプリケーションではないため、別途サーバー上にインストールする必要があります。VPS等、アプリケーションを自由にインストールできる環境でないと利用できません。
使用する自然言語処理器ごとにサブモジュールとして分かれています。使用したい自然言語処理に合わせてモジュールを有効にしてください。
各サブモジュールを有効にすると、Search APIのプロセッサーの設定画面に次のトークナイザーが追加されます。
- TinySegmentation tokenizer
- MeCab tokenizer
- Sudachi tokenizer
検索精度を向上させるための追加機能
本モジュールでは自然言語処理をする以外にも、日本語の検索精度を向上させるための機能を実装しています。
TinySegmenter tokenizer
- 文字種ごとのインデックス制御
- ひらがな、カタカナ、漢字、その他の文字種ごとに、最小文字数を設定可能
MeCab tokenizer / Sudachi tokenizer
- 品詞種別によるインデックス対象の制御
- 日本語以外の文字種の最小文字数を設定可能
- 特定の品詞を除外可能(例:記号、助詞、助動詞など)
モジュールの利用方法
Search API Japanese TokenizerモジュールはSearch API
用のプラグインを提供するモジュールですので、単体では動作しません。Search API
モジュールはDrupalコアに高度な検索機能を追加するためのモジュールです。モジュールの設定方法については、Search APIの公式ドキュメント
を参照してください。Search API Japanese Tokenizer
の設定方法などについては、モジュールのREADME.md
を参照してください。
本記事は性能面の違いを比較することにフォーカスしますので、Search APIやSearch API Japanese Tokenizer
モジュールのインストールや設定の方法については割愛します。
N-gram vs. 自然言語処理
ここからは本モジュールを使うことで、Drupalの日本語検索はどのように改善されるのかを検証していきます。
まず、検索インデックス作成の基本的な仕組みを説明します。検索インデックスを作成するには、文章を適切に単語単位に分割する必要があります。この処理を行うのがトークナイザーであり、分割の工程はトークナイゼーションと呼ばれます。
前提条件
次の文章を用いて検索性能を検証していきます。この文章はChatGPTで適当に作成したものなので、ちゃんと読まなくて大丈夫です(笑)
東京都の猫
東京都には、さまざまな場所で猫たちが暮らしています。都会の喧騒の中にも、彼らの穏やかな生活が垣間見える瞬間があります。東京都の猫たちは、飼い猫として愛されるだけでなく、地域猫として住民に見守られながら生きることも多いです。
東京都の街角と猫
東京都の街中を歩いていると、意外にも多くの猫に出会うことができます。特に下町や昔ながらの住宅街では、猫がのんびりと日向ぼっこをしている光景がよく見られます。また、公園や神社の境内にも猫が住み着いていることが多く、訪れる人々を和ませています。
猫が集まるスポット
東京都には、猫好きにはたまらないスポットがいくつか存在します。たとえば、谷中銀座は「猫の街」として知られ、商店街のあちこちで猫の姿を見かけます。また、神楽坂や深大寺周辺も、猫たちが自由気ままに過ごしているエリアとして人気があります。
東京都の地域猫活動
東京都では、地域猫活動が積極的に行われています。地域猫とは、飼い主のいない猫たちを地域の人々が見守りながら共生する仕組みのことです。特に、世田谷区や杉並区では、ボランティア団体が猫のTNR活動(捕獲・不妊手術・元の場所へ戻す)を推進しており、猫たちが適切な環境で暮らせるよう支援しています。
猫と共に生きる東京都
東京都は大都市でありながら、猫たちがのびのびと暮らせる場所も多く存在します。地域の人々と猫が共存することで、東京都の街並みはさらに魅力的なものになっています。猫好きな方は、東京都内の猫スポットを巡ってみるのも楽しいかもしれません。
東京都の猫の魅力
東京都の猫たちは、都会の中にいながらもどこかのんびりとした雰囲気を持っています。人懐っこい猫もいれば、少し距離をとりながらも人間の存在を受け入れている猫もいます。その自由気ままな姿は、見る人の心を和ませてくれます。
また、東京都の猫たちは、多様な環境に適応しながら生活しているのも魅力のひとつです。商店街で店主に可愛がられる猫、神社で静かに佇む猫、公園で子どもたちと遊ぶ猫など、それぞれがその場所に合った生き方をしています。
東京都の猫たちは、人々の生活の一部として、今日も静かに息づいています。
検証にあたり、各トークナイザーの設定は次のようにしました。
- Tokenizer(Search API標準)
- 「インデックス付けをする単語の最小文字数」は2文字に設定
- TinySegmentation tokenizer
- インデックスするひらがなの最小文字数は2文字に設定
- インデックスするカタカナの最小文字数は2文字に設定
- インデックスする漢字の最小文字数は1文字に設定
- インデックスするその他の文字種の最小文字数は3文字に設定
- MeCab tokenizer
- 「Base form convert」は有効
- 「インデックスから除外する品詞」は「記号、助詞、助動詞」に設定
- 「Minimum number of characters for non-Japanese words to be indexed」は3文字に設定
- Sudachi tokenizer
- 「分割モード」は「A」に設定
- 「インデックスから除外する品詞」は「助詞、助動詞、接頭語、補助記号」に設定
- 「Use normalized words」は有効
- 「Minimum number of characters for non-Japanese words to be indexed」は3文字に設定
検索精度の比較
様々な視点で検索性能を検証していきます。
普通に検索
まずは記事に頻出する「東京都」で検索してみましょう。結果は次のとおりです。
トークナイザー | 結果 |
---|---|
Tokenizerの簡易CJK処理 | ヒット |
TinySegmenter tokenizer | ヒット |
MeCab tokenizer | ヒット |
Sudachi tokenizer | ヒット |
当然ながら、すべてのモジュールでヒットします。
単語の分割性能を検証
次に「京都」で検索してみます。結果は次のとおりです。
トークナイザー | 結果 |
---|---|
Tokenizerの簡易CJK処理 | ヒット |
TinySegmenter tokenizer | ❓該当なし |
MeCab tokenizer | ❓該当なし |
Sudachi tokenizer | ❓該当なし |
N-gramのみヒットしました。これは「東京都」と言う文字列が「東京」と「京都」の2つに分割されるためです。「京都」で検索した検索結果に東京の記事が含まれるのは、明らかにノイズです。自然言語処理を行えば「東京都」と言う単語はそのまま「東京都」としてインデックスされるため、このような問題は発生しません。
1文字検索の検証
続いて「猫」で検索してみます。
トークナイザー | 結果 |
---|---|
Tokenizerの簡易CJK処理 | 検索不可 |
TinySegmenter tokenizer | ヒット |
MeCab tokenizer | ヒット |
Sudachi tokenizer | ヒット |
N-gramでは2文字以上の単語でしかインデックス・検索できないため、検索ができませんでした。一方で自然言語処理した場合は1文字のキーワードでも検索が可能です。
単語の正規化機能を検証
例文には含まれていない「暮らす」というキーワードで検索してみます。
トークナイザー | 結果 |
---|---|
Tokenizerの簡易CJK処理 | ❓該当なし |
TinySegmenter tokenizer | ❓該当なし |
MeCab tokenizer | ヒット |
Sudachi tokenizer | ヒット |
MeCabとSudachiではヒットしました。MeCabは動詞の原形変換機能により、「暮らし」が「暮らす」に変換され、Sudachiは正規化機能により「暮らせる」と「暮らし」が「暮らす」に変換されるためヒットします。このように形態素解析器の正規化(原型化)機能を利用すれば、書き方は異なっていても同じ意味を持つ単語を検索できます。
複合語の検索
最後に「日向」で検索してみましょう。例文には「日向ぼっこ」というフレーズが含まれています。
トークナイザー | 結果 |
---|---|
Tokenizerの簡易CJK処理 | ヒット |
TinySegmenter tokenizer | ヒット |
MeCab tokenizer | ❓該当なし |
Sudachi tokenizer | ❓該当なし |
N-gramと機械学習のTinySegmenterではヒットしましたが、MeCabとSudachiではヒットしませんでした。TinySegmenterは「日向ぼっこ」という複合語を「日向」と「ぼっこ」に分割するためヒットします。一方でMeCabとSudachiは形態素解析によって「日向ぼっこ」という複合語は、1つの名詞として認識するためヒットしません。
これまで完璧に見えていた形態素解析ですが、場合によっては検索精度を下げることがあると分かります。
検索インデックスのレコード数を比較
検索インデックスに登録されるレコード数は、少なければ少ないほど検索スピードが向上します。N-gramと形態素解析の2つの方法で検索インデックスを作成し、そのレコードの数を比較してみましょう。
次の結果は例文を元に検索インデックスを作成した際のレコード数です。
トークナイザー | 処理方法 | レコード数 |
---|---|---|
Tokenizerの簡易CJK処理 | N-gram | 1105件 |
TinySegmenter tokenizer | 機械学習 | 447件 |
MeCab tokenizer | 形態素解析 | 405件 |
Sudachi tokenizer | 形態素解析 | 413件 |
自然言語処理を使えば、N-gramに比べ約36%〜40%のレコード数で検索インデックスを作成できることがわかります。青空文庫の小説をいくつか試したところ、50%程度のレコード数で済むことが確認できました。
まとめ
いかがでしたでしょうか。自然言語処理を導入すると、多くのケースで検索精度と検索パフォーマンスを向上できることが分かりました。
開発したSearch API Japanese Tokenizerモジュールは今現在α版として公開しています。今後はユーザーのフィードバックを受けて、さらなる改善をする予定です。ぜひ、お試しいただき、ご意見をお寄せいただければ幸いです。
謝辞
本モジュールでは外部のライブラリやソフトウェアを利用しています。自然言語処理の分野は高度で複雑なため、これらの技術なしに高精度な処理を実現するのは困難です。OSSとして公開し、貢献してくださっている開発者の皆様に心より感謝申し上げます。