🕌
FAISS の IVF+HNSWにおけるパラメーター推奨値
FAISS の IVF+HNSW (Inverted File with Hierarchical Navigable Small World) インデックスは、高次元ベクトルの近似最近傍検索(ANN: Approximate Nearest Neighbor Search)を高速化するための強力な手法です。
特に、検索精度と検索速度のバランスを取るために、以下のパラメーターを調整することが重要です。
調整可能なパラメーター
nlist
(クラスタ数)
1. - データセットを
nlist
個のクラスタに分割する。 -
nlist
が大きいほどクラスタは細かくなり、検索時の候補数が減るため検索速度は向上するが、適切なクラスタが選ばれないと精度が低下する。 - 推奨値:
sqrt(N)
, ただしN
はデータセットのサイズ。
nprobe
(検索するクラスタ数)
2. - 検索時に探索するクラスタの数。
-
nprobe
を大きくすると検索精度は向上するが、検索時間が増加する。 - 推奨値:
nlist
の 1%〜10%。
efSearch
(HNSW の検索用パラメータ)
3. - HNSW の検索の際に考慮する候補数。
-
efSearch
を大きくすると検索精度は向上するが、計算コストが増加する。 - 推奨値:
nprobe * 4
くらいが目安。
efConstruction
(HNSW の構築用パラメータ)
4. - HNSW グラフを構築する際の最大候補数。
-
efConstruction
を大きくすると検索精度は向上するが、インデックス構築時間とメモリ消費が増加する。 - 推奨値: 64〜256。
実際のコード例
以下のコードでは、IVF+HNSW を用いてベクトル検索を最適化する方法を示します。
1. インデックスの作成
import faiss
import numpy as np
# データセットの準備
d = 128 # ベクトルの次元
N = 100000 # データセットのサイズ
X = np.random.random((N, d)).astype('float32') # ランダムなベクトルを生成
# パラメータ設定
nlist = int(np.sqrt(N)) # クラスタ数(IVFのパーティション数)
nprobe = max(1, nlist // 10) # 検索時に探索するクラスタ数
efConstruction = 128 # HNSW の構築パラメータ
efSearch = nprobe * 4 # HNSW の検索パラメータ
# IVF+HNSW のインデックスを作成
quantizer = faiss.IndexHNSWFlat(d, 32) # 32はHNSWの接続度
index = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)
# HNSWの構築パラメータを設定
quantizer.hnsw.efConstruction = efConstruction
# インデックスをトレーニング
index.train(X)
index.add(X)
# HNSWの検索パラメータを設定
index.nprobe = nprobe
quantizer.hnsw.efSearch = efSearch
print(f"Index trained: {index.is_trained}, Total vectors: {index.ntotal}")
2. 検索時のパラメータ調整
# クエリデータの準備
query = np.random.random((1, d)).astype('float32') # 1つのクエリ
# 検索時のパラメータ
index.nprobe = nprobe # IVF の探索クラスタ数
quantizer.hnsw.efSearch = efSearch # HNSW の探索候補数
# 近傍検索
k = 10 # 取得する近傍の数
distances, indices = index.search(query, k)
print("Nearest neighbors:", indices)
print("Distances:", distances)
パフォーマンスチューニングのポイント
-
nlist
を適切に設定-
nlist
が小さすぎると検索時間が増加し、大きすぎるとクラスタの分散が大きくなり精度が低下する。 - 一般的に
sqrt(N)
くらいが良いバランス。
-
-
nprobe
を適切に調整-
nprobe
を大きくすると検索精度が向上するが、検索時間が増加する。 -
nprobe = nlist / 10
くらいから試し、必要に応じて調整。
-
-
efConstruction
を大きめに設定- HNSW の構築時に多くの候補を考慮すると、検索精度が向上する。
- ただし、メモリ消費が増加するため
64〜256
の範囲で調整。
-
efSearch
を調整-
efSearch
を大きくすると検索精度が向上するが、速度が低下する。 -
nprobe * 4
くらいを基準にし、精度に応じて調整。
-
-
マルチスレッド化
- FAISS はマルチスレッドで動作するため、並列化のためにスレッド数を設定できる。
faiss.omp_set_num_threads(4) # 4スレッドを使用
まとめ
FAISS の IVF+HNSW を効果的に活用するためには、以下のパラメータを調整することが重要です。
パラメータ | 役割 | 推奨値 |
---|---|---|
nlist |
クラスタの数(大きいほど高速だが精度が低下) | sqrt(N) |
nprobe |
探索するクラスタ数(大きいほど精度向上) | nlist / 10 |
efConstruction |
HNSW のグラフ構築時の候補数 | 64〜256 |
efSearch |
HNSW の検索時の候補数 | nprobe * 4 |
調整の指針
- 検索精度を上げたいなら
nprobe
とefSearch
を増やす。 - 検索速度を上げたいなら
nlist
を増やしてnprobe
を減らす。 - メモリ制約がある場合は
efConstruction
を小さくする。
このようにパラメータを調整することで、検索精度と速度のバランスを最適化できます。
実際のデータセットで試しながら、適切な値を見つけてみてください!
Discussion