ベクトル場を用いたテキスト類似性検索

この投稿では、テキスト埋め込みと Elasticsearch の新しい dense_vector タイプを使用して類似性検索をサポートする方法について説明します。

ベクトル検索から強力なREST APIまで、Elasticsearchは開発者に最も広範な検索ツールキットを提供します。GitHubのサンプルノートブックにアクセスして新しいことを試してみましょう。また、無料トライアルを始めるか、ローカルでElasticsearchを実行することもできます。

Elasticsearch は、レシピ検索エンジンとして誕生して以来、高速で強力な全文検索を提供するように設計されました。このような背景から、テキスト検索の改善は、ベクターに関する私たちの継続的な取り組みの重要な動機となっています。Elasticsearch 7.0 では、高次元ベクトル用の実験的なフィールドタイプを導入し、7.3 リリースでは、ドキュメント スコアリングでこれらのベクトルを使用するためのサポートが追加されました。

この投稿では、テキスト類似性検索と呼ばれる特定の手法に焦点を当てています。このタイプの検索では、ユーザーは短いフリーテキストクエリを入力し、ドキュメントはクエリとの類似性に基づいてランク付けされます。テキストの類似性は、さまざまな使用例で役立ちます。

  • 質問回答:よくある質問のコレクションが与えられた場合、ユーザーが入力した質問に類似した質問を見つけます。
  • 記事検索:研究記事のコレクションで、ユーザーのクエリに密接に関連するタイトルの記事を返します。
  • 画像検索:キャプション付きの画像のデータセットで、ユーザーの説明に類似したキャプションを持つ画像を検索します。

類似性検索の直接的なアプローチは、クエリと共有する単語の数に基づいてドキュメントをランク付けすることです。しかし、共通する単語がほとんどない場合でも、ドキュメントがクエリと類似している可能性があります。より堅牢な類似性の概念では、構文と意味の内容も考慮されます。

自然言語処理 (NLP) コミュニティは、単語や文章を数値ベクトルとしてエンコードするテキスト埋め込みと呼ばれる手法を開発しました。これらのベクトル表現は、テキストの言語コンテンツをキャプチャするように設計されており、クエリとドキュメント間の類似性を評価するために使用できます。

この投稿では、テキスト埋め込みと Elasticsearch の dense_vector タイプを使用して類似性検索をサポートする方法について説明します。まず、埋め込み技術の概要を説明し、次に Elasticsearch を使用した類似性検索の簡単なプロトタイプを段階的に説明します。

注:検索でテキスト埋め込みを使用することは、複雑かつ進化を続ける領域です。このブログは、特定のアーキテクチャや実装を推奨するものではありません。ベクター検索の力を利用して検索エクスペリエンスを強化する方法を学ぶには、ここから始めてください。

テキスト埋め込みとは何ですか?

さまざまな種類のテキスト埋め込みと、従来の検索アプローチとの比較を詳しく見てみましょう。

単語埋め込み

単語埋め込みモデルは、単語を密な数値ベクトルとして表現します。これらのベクトルは、単語の意味特性を捉えることを目的としています。つまり、ベクトルが近い単語は、意味の点で類似しているはずです。適切な埋め込みでは、ベクトル空間の方向は単語の意味のさまざまな側面に結び付けられます。たとえば、「カナダ」のベクトルは、ある方向では「フランス」に近く、別の方向では「トロント」に近くなる可能性があります。

NLP および検索コミュニティは、かなり長い間、単語のベクトル表現に興味を抱いてきました。過去数年間、多くの従来のタスクがニューラル ネットワークを使用して再検討され、単語埋め込みへの関心が再び高まりました。word2vecGloVeなど、いくつかの成功した単語埋め込みアルゴリズムが開発されました。これらのアプローチでは、大規模なテキスト コレクションを利用し、各単語が出現するコンテキストを調べてベクトル表現を決定します。

  • word2vec Skip-gram モデルは、ニューラル ネットワークをトレーニングして、文中の単語の周囲のコンテキスト ワードを予測します。ネットワークの内部重みによって単語の埋め込みが与えられます。
  • GloVe では、単語の類似性は、他の文脈上の単語と一緒に出現する頻度によって決まります。このアルゴリズムは、単語の共起カウントに基づいて単純な線形モデルをトレーニングします。

多くの研究グループが、Wikipedia や Common Crawl などの大規模なテキスト コーパスで事前トレーニングされたモデルを配布しており、ダウンロードして下流のタスクに組み込むのが便利になっています。事前トレーニング済みのバージョンが直接使用される場合もありますが、特定のターゲット データセットとタスクに合わせてモデルを調整すると役立つ場合があります。これは通常、事前トレーニング済みのモデルに対して「微調整」ステップを実行することによって実現されます。

単語埋め込みは非常に堅牢かつ効果的であることが証明されており、機械翻訳や感情分類などの NLP タスクでは、個々のトークンの代わりに埋め込みを使用するのが一般的になっています。

文の埋め込み

最近では、研究者たちは単語だけでなく、より長いテキストセクションを表す埋め込み技術に注目し始めています。現在のアプローチのほとんどは、複雑なニューラル ネットワーク アーキテクチャに基づいており、意味情報の取得を支援するためにトレーニング中にラベル付けされたデータを組み込むこともあります。

一度トレーニングされると、モデルは文を受け取り、文脈内の各単語のベクトルと文全体のベクトルを生成できるようになります。単語埋め込みと同様に、多くのモデルの事前トレーニング済みバージョンが利用可能であり、ユーザーはコストのかかるトレーニング プロセスを省略できます。トレーニング プロセスは大量のリソースを消費する可能性がありますが、モデルの呼び出しははるかに軽量です。文埋め込みモデルは通常、リアルタイム アプリケーションの一部として使用できるほど高速です。

一般的な文埋め込み手法としては、 InferSentUniversal Sentence EncoderELMoBERTなどがあります。単語や文の埋め込みの改善は活発に研究されている分野であり、今後さらに強力なモデルが導入される可能性があります。

従来の検索アプローチとの比較

従来の情報検索では、テキストを数値ベクトルとして表現する一般的な方法は、語彙内の単語ごとに 1 つの次元を割り当てることです。テキストのベクトルは、語彙内の各用語が出現する回数に基づいて決定されます。テキストを表現するこの方法は、文の構造を考慮せずに単語の出現回数を単純に数えるため、「bag of words」と呼ばれることがよくあります。

テキスト埋め込みは、いくつかの重要な点で従来のベクトル表現と異なります。

  • エンコードされたベクトルは密度が高く、比較的低次元であり、多くの場合 100 次元から 1,000 次元の範囲になります。対照的に、Bag of Words ベクトルはスパースであり、50,000 以上の次元で構成できます。埋め込みアルゴリズムは、テキストの意味をモデル化する一環として、テキストを低次元空間にエンコードします。理想的には、同義語やフレーズは、新しいベクトル空間で同様の表現になります。
  • 文の埋め込みでは、ベクトル表現を決定するときに単語の順序を考慮できます。たとえば、「tune in」というフレーズは、「in tune」とはまったく異なるベクトルとしてマッピングされる場合があります。
  • 実際には、文の埋め込みはテキストの大きなセクションにはうまく一般化されないことがよくあります。これらは通常、短い段落よりも長いテキストを表すために使用されません。

質問と回答の大きなコレクションがあったとしましょう。ユーザーは質問をすることができ、私たちはユーザーが回答を見つけやすくするために、コレクション内で最も類似した質問を取得したいと考えています。

テキスト埋め込みを使用すると、類似の質問を取得できるようになります。

  • インデックス作成中に、各質問は文埋め込みモデルに渡され、数値ベクトルが生成されます。
  • ユーザーがクエリを入力すると、同じ文埋め込みモデルが実行され、ベクトルが生成されます。回答をランク付けするために、各質問とクエリ ベクトル間のベクトル類似度を計算します。埋め込みベクトルを比較する場合、コサイン類似度を使用するのが一般的です。

このリポジトリには、 Elasticsearch でこれをどのように実現できるかの簡単な例が示されています。メイン スクリプトは、 StackOverflow データセットから約 20,000 件の質問にインデックスを付け、ユーザーがデータセットに対してフリーテキスト クエリを入力できるようにします。

スクリプトの各部分については後ほど詳しく説明しますが、まずはいくつかの例の結果を見てみましょう。多くの場合、この方法は、クエリとインデックス付けされた質問の間に強い単語の重複がない場合でも類似性を捉えることができます。

  • 「ファイルを圧縮」と入力すると、「フォルダとファイルの圧縮/解凍」が返されます。
  • 「何かが IP であるかどうかを判断する」は、「文字列が IP であるかホスト名であるかを判断する方法」を返します。
  • 「バイトを倍精度浮動小数点数に変換する」は「Pythonでバイトを浮動小数点数に変換する」を返します。

実装の詳細

スクリプトは、 TensorFlow に埋め込みモデルをダウンロードして作成することから始まります。Google の Universal Sentence Encoder を選択しましたが、他の多くの埋め込み方法を使用することもできます。スクリプトは追加のトレーニングや微調整を行わずに、埋め込みモデルをそのまま使用します。

次に、質問のタイトル、タグ、およびベクトルとしてエンコードされた質問のタイトルのマッピングを含む Elasticsearch インデックスを作成します。

dense_vector のマッピングでは、ベクトルに含まれる次元の数を指定する必要があります。title_vector フィールドにインデックスを作成するとき、Elasticsearch はマッピングで指定されたのと同じ数のディメンションがあるかどうかを確認します。

ドキュメントのインデックスを作成するには、質問のタイトルを埋め込みモデルに渡して数値配列を取得します。この配列は、title_vector フィールドのドキュメントに追加されます。

ユーザーがクエリを入力すると、テキストは最初に同じ埋め込みモデルに渡され、パラメータ query_vector に保存されます。7.3 以降、Elasticsearch はネイティブ スクリプト言語でcosineSimilarity 関数を提供します。したがって、ユーザーのクエリとの類似性に基づいて質問をランク付けするには、script_score クエリを使用します。

新しいクエリごとにスクリプト () が再コンパイルされるのを避けるために、クエリ ベクトルをスクリプト パラメータとして渡すようにします。Elasticsearch では負のスコアが許可されないため、コサイン類似度に 1 を追加する必要があります。

|注:このブログ投稿では、元々、Elasticsearch 7.3 で使用可能だったベクトル関数の別の構文を使用していましたが、7.6 では非推奨になりました。|

重要な制限事項

script_score クエリは、制限的なクエリをラップし、返されるドキュメントのスコアを変更するように設計されています。ただし、match_all クエリを提供しているため、スクリプトはインデックス内のすべてのドキュメントに対して実行されます。これは、Elasticsearch におけるベクトル類似性の現在の制限です。ベクトルはドキュメントのスコアリングには使用できますが、最初の検索手順では使用できません。ベクトル類似性に基づく検索のサポートは、現在進行中の作業の重要な領域です。

すべてのドキュメントをスキャンすることを回避し、高速なパフォーマンスを維持するために、match_all クエリをより選択的なクエリに置き換えることができます。検索に使用する適切なクエリは、特定のユースケースによって異なる可能性があります。

上記ではいくつか有望な例を見てきましたが、結果にはノイズが多く直感的でない場合もあることに注意することが重要です。例えば、「ファイルを圧縮する」では、「部分的な.csproj」にも高いスコアが割り当てられます。ファイル」と「.pyc を回避する方法」ファイルですか?また、メソッドが予期しない結果を返す場合、その問題をデバッグする方法が必ずしも明確であるとは限りません。各ベクトル要素の意味は不透明であることが多く、解釈可能な概念に対応していません。単語の重複に基づく従来のスコアリング手法を使用すると、「なぜこのドキュメントのランクが高いのか」という質問に答えるのが簡単になることがよくあります。

前述のように、このプロトタイプは埋め込みモデルをベクトル フィールドで使用する方法の例として提供されており、本番環境で使用できるソリューションとして提供されているわけではありません。新しい検索戦略を開発するときは、一致クエリなどの強力なベースラインと比較しながら、独自のデータでそのアプローチがどのように機能するかをテストすることが重要です。確実な結果を得るには、ターゲット データセットの埋め込みモデルを微調整したり、単語レベルのクエリ拡張などの埋め込みを組み込むさまざまな方法を試したりするなど、戦略に大きな変更を加える必要がある場合があります。

結論

埋め込み技術は、テキストの言語コンテンツを取得する強力な方法を提供します。埋め込みをインデックス化し、ベクトル距離に基づいてスコアリングすることで、単語レベルの重複を超えた類似性の概念を使用してドキュメントを比較できます。

ベクター フィールド タイプに基づいた機能をさらに導入することを楽しみにしています。検索にベクトルを使用するのは、微妙で発展途上の領域です。いつものように、 Githubディスカッション フォーラムで、皆さんの使用事例や体験談をお聞かせください。

よくあるご質問

テキスト類似性検索とは何ですか?

テキスト類似性検索は、ユーザーが短いフリーテキストクエリを入力し、そのクエリとの類似性に基づいてドキュメントがランク付けされるタイプの検索です。質問回答、記事検索、画像検索など、さまざまなユースケースで役立ちます。

関連記事

最先端の検索体験を構築する準備はできましたか?

十分に高度な検索は 1 人の努力だけでは実現できません。Elasticsearch は、データ サイエンティスト、ML オペレーター、エンジニアなど、あなたと同じように検索に情熱を傾ける多くの人々によって支えられています。ぜひつながり、協力して、希望する結果が得られる魔法の検索エクスペリエンスを構築しましょう。

はじめましょう