Введение в векторный поиск по сходству
В предыдущих руководствах мы рассмотрели неструктурированные данные, векторные базы данных и Milvus — самую популярную в мире векторную базу данных с открытым исходным кодом, используемую для поиска по сходству. Мы также кратко затронули идею эмбеддингов — многомерных векторов, которые служат отличными семантическими представлениями неструктурированных данных. Один ключевой момент, который следует запомнить: эмбеддинги и векторные представления, которые находятся «близко» друг к другу, представляют семантически похожие фрагменты данных.
В этом введении в векторный поиск (он же поиск по сходству) мы определим, что это такое, и ответим на некоторые фундаментальные вопросы о нем. Затем мы закрепим эти знания, рассмотрев пример эмбеддингов слов и увидев, как семантически похожие фрагменты неструктурированных данных находятся «рядом» друг с другом, а непохожие фрагменты неструктурированных данных — «далеко» друг от друга. Это приведет нас к высокоуровневому обзору поиска ближайших соседей, вычислительной задачи, которая включает нахождение ближайшего(-их) вектора(-ов) к вектору запроса на основе единой метрики расстояния. Мы рассмотрим некоторые известные методы (алгоритмы поиска по сходству векторов) для поиска ближайших соседей (включая мой любимый — ANNOY) в дополнение к часто используемым метрикам расстояния.
Давайте погрузимся.
Что такое векторный поиск или поиск по сходству векторов?
Векторный поиск, также известный как поиск по сходству векторов, поиск ближайших соседей или семантический поиск, — это метод, используемый в системах поиска данных и информационного поиска для нахождения элементов или точек данных, которые похожи или тесно связаны с заданным вектором запроса. В отличие от традиционного поиска по ключевым словам, который сопоставляет точные слова или фразы, семантический поиск понимает намерение и контекстуальное значение запроса, что позволяет ему возвращать более релевантные результаты, даже когда точные ключевые слова отсутствуют в содержимом. В векторном поиске мы представляем точки данных, такие как изображения, тексты и аудио, в виде векторов в многомерном пространстве. Цель векторного поиска — эффективно искать и извлекать наиболее релевантные векторы, которые похожи или ближайшие к вектору запроса.
Обычно для измерения сходства между векторами используются метрики расстояния, такие как евклидово расстояние или косинусное сходство. Близость вектора в векторном пространстве определяет, насколько он похож. Чтобы эффективно организовывать и показывать результаты поиска для векторов, алгоритмы векторного поиска используют структуры индексирования, такие как древовидные структуры или методы хеширования.
Векторный поиск является центральным элементом векторных баз данных и имеет различные применения, включая рекомендательные системы, поиск изображений и видео, обработку естественного языка, обнаружение аномалий и чат-боты для вопросов и ответов. Использование семантического поиска делает возможным нахождение релевантных элементов, шаблонов или связей в многомерных данных, обеспечивая более точный и эффективный информационный поиск.
Векторный поиск — это мощный метод анализа и извлечения информации из многомерных пространств. Он позволяет пользователям находить элементы, похожие или тесно связанные с заданным запросом, что делает его крайне важным в различных областях. Вот преимущества векторного поиска:
Извлечение на основе сходства— Семантический поиск позволяет выполнять извлечение на основе сходства, давая пользователям возможность находить элементы, похожие или тесно связанные с заданным запросом. Извлечение на основе сходства имеет решающее значение в различных областях, таких как рекомендательные системы, где пользователи ожидают персонализированных рекомендаций на основе своих предпочтений или сходства с другими пользователями.
Анализ многомерных данных — С ростом доступности многомерных данных, таких как изображения, аудио и текстовые данные, традиционные методы поиска становятся менее эффективными. Векторный поиск предоставляет мощный способ анализа и извлечения информации из многомерных пространств, позволяя более точно и эффективно исследовать данные.
Поиск ближайших соседей — Эффективные алгоритмы поиска ближайших соседей находят ближайших соседей для заданного вектора запроса. Поиск ближайших соседей удобен для критически важных задач, таких как поиск похожих изображений или документов, извлечение на основе содержимого или обнаружение аномалий, которые требуют нахождения наиболее близких совпадений или похожих элементов.
Улучшенный пользовательский опыт— Используя семантический поиск, приложения могут предоставлять пользователям более релевантные и персонализированные результаты. Будь то предоставление релевантных рекомендаций, поиск визуально похожих изображений или нахождение документов с похожим содержанием, векторный поиск улучшает общий пользовательский опыт, предоставляя более целевые и значимые результаты.
Масштабируемость — Алгоритмы векторного поиска и структуры индексирования эффективно обрабатывают крупномасштабные наборы данных и многомерные пространства. Они обеспечивают быстрые операции поиска и извлечения, делая возможным выполнение запросов на основе сходства в реальном времени даже на огромных наборах данных.
Как работает векторная поисковая система?
С популярностью ИИ и LLM каждый инструмент разработчика, поисковая система и база данных добавляет возможности векторного поиска в свой набор функций, и из-за этого термины vector engine и Vector Search Engines часто используются взаимозаменяемо с Vector Databases. Vector Search Engines выполняют векторный семантический поиск (иногда называемый Vector Search). Векторный поиск — это техника нахождения похожих элементов или точек данных в наборе данных на основе их представления в виде векторов в многомерном пространстве. Каждый элемент отображается в точку в этом пространстве, при этом каждое измерение вектора представляет определенный признак. Процесс векторного поиска включает индексирование, запрос, ранжирование и извлечение.
Чтобы выполнить векторный поиск, сначала вы представляете элементы данных в виде векторов, используя такие техники, как Word2Vec или для текстовых данных. Структура данных индекса эффективно хранит эти векторы для быстрого извлечения, используя такие методы, как KD-trees или hash tables. Когда пользователь отправляет элемент запроса, он преобразуется в векторное представление, сравнивается с проиндексированными векторами с использованием метрик сходства, таких как cosine similarity или Euclidean distance, а наиболее похожие элементы извлекаются и ранжируются.
Примеры использования векторного поиска
- Поиск похожих изображений, видео, аудио
- Разработка лекарств с помощью ИИ
- Семантическая поисковая система
- Классификация последовательностей ДНК
- Система ответов на вопросы
- Рекомендательная система
- Обнаружение аномалий
- Retrieval Augmented Generation (RAG)
Теперь, когда мы рассмотрели основы векторного поиска, давайте перейдем к более техническим деталям, рассмотрев пример векторного представления слова, и закончим высокоуровневым обзором поиска ближайших соседей.
Сравнение эмбеддингов
Как только пользователи решают, что хотят приступить к созданию векторного поиска в своем решении, следующий вопрос, который они часто задают: «Какую модель машинного обучения мне следует использовать для создания векторных эмбеддингов.» Прежде чем выбрать модель, важно понять векторные эмбеддинги, сравнив несколько примеров. Давайте рассмотрим пару примеров векторных представлений слов. Для простоты мы будем использовать word2vec, старую модель, которая использует методологию обучения на основе skipgrams. BERT и другие современные модели на основе трансформеров смогут предоставить вам более контекстуализированные векторные представления слов, но для простоты мы остановимся на word2vec. Jay Alammar предлагает отличное руководство по word2vec, если вам интересно немного больше использовать модели машинного обучения.
Некоторая подготовительная работа
Перед началом нам нужно установить библиотеку gensim и загрузить модель word2vec.
% pip install gensim --disable-pip-version-check
% wget https://s3.amazonaws.com/dl4j-distribution/GoogleNews-vectors-negative300.bin.gz
% gunzip GoogleNews-vectors-negative300.bin
Requirement already satisfied: gensim in /Users/fzliu/.pyenv/lib/python3.8/site-packages (4.1.2)
Requirement already satisfied: smart-open>=1.8.1 in /Users/fzliu/.pyenv/lib/python3.8/site-packages (from gensim) (5.2.1)
Requirement already satisfied: numpy>=1.17.0 in /Users/fzliu/.pyenv/lib/python3.8/site-packages (from gensim) (1.19.5)
Requirement already satisfied: scipy>=0.18.1 in /Users/fzliu/.pyenv/lib/python3.8/site-packages (from gensim) (1.7.3)
--2022-02-22 00:30:34-- https://s3.amazonaws.com/dl4j-distribution/GoogleNews-vectors-negative300.bin.gz
Resolving s3.amazonaws.com (s3.amazonaws.com)... 52.216.20.165
Connecting to s3.amazonaws.com (s3.amazonaws.com)|52.216.20.165|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1647046227 (1.5G) [application/x-gzip]
Saving to: GoogleNews-vectors-negative300.bin.gz
GoogleNews-vectors- 100%[===================>] 1.53G 2.66MB/s in 11m 23s
2022-02-22 00:41:57 (2.30 MB/s) - GoogleNews-vectors-negative300.bin.gz saved [1647046227/1647046227]
gunzip: GoogleNews-vectors-negative300.bin: unknown suffix -- ignored
Теперь, когда мы выполнили всю подготовительную работу, необходимую для создания векторных представлений слов, загрузим обученную модель word2vec.
>>> from gensim.models import KeyedVectors
>>> model = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)
Пример 0: Марлон Брандо
Давайте посмотрим, как word2vec интерпретирует знаменитого актера Марлона Брандо.
>>> print(model.most_similar(positive=['Marlon_Brando']))
[('Brando', 0.757453978061676), ('Humphrey_Bogart', 0.6143958568572998), ('actor_Marlon_Brando', 0.6016287207603455), ('Al_Pacino', 0.5675410032272339), ('Elia_Kazan', 0.5594002604484558), ('Steve_McQueen', 0.5539456605911255), ('Marilyn_Monroe', 0.5512186884880066), ('Jack_Nicholson', 0.5440199375152588), ('Shelley_Winters', 0.5432392954826355), ('Apocalypse_Now', 0.5306933522224426)]
Марлон Брандо работал с Аль Пачино в «Крестном отце» и Элией Казаном в «Трамвае „Желание“». Он также снялся в «Апокалипсисе сегодня».
Пример 1: Если бы у всех королей на троне были свои королевы
Векторы можно складывать и вычитать друг из друга, чтобы продемонстрировать лежащие в основе семантические изменения.
>>> print(model.most_similar(positive=['king', 'woman'], negative=['man'], topn=1))
[('queen', 0.7118193507194519)]
Кто сказал, что инженеры не могут время от времени наслаждаться танцевальной поп-музыкой?
Пример 2: Apple — компания, фрукт, ... или и то и другое?
Слово "apple" может обозначать как компанию, так и вкусный красный фрукт. В этом примере мы видим, что Word2Vec сохраняет оба значения.
>>> print(model.most_similar(positive=['samsung', 'iphone'], negative=['apple'], topn=1))
>>> print(model.most_similar(positive=['fruit'], topn=10)[9:])
[('droid_x', 0.6324754953384399)]
[('apple', 0.6410146951675415)]
"Droid" относится к первому смартфону Samsung с 4G LTE ("Samsung" + "iPhone" - "Apple" = "Droid"), тогда как "apple" — 10-е ближайшее слово к "fruit".
Стратегии векторного поиска
Теперь, когда мы увидели силу векторных представлений, давайте кратко рассмотрим некоторые способы выполнения поиска ближайших соседей. Это не исчерпывающий список; мы лишь кратко пройдемся по некоторым распространенным методам, чтобы дать общее представление о том, как векторный поиск выполняется в больших масштабах. Обратите внимание, что некоторые из этих методов не исключают друг друга — например, можно использовать квантование вместе с разбиением пространства.
(Мы также подробно рассмотрим каждый из этих методов в будущих руководствах, так что следите за обновлениями.)
Линейный поиск
Самый простой, но самый наивный алгоритм поиска ближайшего соседа — это старый добрый линейный поиск: вычисление расстояния от вектора запроса до всех остальных векторов в векторной базе данных.
По очевидным причинам наивный поиск не работает при попытке масштабировать нашу векторную базу данных до десятков или сотен миллионов векторов. Но когда общее количество элементов в базе данных невелико, это на самом деле может быть самым эффективным способом выполнения векторного поиска, поскольку отдельная структура данных для индекса не требуется, а вставки и удаления могут быть реализованы довольно легко.
Из-за отсутствия пространственной сложности, а также постоянных пространственных накладных расходов, связанных с наивным поиском, этот метод часто может превосходить разбиение пространства даже при запросах по умеренному числу векторов.
Разбиение пространства
Разбиение пространства — это не один алгоритм, а скорее семейство алгоритмов, которые используют одну и ту же концепцию.
K-мерные деревья (kd-trees), пожалуй, наиболее известны в этом семействе и работают путем непрерывного деления пространства поиска пополам (разделения векторов на “левые” и “правые” корзины) способом, похожим на бинарные деревья поиска.
Инвертированный файловый индекс (IVF) также является формой разбиения пространства и работает путем назначения каждого вектора его ближайшему центроиду — затем поиск выполняется путем сначала определения ближайшего центроида вектора запроса и проведения поиска вокруг него, что значительно сокращает общее число векторов, которые нужно просмотреть. IVF — довольно популярная стратегия индексирования, и ее обычно комбинируют с другими алгоритмами индексирования для повышения производительности.
Квантование
Квантование — это техника уменьшения общего размера базы данных путем снижения точности векторов.
Скалярное квантование (SQ), например, работает путем умножения высокоточных векторов с плавающей точкой на скалярное значение, а затем приведения элементов получившегося вектора к ближайшим целым числам. Это не только уменьшает эффективный размер всей базы данных (например, в восемь раз при преобразовании из float64_t в int8_t), но и дает положительный побочный эффект в виде ускорения вычислений расстояния между векторами.
Продуктовое квантование (PQ) — еще одна техника квантования, работающая аналогично словарному сжатию. В PQ все векторы разбиваются на подвекторы одинакового размера, а затем каждый подвектор заменяется центроидом.
Иерархические навигируемые малые миры (HNSW)
Hierarchical Navigable Small Worlds — это алгоритм индексирования и извлечения на основе графов.
Он работает иначе, чем продуктовое квантование: вместо улучшения возможности поиска по базе данных за счет уменьшения ее эффективного размера, HNSW создает многослойный граф из исходных данных. Верхние слои содержат только "длинные связи", тогда как нижние слои содержат только "короткие связи" между векторами в базе данных (см. следующий раздел для обзора метрик расстояния между векторами). Отдельные связи графа создаются по аналогии со skip lists.
При такой архитектуре поиск становится довольно простым — мы жадно обходим самый верхний граф (тот, у которого самые длинные связи между векторами) в поисках вектора, ближайшего к нашему вектору запроса. Затем мы делаем то же самое для второго слоя, используя результат поиска на первом слое в качестве начальной точки. Это продолжается до тех пор, пока мы не завершим поиск на самом нижнем слое, результат которого становится ближайшим соседом вектора запроса.
HNSW, визуализация. Источник изображения: https://arxiv.org/abs/1603.09320
Approximate Nearest Neighbors Oh Yeah
Вероятно, это мой любимый алгоритм ANN просто из-за его игривого и неинтуитивного названия. Approximate Nearest Neighbors Oh Yeah (ANNOY) — это алгоритм на основе деревьев, популяризированный Spotify (он используется в их системе музыкальных рекомендаций). Несмотря на странное название, базовая концепция ANNOY на самом деле довольно проста — бинарные деревья.
ANNOY работает так: сначала случайным образом выбирает два вектора в базе данных и делит поисковое пространство пополам вдоль гиперплоскости, разделяющей эти два вектора. Это выполняется итеративно до тех пор, пока в каждом узле не останется меньше некоторого заранее заданного параметра NUM_MAX_ELEMS. Поскольку получающийся индекс по сути является бинарным деревом, это позволяет выполнять поиск со сложностью O(log n).
ANNOY, визуализация. Источник изображения: https://github.com/spotify/annoy
Часто используемые метрики сходства
Самые лучшие векторные базы данных бесполезны без метрик сходства — методов вычисления расстояния между двумя векторами. Существует множество метрик, поэтому здесь мы обсудим только наиболее часто используемое подмножество.
Метрики сходства векторов с плавающей точкой
Наиболее распространенные метрики сходства векторов с плавающей точкой — в произвольном порядке: L1 distance, L2 distance и cosine similarity. Первые два значения являются метриками расстояния (меньшие значения означают большее сходство, а большие значения — меньшее сходство), тогда как cosine similarity — это метрика сходства (большие значения означают большее сходство).
L1 distance также часто называют манхэттенским расстоянием — удачное название, связанное с тем, что, чтобы добраться из точки A в точку B на Манхэттене, нужно двигаться вдоль одного из двух перпендикулярных направлений. Второе уравнение, L2 distance, — это просто расстояние между двумя векторами в евклидовом пространстве. Третье и последнее уравнение — cosine distance, эквивалентное косинусу угла между двумя векторами. Обратите внимание, что уравнение для cosine similarity сводится к скалярному произведению нормализованных версий входных векторов a и b.
С помощью небольшой математики мы также можем показать, что L2 distance и cosine similarity фактически эквивалентны, когда речь идет о ранжировании по сходству для векторов единичной нормы:
Напомним, что векторы единичной нормы имеют величину 1:
С учетом этого получаем:
Поскольку у нас векторы единичной нормы, cosine distance сводится к скалярному произведению a и b (знаменатель в уравнении 3 выше оказывается равным 1):
По сути, для векторов единичной нормы L2 distance и cosine similarity функционально эквивалентны! Всегда помните о необходимости нормализовать ваши embeddings.
Метрики сходства бинарных векторов
Бинарные векторы, как следует из их названия, не имеют метрик, основанных на арифметике, как векторы с плавающей точкой. Метрики сходства для бинарных векторов вместо этого опираются либо на теорию множеств, либо на битовые операции, либо на сочетание того и другого (ничего страшного, я тоже ненавижу дискретную математику). Вот формулы для двух часто используемых метрик сходства бинарных векторов:
Первое уравнение называется расстоянием Танимото/Жаккара и, по сути, является мерой величины перекрытия между двумя бинарными векторами. Второе уравнение — это расстояние Хэмминга, и оно представляет собой подсчет количества элементов векторов a и b, которые отличаются друг от друга.
Скорее всего, вы можете спокойно игнорировать эти метрики сходства, поскольку большинство приложений используют косинусное сходство для эмбеддингов с плавающей точкой.
Подведение итогов
В этом руководстве мы рассмотрели векторный поиск, а также некоторые распространенные алгоритмы векторного поиска и метрики расстояния. Вот несколько ключевых выводов:
Векторы эмбеддингов — это мощные представления как с точки зрения расстояния между векторами, так и с точки зрения векторной арифметики. Применяя к эмбеддингам щедрое количество векторной алгебры, мы можем выполнять масштабируемый семантический анализ, используя лишь базовые математические операторы.
Semantic Vector search преодолевает ограничение поиска по ключевым словам, позволяя выполнять поиск на основе смысла вашего запроса. Он обеспечивает быстрое извлечение ответов с помощью векторного поиска.
Существует широкий спектр алгоритмов поиска приближенных ближайших соседей и/или типов индексов на выбор. Наиболее часто используемый сегодня — HNSW, но другой алгоритм индексирования может лучше подойти для вашего конкретного приложения, в зависимости от общего количества имеющихся у вас векторных эмбеддингов, а также длины каждого отдельного вектора.
Две основные метрики расстояния, используемые сегодня, — это L2/евклидово расстояние и косинусное расстояние. Эти две метрики при использовании на нормализованных эмбеддингах функционально эквивалентны.
Спасибо, что присоединились к нам в этом руководстве! Векторный поиск является ключевой частью Milvus, и так будет продолжаться. В будущих руководствах мы подробнее рассмотрим наиболее часто используемые алгоритмы ANNS — HNSW и ScaNN.
Еще раз взгляните на курсы Vector Database 101
- Введение в неструктурированные данные
- Что такое векторная база данных?
- Сравнение векторных баз данных, библиотек векторного поиска и плагинов векторного поиска
- Введение в Milvus
- Быстрый старт с Milvus
- Введение в поиск по векторному сходству
- Основы векторных индексов и инвертированный файловый индекс
- Скалярное квантование и произведенное квантование
- Иерархические навигируемые малые миры (HNSW)
- Приближенные ближайшие соседи — о да (ANNOY)
- Выбор правильного векторного индекса для вашего проекта
- DiskANN и алгоритм Vamana
Читать далее

Why We Built Vector Lakebase: Rethinking Unstructured Data Architecture for AI
Vector Lakebase: a unified, lake-native data foundation for AI workloads — and an answer to what happens after vector databases succeed.

Smarter Autoscaling in Zilliz Cloud: Always Optimized for Every Workload
With the latest upgrade, Zilliz Cloud introduces smarter autoscaling—a fully automated, more streamlined, elastic resource management system.

Zilliz Cloud Update: Smarter Autoscaling for Cost Savings, Stronger Compliance with Audit Logs, and More
What's new in Zilliz Cloud? Smarter autoscaling with scale-down, audit logs GA, enhanced SSO, and Milvus 2.6 in Private Preview.



