web-dev-qa-db-ja.com

150次元空間での最近傍検索

可能なRDBMSのいずれかを使用してデータベースを作成したい。約150列のテーブルがあります。目的は、いくつかの他のオブジェクトの最近傍探索を実行することです。つまり、これは150次元空間のNNSです。

L1またはL2距離のような明らかな方法をすでに使用しようとしましたが、もちろん、行数が多いテーブルの場合は時間がかかります。また、KDツリー(テストしていないことに注意してください)とPG-Stromを確認しようとしましたが、これらは、多くの次元を持つデータには適していません。

数学の方法(KD-treeなど)または技術的な方法(PG-Stromなど)を使用して、説明された検索の速度をどうにかして向上させることができますか?

NNSの速度を改善できるRDBMSを使用してみます。しかし、MySQLとPostgreSQLは私にとって最も適切なDBMSです。

13
don-prog

cube を使用するPostgreSQL 9.6

最初に cube拡張機能をインストールします

CREATE EXTENSION cube;

次に、50次元で100,000ポイントのn次元空間を作成します。さらに、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.

とはいえ、注意点が1つあります。

人々が物事を壊しにくくするために、キューブの次元数は100に制限されています。これは、何か大きなものが必要な場合に、cubedata.hで設定されます。

150の寸法を要求します。それは小さな合併症をもたらすかもしれません。

17
Evan Carroll

最初に次元削減を実行することを検討してください(例:主成分分析)。

次に、より高いパフォーマンスで少数の次元でNNを実行します。

必要に応じて、Pl/Rを使用してpostgres内でPCAを実行できます。

2
Robin Chauhan

https://github.com/a-mma/AquilaDB を見てください。これは、JSONメタデータとともに機能ベクトルを格納するためのベクトルデータベースです。 RDBMSと一緒に保管し、メタデータを使用してデータ間の相互参照を維持してください。

0
a_മ്മ

FLANN and OpenCV をご覧ください。

残念ながら、RDBMSシステムへの統合については知りません。しかし、たとえば、Posgresでは 化学構造情報の統合 があります。したがって、原則としてこれは可能です。

0
Grimaldi