KNN
Введение
Поиск ближайшего соседа (NN) - это задача оптимизации, заключающаяся в нахождении ближайшей точки (или набора точек) в заданном наборе данных к заданной точке запроса. Близость может быть определена в терминах метрики расстояния или сходства.
Обобщением задачи NN является задача k-NN, где от нас требуется найти k ближайших точек к точке запроса. Это может быть полезно в различных приложениях, таких как классификация изображений, рекомендательные системы и многое другое.
Решения задачи k-NN разбивается на два крупных подкласса методов: точные и приближенные. В данном документе речь пойдет о точном подходе, а именно о точном подходе методом грубой силы.
В основе метода лежит вычисление расстояния от точки запроса до каждой другой точки в базе данных. Этот алгоритм, также известный как наивный подход, имеет время выполнения O(dn)
, где n
- количество точек в наборе данных, а d
- его размерность.
Преимуществом метода является отсутствие необходимости в дополнительных структурах данных, вроде специализированных векторных индексов.
Недостатком является необходимость полного перебора данных. Но данный недостаток является несущественным в случаях, когда произошла предварительная фильтрация данных, например, по идентификатору пользователя.
Пример:
$TargetEmbedding = Knn::ToBinaryString([1.2f, 2.3f, 3.4f, 4.5f]);
SELECT id, fact, embedding FROM Facts
WHERE user="Williams"
ORDER BY Knn::CosineDistance(embedding, $TargetEmbedding)
LIMIT 10
Типы данных
В математике для хранения точек используется вектор вещественных чисел.
В YDB операции будут происходить над строковым типом данных String
, который является бинарным сериализованным представлением List<Float>
.
Функции
Функции работы с векторами реализовываются в виде пользовательских функций (UDF) в модуле Knn
.
Функции расстояния и сходства
Функции расстояния и сходства принимают на вход два списка вещественных чисел и возвращает расстояние/сходство между ними.
Примечание
Функции расстояния возвращает малое значение для близких векторов, функции сходства возвращают большие значения для близких векторов. Это следует учитывать в порядке сортировки.
Фукнции сходства:
- скалярное произведение
InnerProductSimilarity
(сумма произведений координат) - косинусное сходство
CosineSimilarity
(скалярное произведение / длины векторов)
Фукнции расстояния:
- косинусное расстояние
CosineDistance
( 1 - косинусное сходство)
Сигнатуры функций
Knn::InnerProductSimilarity(String{Flags:AutoMap}, String{Flags:AutoMap})->Float?
Knn::CosineSimilarity(String{Flags:AutoMap}, String{Flags:AutoMap})->Float?
Knn::CosineDistance(String{Flags:AutoMap}, String{Flags:AutoMap})->Float?
В случае ошибки вычисления, фукнции возвращают NULL
.
Функции преобразования вектора в бинарное представление
Функции преобразования нужны для сериализации множества вектора во внутреннее бинарное представление и обратно.
Бинарное представление вектора будет храниться в YDB в типе String
.
Сигнатуры функций
Knn::ToBinaryString(List<Float>{Flags:AutoMap})->String
Knn::FromBinaryString(String{Flags:AutoMap})->List<Float>?
Примеры
Создание таблицы
CREATE TABLE Facts (
id Uint64, // Id of fact
user Utf8, // User name
fact Utf8, // Human-readable description of a user fact
embedding String, // Binary representation of embedding vector (result of Knn::ToBinaryString)
PRIMARY KEY (id)
)
Добавление векторов
UPSERT INTO Facts (id, user, fact, embedding)
VALUES (123, "Williams", "Full name is John Williams", Knn::ToBinaryString([1.0f, 2.0f, 3.0f, 4.0f]))
Точный поиск ближайших векторов
$TargetEmbedding = Knn::ToBinaryString([1.2f, 2.3f, 3.4f, 4.5f]);
SELECT * FROM Facts
WHERE user="Williams"
ORDER BY Knn::CosineDistance(embedding, $TargetEmbedding)
LIMIT 10