Измерение и улучшение качества извлечения данных при семантическом поиске#
Семантические поисковые конвейеры настолько хороши, насколько хороши используемые ими эмбеддинги. Если модель не может правильно представить входные данные, похожие объекты могут находиться далеко друг от друга в векторном пространстве. Нет ничего удивительного в том, что результаты поиска будут плохими в этом случае. Однако существует еще один компонент процесса, который также может ухудшить качество результатов поиска. Это сам алгоритм приближенных ближайших соседей (ANN).
В данном руководстве показано как измерить качество семантического извлечения данных и как настроить параметры алгоритма HNSW, используемого в Platform V Vector DB (далее - Vector DB) для получения наилучших результатов.
Качество эмбеддингов#
Качество эмбеддингов — тема отдельного руководства. Оно обычно измеряется и сравнивается по эталонным тестам, таким как Масштабный бенчмарк текстовых эмбеддингов (MTEB). Сам процесс оценки довольно прост и основан на наборе данных «истины», созданном людьми. Есть набор запросов и набор документов, которые ожидаем получить для каждого из них. В процессе оценки берется запрос, находятся наиболее похожие документы в векторном пространстве и сравниваются их с набором истинных значений. При такой настройке поиск наиболее похожих документов реализован как полный поиск k-ближайших соседей (kNN), без какой-либо аппроксимации. Таким образом возможно измерить само качество эмбеддингов, исключив влияние алгоритма ANN.
Качество извлечения данных#
Действительно, качество эмбеддингов является самым важным фактором в качестве семантического поиска. Векторные поисковые движки, такие как Vector DB, не выполняют чистый поиск kNN. Вместо этого они используют алгоритмы приблизительных ближайших соседей (ANN), которые значительно быстрее точного поиска, но могут возвращать неоптимальные результаты. Также можно измерить качество такого приближения, которое также влияет на общее качество поиска.
Метрики качества#
Существует множество способов количественной оценки качества семантического поиска. Некоторые из них, например Precision at K (p@K), основаны на количестве релевантных документов среди первых k результатов поиска. Другие метрики, такие как Средний обратный ранг (MRR), учитывают позицию первого релевантного документа в результатах поиска. Метрики DCG и NDCG, в очередь, основываются на оценках релевантности документов.
Если рассматривать поисковый конвейер целиком, можно использовать все перечисленные выше метрики. То же самое верно и для оценки качества эмбеддингов. Однако для самого алгоритма ANN любые метрики, основанные на оценке релевантности или ранжировании, неприменимы. Ранжирование в векторном поиске основано на расстоянии между запросом и документом в векторном пространстве, однако расстояние не изменится из-за аппроксимации, так как функция остается той же самой.
Таким образом, имеет смысл оценивать качество алгоритма ANN только по количеству релевантных документов среди первых k результатов поиска, таких как precision@k. Она рассчитывается как отношение количества релевантных документов среди первых k результатов к k. В случае тестирования только алгоритма ANN можно использовать точный поиск kNN в качестве набора истинных значений, установив фиксированное значение k. Это будет показателем того, насколько хорошо алгоритм ANN аппроксимирует точный поиск.
Оценка качества результатов поиска#
Постройте оценку качества алгоритма ANN в Vector DB. Сначала вызовите стандартный конечный пункт поиска, чтобы получить приблизительные результаты поиска. Затем вызовите конечную точку точного поиска, чтобы получить точные совпадения, и сравните оба результата по точности.
Вначале создайте коллекцию, заполните ее некоторыми данными, а затем приступите к оценке. Используйте набор данных Qdrant/arxiv-titles-instructorxl-embeddings из репозитория Hugging Face. Загрузите его в потоковом режиме, поскольку понадобится лишь часть данных.
from datasets import load_dataset
dataset = load_dataset(
"Qdrant/arxiv-titles-instructorxl-embeddings", split="train", streaming=True
)
Нужны некоторые данные для индексации и другой набор для целей тестирования. Возьмите первые 50000 элементов для обучения и следующие 1000 для тестирования.
dataset_iterator = iter(dataset)
train_dataset = [next(dataset_iterator) for _ in range(60000)]
test_dataset = [next(dataset_iterator) for _ in range(1000)]
Создайте коллекцию и проиндексируйте обучающие данные. Эта коллекция будет создана с конфигурацией по умолчанию. Обратите внимание, что она может отличаться от настроек коллекции, поэтому всегда важно протестировать именно ту конфигурацию, которую собираетесь использовать позже в производственной среде.
Функция расстояния — еще один параметр, который может повлиять на качество извлечения данных. Если модель эмбеддинга не была обучена минимизировать косинусное расстояние, использование его может привести к субоптимальным результатам поиска. Пожалуйста, проверьте разные функции расстояния, чтобы найти лучшую для эмбеддингов, если не знаете специфики обучения модели.
from qdrant_client import QdrantClient, models
client = QdrantClient("http://localhost:6333")
client.create_collection(
collection_name="arxiv-titles-instructorxl-embeddings",
vectors_config=models.VectorParams(
size=768, # Size of the embeddings generated by InstructorXL model
distance=models.Distance.COSINE,
),
)
Обучающие данные готовы к индексированию. Загрузка записей запустит процесс индексации, который создаст граф HNSW. Процесс индексации может занять некоторое время в зависимости от размера набора данных, но данные станут доступны для поиска сразу после получения ответа от конечной точки upsert. Пока индексирование не завершено и граф HNSW не построен, Vector DB выполняет точный поиск. Необходимо дождаться завершения индексации, чтобы убедиться, что выполняется приблизительный поиск.
client.upload_points( # upload_points is available as of qdrant-client v1.7.1
collection_name="arxiv-titles-instructorxl-embeddings",
points=[
models.PointStruct(
id=item["id"],
vector=item["vector"],
payload=item,
)
for item in train_dataset
]
)
while True:
collection_info = client.get_collection(collection_name="arxiv-titles-instructorxl-embeddings")
if collection_info.status == models.CollectionStatus.GREEN:
# Collection status is green, which means the indexing is finished
break
Стандартный режим против точного поиска#
В Vector DB встроен режим точного поиска, который можно использовать для измерения качества результатов поиска. В этом режиме Vector DB выполняет полный поиск kNN для каждого запроса без каких-либо приближений. Он не подходит для использования в производстве с высокой нагрузкой, но идеально подходит для оценки алгоритма ANN и его параметров. Его можно активировать, задав параметру exact значение True в запросе поиска. Воспользуйтесь всеми примерами из тестового набора данных в качестве запросов и сравните результаты приблизительного поиска с результатами точного поиска. Создайте вспомогательную функцию с параметром k, чтобы вычислить precision@k для разных значений k.
def avg_precision_at_k(k: int):
precisions = []
for item in test_dataset:
ann_result = client.query_points(
collection_name="arxiv-titles-instructorxl-embeddings",
query=item["vector"],
limit=k,
).points
knn_result = client.query_points(
collection_name="arxiv-titles-instructorxl-embeddings",
query=item["vector"],
limit=k,
search_params=models.SearchParams(
exact=True, # Turns on the exact search mode
),
).points
# We can calculate the precision@k by comparing the ids of the search results
ann_ids = set(item.id for item in ann_result)
knn_ids = set(item.id for item in knn_result)
precision = len(ann_ids.intersection(knn_ids)) / k
precisions.append(precision)
return sum(precisions) / len(precisions)
Вычисление precision@5 столь же просто, как вызов функции с соответствующим параметром:
print(f"avg(precision@5) = {avg_precision_at_k(k=5)}")
Ответ:
avg(precision@5) = 0.9935999999999995
Точность приблизительного поиска относительно точного достаточно высока. Бывают ситуации, когда требуется более высокая точность, и можно принять большую задержку. Алгоритм HNSW легко настраивается, и можно повысить точность, изменяя его параметры.
Настройка параметров HNSW#
HNSW - иерархический граф, где каждый узел имеет набор ссылок на другие узлы. Число ребер на узел называется параметром m. Чем больше его значение, тем выше точность поиска, но требуется больше пространства. Параметр ef_construct - число соседей, рассматриваемых во время построения индекса. Чем больше значение, тем выше точность, но дольше время индексации. Значения этих параметров по умолчанию равны m=16 и ef_construct=100. Попробуйте увеличить их до m=32 и ef_construct=200 и посмотрите, как это повлияет на точность. Конечно, нужно подождать окончания индексации перед выполнением поиска.
client.update_collection(
collection_name="arxiv-titles-instructorxl-embeddings",
hnsw_config=models.HnswConfigDiff(
m=32, # Increase the number of edges per node from the default 16 to 32
ef_construct=200, # Increase the number of neighbours from the default 100 to 200
)
)
while True:
collection_info = client.get_collection(collection_name="arxiv-titles-instructorxl-embeddings")
if collection_info.status == models.CollectionStatus.GREEN:
# Collection status is green, which means the indexing is finished
break
Та же самая функция может использоваться для расчета среднего значения precision@5:
print(f"avg(precision@5) = {avg_precision_at_k(k=5)}")
Ответ:
avg(precision@5) = 0.9969999999999998
Очевидно, что точность увеличилась, и теперь известно, как ею управлять. Однако здесь имеется компромисс между точностью и временем отклика поиска и требованиями к памяти. В некоторых конкретных случаях можно захотеть максимально увеличить точность, и теперь известно, как это сделать.
Заключение#
Оценка качества извлечения данных является критически важной частью оценивания производительности семантического поиска. Необходимо измерять качество извлечения данных, стремясь к оптимальному качеству результатов поиска. Vector DB предоставляет встроенный режим точного поиска, который можно использовать для измерения качества самого алгоритма ANN, даже автоматически, как часть конвейера CI/CD.
Самым важным фактором является качество эмбеддингов. HNSW отлично справляется с задачей обеспечения точности и поддается настройке, когда это необходимо. Существуют и другие доступные алгоритмы ANN, такие как IVF*, но они обычно работают хуже, чем HNSW, как по качеству, так и по производительности.