はじめに
少し長くなりそうなので結論から言いますと、分散表現のベクトルを格納するフィールドタイプ「dense_vector」の代わりにAmazon Elasticsearch Serviceに用意されているフィールドタイプ「knn_vector」を使用することにして困りごとを解消いたしました。
困ったこと
Elasticsearch 7.3のリリースで追加された高次元ベクトルのドキュメントスコアリング機能を用いてとある文章の機械学習を行い、「テキスト類似性検索」を実装しました。
始めにElastic社のElasticsearch(以下、Elasticsearch)を使用してローカル環境で機械学習を行っており、その後しばらくして学習済データをAmazon Elasticsearch Service(以下、Amazon ES)に移行する必要が出てきました。その際にエラーが発生し、後続作業が中断する事態となってしまいました。
※テキスト類似性検索(または類似文書検索)とは「文章を数値化し、その数値の類似度をもって検索対象の文章群の中から検索条件に近い文章を選択する自然言語処理の技術」です。
原因
エラーの原因は単純なことでした。存在しないフィールドタイプを使用しようとしてエラーとなってしまっていたのです。
Elasticsearch上で分散表現のベクトルを格納する際にフィールドタイプ「dense_vector」を使用していたのですが、Amazon ESに該当のフィールドタイプが存在しなかったのです。
対処法
何か手はないかとAmazon ESのドキュメントを読み漁ったところ、「KNN」というアルゴリズムがフィールドタイプ「knn_vector」として用意されていることがわかりました。
Amazon ESの開発者ガイドを見てみると
関連する k-近隣住民 アルゴリズム、KNN Amazon Elasticsearch Service では、ベクトル空間内の点を検索し、ユークリッド距離またはコサインの類似性によって、それらの点の「最も近くの隣人」を見つけることができます。ユースケースには、推奨 (音楽アプリケーションの「あなたにおすすめの曲」機能など)、画像認識、不正行為の検出などがあります。
と書いてあります(日本語ページの原文ママ)。何やら「dense_vector」と同様に高次元ベクトルを格納できるフィールドタイプのようです。
試しにAmazon ES上にフィールドタイプ「knn_vector」のフィールドを定義し、「dense_vector」に格納していたベクトルデータをインポートしてみたところエラーなく登録できました。
検索クエリの違い
フィールドタイプが異なるので検索クエリも変わってきます。
1.Elasticsearchの「dense_vector」
"query": {
"script_score": {
"query": {"match_all": {}},
"script": {
"source": "cosineSimilarity(params.query_vector, doc['text_vector']) + 1.0",
"params": {"query_vector": target_vector}
}
}
}
2.Amazon ESの「knn_vector」
"query": {
"knn": {
"text_vector": {
"vector": target_vector,
"k": 100
}
}
}
検索結果の差分
アルゴリズムが異なるため、当然検索結果も違ってくると思います。
今回は「それらしい結果が取得できている」で検証を終えています。
いつかちゃんと検索結果の違いについて調査しようと思います。
参考サイト
Amazon Elasticsearch Service>開発者ガイド>KNN
Amazon ElasticsearchServiceのK-NNを触ってみる
ベクトルフィールドを使ったテキスト類似性検索
Elasticsearchで分散表現を使った類似文書検索