在150维空间中进行快速最近邻居搜索


13

我想使用任何可能的RDBMS创建数据库。它将有一个大约150列的表格。目的是对某些其他对象执行最近邻搜索。因此,它是150维空间中的NNS。

我已经尝试使用一些显而易见的方法,例如L1或L2距离,但是对于具有多行的表,当然会花费很多时间。另外,我尝试查看KD树(请注意,我没有对其进行测试)和PG-Strom,但它们并不是多维数据的良好解决方案。

我可以使用数学方法(例如KD-tree)或技术方法(例如PG-Strom)以某种方式提高描述搜索的速度吗?

我将尝试使用允许提高NNS速度的任何RDBMS。但是MySQL和PostgreSQL是最适合我的DBMS。


1
这些是其他问题。只需问另一个问题@ don-prog
Evan Carroll

Answers:


17

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.

那就是一个警告,

为了使人们更难以打破事物,多维数据集的维数限制为100。如果需要更大的参数,可以在cubedata.h中设置。

您要求150个尺寸。这可能会带来轻微的并发症。


1
根据cubedata.h我的经验,对130尺寸的修改无效。也许您也可以将扩展名中的所有doubles或float8s 更改为float4,因为Postgres对每行索引大小有限制,可以通过将每个数字使用的字节数减半来避免。我进行了一些测试,并以此方式获得了更大的尺寸,而IIRC却超过了150,但我不确定。
sudo

我在尺寸限制上遇到了同样的问题,并创建了2048个限制的docker
专家

2

考虑首先执行降维(例如,主成分分析)。

然后,您将在少数维度上以更高的性能进行NN。

如果需要,可以使用Pl / R在postgres中执行PCA。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.