高密度ベクトル検索

Solrの高密度ベクトル検索は、高密度数値ベクトルのインデックス作成と検索のサポートを追加します。

深層学習を使用して、情報コーパス内のクエリとドキュメントの両方のベクトル表現を作成できます。

これらのニューラルネットワークベースの手法は、通常、ニューラル検索と呼ばれ、学術分野のニューラル情報検索から派生した業界用語です。

重要な概念

高密度ベクトル表現

従来のトークン化された転置インデックスは、テキストを「スパース」ベクトルとしてモデル化すると考えられます。このモデルでは、コーパス内の各用語が1つのベクトル次元に対応します。このようなモデルでは、次元の数は一般に非常に多く(用語辞書のカーディナリティに対応)、任意のドキュメントのベクトルにはほとんどゼロが含まれます(したがって、インデックス全体に存在する用語のごく一部が特定のドキュメントに存在するため、スパースになります)。

高密度ベクトル表現は、近似的な意味を固定(かつ制限された)数の次元に抽出するという点で、用語ベースのスパースベクトル表現とは対照的です。

このアプローチにおける次元の数は、一般にスパースの場合よりもはるかに少なく、任意のドキュメントのベクトルは高密度であり、その次元のほとんどがゼロ以外の値で埋められています。

スパースアプローチ(テキスト入力から直接スパースベクトルを生成するためにトークナイザーが使用される)とは対照的に、ベクトルの生成タスクは、Apache Solrの外部のアプリケーションロジックで処理する必要があります。

ベクトルとしてネイティブに存在するデータ(例:科学データ)を直接検索することが理にかなっている場合もありますが、テキスト検索のコンテキストでは、ユーザーはBERTなどの深層学習モデルを活用してテキスト情報を高密度ベクトルとしてエンコードし、インデックス作成時とクエリ時に結果のベクトルをApache Solrに明示的に提供する可能性があります。

詳細については、このブログ記事を参照してください。

高密度検索

情報ニーズをモデル化する高密度ベクトルvが与えられた場合、高密度ベクトル検索を提供する最も簡単な方法は、vと情報コーパス内のドキュメントを表す各ベクトルdとの間の距離(ユークリッド、ドット積など)を計算することです。

このアプローチは非常にコストがかかるため、現在多くの近似戦略が活発に研究されています。

Apache Luceneで実装され、Apache Solrで使用されている戦略は、ナビゲーティング可能なスモールワールドグラフに基づいています。

高次元ベクトルに対して効率的な近似最近傍検索を提供します。

インデックス作成時間

これは、高密度ベクトル検索をサポートするように設計されたApache Solrフィールドタイプです。

DenseVectorField

高密度ベクトルフィールドは、浮動小数点要素の高密度ベクトルのインデックス作成と検索の可能性を提供します。

例:

[1.0, 2.5, 3.7, 4.1]

DenseVectorFieldをスキーマで構成する方法を次に示します。

<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="4" similarityFunction="cosine"/>
<field name="vector" type="knn_vector" indexed="true" stored="true"/>
vectorDimension

必須

デフォルト:なし

渡す高密度ベクトルの次元。

受け入れられる値:任意の整数。

similarityFunction

オプション

デフォルト:euclidean

ベクトル類似性関数。検索で、ターゲットベクトルに最も類似した上位K個のベクトルを返すために使用されます。

受け入れられる値:euclideandot_product、またはcosine

この類似度は、コサイン類似度を実行するための最適化された方法として意図されています。これを使用するには、ドキュメントベクトルとクエリベクトルの両方を含む、すべてのベクトルが単位長でなければなりません。単位長ではないベクトルでドット積を使用すると、エラーが発生したり、検索結果が不十分になる可能性があります。
コサイン類似度を実行する推奨方法は、すべてのベクトルを単位長に正規化し、代わりに DOT_PRODUCT を使用することです。元のベクトルを保持する必要があり、事前に正規化できない場合にのみ、この関数を使用する必要があります。

コーデック形式と HNSW アルゴリズムのハイパーパラメータをカスタマイズする以下の高度なパラメータを使用するには、スキーマコーデックファクトリーを使用していることを確認してください。

DenseVectorField を高度なハイパーパラメータで構成する方法を次に示します。

<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="4" similarityFunction="cosine" knnAlgorithm="hnsw" hnswMaxConnections="10" hnswBeamWidth="40"/>
<field name="vector" type="knn_vector" indexed="true" stored="true"/>
knnAlgorithm

オプション

デフォルト: hnsw

(高度) 使用する基盤となる knn アルゴリズムを指定します

使用可能な値: hnsw.

knnAlgorithm で使用可能な値は、将来のリリースで変更される可能性があることに注意してください。

vectorEncoding

オプション

デフォルト: FLOAT32

(高度) 密ベクトル要素の基盤となるエンコーディングを指定します。これは、インデックス付きフィールドと保存済みフィールド(有効な場合)の両方のメモリ/ディスクへの影響に影響します

使用可能な値: FLOAT32, BYTE.

hnswMaxConnections

オプション

デフォルト: 16

(高度) このパラメータは hnsw knn アルゴリズムに固有のものです

新しいノードに接続される最も近い隣接候補の数を制御します。

2018 年の論文の M と同じ意味を持ちます。

受け入れられる値:任意の整数。

hnswBeamWidth

オプション

デフォルト: 100

(高度) このパラメータは hnsw knn アルゴリズムに固有のものです

これは、新しく挿入された各ノードのグラフを検索中に追跡する最も近い隣接候補の数です。

2018 年の論文の efConstruction と同じ意味を持ちます。

受け入れられる値:任意の整数。

DenseVectorField は、属性: indexed, stored をサポートしています。

現在、多値はサポートされていません

DenseVectorField をインデックス化する方法を次に示します。

JSON

[{ "id": "1",
"vector": [1.0, 2.5, 3.7, 4.1]
},
{ "id": "2",
"vector": [1.5, 5.5, 6.7, 65.1]
}
]

XML

<add>
<doc>
<field name="id">1</field>
<field name="vector">1.0</field>
<field name="vector">2.5</field>
<field name="vector">3.7</field>
<field name="vector">4.1</field>
</doc>
<doc>
<field name="id">2</field>
<field name="vector">1.5</field>
<field name="vector">5.5</field>
<field name="vector">6.7</field>
<field name="vector">65.1</field>
</doc>
</add>

SolrJ

final SolrClient client = getSolrClient();

final SolrInputDocument d1 = new SolrInputDocument();
d1.setField("id", "1");
d1.setField("vector", Arrays.asList(1.0f, 2.5f, 3.7f, 4.1f));


final SolrInputDocument d2 = new SolrInputDocument();
d2.setField("id", "2");
d2.setField("vector", Arrays.asList(1.5f, 5.5f, 6.7f, 65.1f));

client.add(Arrays.asList(d1, d2));

クエリ時

これは、密ベクトル検索をサポートするために設計された Apache Solr のクエリ手法です。

knn クエリパーサー

knn k 最近傍クエリパーサーを使用すると、指定されたフィールドのインデックス付き密ベクトルに従って、ターゲットベクトルに最も近い k 個のドキュメントを見つけることができます。

取得されたドキュメントのスコアは、ターゲットベクトルへの近似距離(インデックス時に構成された similarityFunction で定義)です。

以下のパラメータを取ります

f

必須

デフォルト:なし

検索する DenseVectorField

topK

オプション

デフォルト: 10

返す最も近い k 個の結果の数。

KNN 検索を実行する方法を次に示します。

&q={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]

取得された検索結果は、入力 [1.0, 2.0, 3.0, 4.0] のベクトルに最も近い k 個であり、インデックス時に構成された similarityFunction でランク付けされます。

フィルタークエリでの使用

knn クエリパーサーは、フィルタークエリで使用できます

&q=id:(1 2 3)&fq={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]

knn クエリパーサーは、フィルタークエリで使用できます

&q={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]&fq=id:(1 2 3)

フィルタークエリはプリフィルターとして実行されます。メインクエリは、「MUST」句(ブール AND)として結合されたすべてのフィルタークエリの適用から派生した検索結果のサブセットを絞り込みます。

これは、次のことを意味します

&q=id:(1 2 3)&fq={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]

結果は topK knn 検索によって事前にフィルター処理され、その後、クエリ 'q=id:(1 2 3)' に一致するこのサブセットからのドキュメントのみが返されます。

次の場合

&q={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]&fq=id:(1 2 3)

結果は fq=id:(1 2 3) で事前にフィルター処理され、その後、このサブセットからのドキュメントのみが topK knn 検索の候補として考慮されます。

フィルタークエリの一部をポストフィルターとして実行する場合は、Apache Solr でのポストフィルターの標準的なアプローチに従い、キャッシュおよびコストローカルパラメータを使用できます。

例:

&q={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]&fq={!frange cache=false l=0.99}$q

再ランキングクエリとしての使用

knn クエリパーサーを使用して、最初のパスのクエリ結果を再ランク付けできます

&q=id:(3 4 9 2)&rq={!rerank reRankQuery=$rqq reRankDocs=4 reRankWeight=1}&rqq={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]

再ランキングで knn を使用する場合は、topK パラメータに注意してください。

最初のパスからのドキュメント d が、検索対象のターゲットベクトルの k 最近傍(インデックス全体で)内にある場合にのみ、2 番目のパスのスコア(knn から派生)が計算されます。

これは、2 番目のパスの knn がいずれにしてもインデックス全体で実行されることを意味します。これは現在の制限です。

結果の最終ランク付けされたリストには、最初のパスのスコア(メインクエリ q)に、2 番目のパスのスコア(検索対象のターゲットベクトルへの近似 similarityFunction 距離)を乗算係数(reRankWeight)で掛け合わせたものが加算されます。

ReRank クエリパーサーの使用に関する詳細は、クエリの再ランキングセクションにあります。