Recherche rapide du plus proche voisin dans l'espace de 150 dimensions


13

Je veux créer une base de données en utilisant l'un des SGBDR possibles. Il aura un tableau avec environ 150 colonnes. L'objectif est d'effectuer la recherche du plus proche voisin de certains autres objets. C'est donc un NNS dans l'espace de 150 dimensions.

J'ai déjà essayé d'utiliser des méthodes évidentes comme les distances L1 ou L2 mais bien sûr, cela prend beaucoup de temps pour les tableaux avec de nombreuses lignes. J'ai également essayé de regarder l'arbre KD (notez que je ne l'ai pas testé) et PG-Strom mais ils ne sont pas une bonne solution pour les données à plusieurs dimensions.

Puis-je en quelque sorte améliorer la vitesse de la recherche décrite en utilisant des méthodes mathématiques (comme KD-tree) ou des méthodes techniques (comme PG-Strom)?

J'essaierai d'utiliser n'importe quel SGBDR qui permettra d'améliorer la vitesse du NNS. Mais MySQL et PostgreSQL sont le SGBD le plus approprié pour moi.


1
Ce sont d'autres problèmes. Posez simplement une autre question @ don-prog
Evan Carroll

Réponses:


17

PostgreSQL 9.6 utilisation cube

Installez d'abord l' extension du cube

CREATE EXTENSION cube;

Nous allons maintenant créer un espace à n dimensions avec 100 000 points dans 50 dimensions. De plus, nous ajouterons un index 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;

Nous allons maintenant générer un seul point et utiliser l' <->opératrice pour trouver le point le plus proche en utilisant la distance euclédienne.

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+ prend en charge d'autres opérateurs de distance cube. Tous ces éléments peuvent utiliser l'index GIST que nous avons créé. À savoir,

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.

Cela dit, il y a une mise en garde,

Pour qu'il soit plus difficile pour les gens de casser des choses, il y a une limite de 100 sur le nombre de dimensions des cubes. Ceci est défini dans cubedata.h si vous avez besoin de quelque chose de plus grand.

Vous demandez 150 dimensions. Cela peut présenter une complication mineure.


1
La modification de cubedata.hne fonctionne pas au-delà de 130 dimensions selon mon expérience. Peut-être que vous pouvez également changer tous les doubles ou float8s dans l'extension float4, car Postgres a une limite sur la taille d'index par ligne que vous pouvez éviter en réduisant de moitié le nombre d'octets que vous utilisez sur chaque numéro. J'ai fait quelques tests et obtenu plus de dimensions de cette façon, et l'IIRC j'ai dépassé 150, mais je ne suis pas totalement sûr.
sudo

J'ai eu le même problème avec la limite des dimensions et créé une image docker avec une limite de 2048: hub.docker.com/r/expert/postgresql-large-cube
expert

2

Envisagez d'effectuer une réduction de dimension en premier (par exemple, analyse des composants principaux).

Ensuite, vous faites NN dans un petit nombre de dimensions avec des performances plus élevées.

Vous pouvez utiliser Pl / R pour effectuer PCA à l'intérieur de postgres si nécessaire.



0

Jetez un œil à https://github.com/a-mma/AquilaDB, c'est une base de données vectorielles pour stocker les vecteurs de fonctionnalités avec les métadonnées JSON. Conservez-le avec votre SGBDR et utilisez des métadonnées pour maintenir la référence croisée entre les données.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.