Швидкий пошук найближчого сусіда у 150-мірному просторі


13

Я хочу створити базу даних, використовуючи будь-яку з можливих RDBMS. У ній буде таблиця з приблизно 150 стовпцями. Мета - здійснити пошук найближчим сусідом деяких інших об'єктів. Отже, це NNS у 150-мірному просторі.

Я вже намагався використовувати деякі очевидні методи, такі як відстані L1 або L2, але, звичайно, потрібно багато часу для таблиць з багатьма рядками. Також я спробував подивитися на KD-дерево (зауважте, я його не тестував) та PG-Strom, але вони не є хорошим рішенням для даних з багатьма розмірами.

Чи можу я якось поліпшити швидкість описаного пошуку за допомогою математичних методів (як KD-дерево) або технічних методів (наприклад, PG-Strom)?

Я спробую використовувати будь-які RDBMS, які дозволяють підвищити швидкість роботи NNS. Але MySQL і PostgreSQL - це найбільш відповідна СУБД для мене.


1
Це інші проблеми. Просто задайте інше питання @ don-prog
Еван Керролл

Відповіді:


17

PostgreSQL 9.6 за допомогою cube

Спочатку встановіть розширення куба

CREATE EXTENSION cube;

Тепер ми створимо деякий n-мірний простір зі 100 000 точок у 50 вимірах. Крім того, ми додамо індекс GIST.

CREATE TEMP TABLE space_nd
AS
  SELECT i, cube(array_agg(random()::float)) AS c
  FROM generate_series(1,1e5) AS i
  CROSS JOIN LATERAL generate_series(1,50)
    AS x
  GROUP BY i;

CREATE INDEX ON space_nd USING gist ( c );
ANALYZE space_nd;

Тепер ми <->створимо єдину точку і скористаємося оператором, щоб знайти найближчу точку за допомогою евклейдової відстані.

WITH points AS (
  SELECT cube(array_agg(random()::float)) AS c
  FROM generate_series(1,50)
    AS x
)
SELECT i,
  pg_typeof(space_nd.c),
  pg_typeof(points.c),
  cube_distance(space_nd.c, points.c)
FROM space_nd
CROSS JOIN points
ORDER BY space_nd.c <-> points.c
LIMIT 5;

PostgreSQL 9.6+ підтримує інші оператори відстані cube. Усі вони можуть використовувати створений нами індекс GIST. А саме,

a <-> b float8  Euclidean distance between a and b.
a <#> b float8  Taxicab (L-1 metric) distance between a and b.
a <=> b float8  Chebyshev (L-inf metric) distance between a and b.

Це сказав, що є один застереження,

Щоб людям було складніше ламати речі, існує обмеження 100 на кількість розмірів кубів. Цей параметр встановлюється в cubedata.h, якщо вам потрібно щось більше.

Ви вимагаєте 150 розмірів. Це може бути незначним ускладненням.


1
На cubedata.hмоєму досвіді редагування не працює за 130 вимірами. Можливо, ви також можете змінити всі doubles або float8s у розширенні на float4, оскільки Postgres має обмеження на розмір індексу на рядок, від якого ви можете утримуватися, зменшуючи вдвічі, скільки байтів ви використовуєте на кожне число. Я зробив тестування і отримав більше розмірів таким чином, і IIRC я ​​минув 150, але я не зовсім впевнений.
судо

У мене була така
експерт

2

Спершу розглянемо зменшення розмірів (наприклад, Аналіз принципових компонентів).

Тоді ви робите NN в невеликій кількості розмірів з більш високою продуктивністю.

Ви можете використовувати Pl / R для виконання PCA всередині постгрес, якщо це необхідно.



0

Погляньте на https://github.com/a-mma/AquilaDB - це векторна база даних для зберігання функцій векторів разом з метаданими JSON. Зберігайте це разом зі своїми RDBMS та використовуйте метадані, щоб підтримувати перехресні посилання між даними.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.