Tìm kiếm hàng xóm gần nhất nhanh chóng trong không gian 150 chiều


13

Tôi muốn tạo một cơ sở dữ liệu bằng cách sử dụng bất kỳ RDBMS nào có thể. Nó sẽ có một bảng với khoảng 150 cột. Mục tiêu là để thực hiện tìm kiếm hàng xóm gần nhất của một số đối tượng khác. Vì vậy, đó là một NNS trong không gian 150 chiều.

Tôi đã cố gắng sử dụng một số phương thức rõ ràng như khoảng cách L1 hoặc L2 nhưng tất nhiên phải mất rất nhiều thời gian cho các bảng có nhiều hàng. Ngoài ra, tôi đã cố gắng nhìn vào cây KD (lưu ý rằng tôi đã không kiểm tra nó) và PG-Strom nhưng chúng không phải là một giải pháp tốt cho dữ liệu có nhiều chiều.

Tôi bằng cách nào đó có thể cải thiện tốc độ tìm kiếm được mô tả bằng các phương pháp toán học (như cây KD) hoặc phương pháp công nghệ (như PG-Strom) không?

Tôi sẽ cố gắng sử dụng bất kỳ RDBMS nào cho phép cải thiện tốc độ của NNS. Nhưng MySQL và PostgreSQL là DBMS thích hợp nhất đối với tôi.


1
Đây là những vấn đề khác. Đơn giản chỉ cần hỏi một câu hỏi khác @ don-prog
Evan Carroll

Câu trả lời:


16

PostgreSQL 9.6 sử dụng cube

Đầu tiên cài đặt phần mở rộng khối

CREATE EXTENSION cube;

Bây giờ chúng tôi sẽ tạo ra một số không gian n chiều với 100.000 điểm trong 50 chiều. Ngoài ra, chúng tôi sẽ thêm một chỉ số 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;

Bây giờ chúng ta sẽ tạo một điểm duy nhất và sử dụng toán hạng <->để tìm điểm gần nhất bằng khoảng cách Eucledian.

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;

PostgreQuery 9.6+ hỗ trợ các nhà khai thác khoảng cách khác cube. Tất cả đều có thể sử dụng chỉ số GIST mà chúng tôi đã tạo. Cụ thể là

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.

Điều đó nói rằng có một cảnh báo,

Để làm cho mọi người khó phá vỡ mọi thứ hơn, có giới hạn 100 về số lượng kích thước của hình khối. Điều này được đặt trong cubedata.h nếu bạn cần một cái gì đó lớn hơn.

Bạn yêu cầu 150 kích thước. Điều đó có thể trình bày một biến chứng nhỏ.


1
Chỉnh sửa để cubedata.hkhông hoạt động quá 130 chiều theo kinh nghiệm của tôi. Có lẽ bạn cũng có thể thay đổi tất cả doublehoặc float8trong phần mở rộng thành float4, vì Postgres có giới hạn về kích thước chỉ mục trên mỗi hàng mà bạn có thể tránh xa bằng cách giảm một nửa số byte bạn sử dụng cho mỗi số. Tôi đã thực hiện một số thử nghiệm và có nhiều kích thước hơn theo cách đó và IIRC tôi đã vượt qua 150, nhưng tôi không hoàn toàn chắc chắn.
sudo

Tôi gặp vấn đề tương tự với giới hạn về kích thước và tạo ra hình ảnh docker
chuyên gia

2

Trước tiên hãy xem xét thực hiện giảm kích thước (ví dụ: Phân tích thành phần nguyên tắc).

Sau đó, bạn đang làm NN với số lượng kích thước nhỏ với hiệu suất cao hơn.

Bạn có thể sử dụng Pl / R để thực hiện PCA bên trong postgres nếu cần.



0

Hãy xem https://github.com/a-mma/AquilaDB, đây là một cơ sở dữ liệu vectơ để lưu trữ các vectơ đặc trưng cùng với siêu dữ liệu JSON. Giữ nó cùng với RDBMS của bạn và sử dụng siêu dữ liệu để duy trì tham chiếu chéo giữa các dữ liệu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.