PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Postgresql k-najbliższy sąsiad (KNN) na wielowymiarowej kostce

PostgreSQL obsługuje operator odległości <-> i jak rozumiem, można to wykorzystać do analizy tekstu (z modułem pg_trgrm) i geometria typ danych.

Nie wiem, jak można go używać z więcej niż 1 wymiarem. Być może będziesz musiał zdefiniować własną funkcję odległości lub jakoś przekonwertować dane do jednej kolumny z tekstem lub typem geometrii. Na przykład, jeśli masz stół z 8 kolumnami (8-wymiarowy sześcian):

c1 c2 c3 c4 c5 c6 c7 c8
 1  0  1  0  1  0  1  2

Możesz go przekonwertować na:

c1 c2 c3 c4 c5 c6 c7 c8
 a  b  a  b  a  b  a  c

A potem do tabeli z jedną kolumną:

c1
abababac

Następnie możesz użyć (po utworzeniu gist indeks ):

SELECT c1, c1 <-> 'ababab'
 FROM test_trgm 
 ORDER BY c1 <-> 'ababab';

Przykład

Utwórz przykładowe dane

-- Create some temporary data
-- ! Note that table are created in tmp schema (change sql to your scheme) and deleted if exists !
drop table if exists tmp.test_data;

-- Random integer matrix 100*8 
create table tmp.test_data as (
   select 
      trunc(random()*100)::int as input_variable_1,
      trunc(random()*100)::int as input_variable_2, 
      trunc(random()*100)::int as input_variable_3,
      trunc(random()*100)::int as input_variable_4, 
      trunc(random()*100)::int as input_variable_5, 
      trunc(random()*100)::int as input_variable_6, 
      trunc(random()*100)::int as input_variable_7, 
      trunc(random()*100)::int as input_variable_8
   from 
      generate_series(1,100,1)
);

Przekształć dane wejściowe w tekst

drop table if exists tmp.test_data_trans;

create table tmp.test_data_trans as (
select 
   input_variable_1 || ';' ||
   input_variable_2 || ';' ||
   input_variable_3 || ';' ||
   input_variable_4 || ';' ||
   input_variable_5 || ';' ||
   input_variable_6 || ';' ||
   input_variable_7 || ';' ||
   input_variable_8 as trans_variable
from 
   tmp.test_data
);

To da ci jedną zmienną trans_variable gdzie przechowywane są wszystkie 8 wymiarów:

trans_variable
40;88;68;29;19;54;40;90
80;49;56;57;42;36;50;68
29;13;63;33;0;18;52;77
44;68;18;81;28;24;20;89
80;62;20;49;4;87;54;18
35;37;32;25;8;13;42;54
8;58;3;42;37;1;41;49
70;1;28;18;47;78;8;17

Zamiast || operatora możesz również użyć następującej składni (krótszej, ale bardziej zagadkowej):

select 
   array_to_string(string_to_array(t.*::text,''),'') as trans_variable
from 
   tmp.test_data t

Dodaj indeks

create index test_data_gist_index on tmp.test_data_trans using gist(trans_variable);

Test odległościUwaga:wybrałem jeden wiersz z tabeli - 52;42;18;50;68;29;8;55 - i użyto nieznacznie zmienionej wartości (42;42;18;52;98;29;8;55 ), aby sprawdzić odległość. Oczywiście w danych testowych będziesz mieć zupełnie inne wartości, ponieważ jest to macierz RANDOM.

select 
   *, 
   trans_variable <->  '42;42;18;52;98;29;8;55' as distance,
   similarity(trans_variable, '42;42;18;52;98;29;8;55') as similarity,
from 
   tmp.test_data_trans 
order by
   trans_variable <-> '52;42;18;50;68;29;8;55';

Możesz użyć operatora odległości <-> lub funkcji podobieństwa. Odległość =1 - Podobieństwo



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Pyspark:Usuń pusty znak UTF z ramki danych pyspark

  2. Jak znaleźć tabelę z określoną kolumną w postgresql

  3. Jaki jest najszybszy sposób na odbudowanie statystyk PostgreSQL od zera/zera za pomocą funkcji ANALYZE?

  4. Jak używać identyfikatorów UUID w SQLAlchemy?

  5. Dlaczego postgres nie używa indeksu w moim zapytaniu