Melakukan penelusuran vektor kesamaan di Spanner dengan menemukan tetangga K-terdekat

Halaman ini menjelaskan cara melakukan penelusuran vektor kemiripan di Spanner menggunakan fungsi jarak kosinus dan vektor jarak Euclidean untuk menemukan tetangga K-terdekat. Sebelum membaca halaman ini, penting bagi Anda untuk memahami konsep-konsep berikut:

  • Jarak kosinus: mengukur kosinus sudut antara dua vektor.
  • Jarak Euclidean: mengukur jarak terpendek antara dua vektor.
  • K-nearestest (KNN): algoritma supervised machine learning yang digunakan untuk menyelesaikan masalah klasifikasi atau regresi.

Anda dapat menggunakan fungsi jarak vektor untuk melakukan penelusuran vektor K-nearestest (KNN) untuk kasus penggunaan seperti penelusuran kemiripan atau pembuatan yang ditambah. Spanner mendukung fungsi COSINE_DISTANCE() dan EUCLIDEAN_DISTANCE(), yang beroperasi di embedding vektor, sehingga Anda dapat menemukan KNN dari embedding input.

Misalnya, setelah membuat dan menyimpan data Spanner operasional sebagai embedding vektor, Anda dapat menyediakan embedding vektor ini sebagai parameter input dalam kueri guna menemukan vektor terdekat di ruang N-dimensi untuk menelusuri item yang serupa atau terkait secara semantik.

Bergantung pada cara embedding dihasilkan dan jenis penelusuran yang diinginkan, jarak kosinus atau fungsi jarak Euclidean dapat menghasilkan hasil penelusuran yang secara subyektif lebih baik daripada fungsi lainnya. Kedua fungsi jarak menggunakan argumen vector1 dan vector2, yang berjenis array<>, dan harus terdiri dari dimensi yang sama serta memiliki panjang yang sama. Untuk mengetahui detail selengkapnya tentang fungsi ini, lihat:

Contoh

Contoh berikut memberikan kasus penggunaan terkait kapan harus menggunakan COSINE_DISTANCE() atau EUCLIDEAN_DISTANCE().

Pertimbangkan tabel Documents yang memiliki kolom (DocEmbedding) embedding teks yang telah diprakomputasi dari kolom byte DocContents.

GoogleSQL

CREATE TABLE Documents (
UserId       INT64 NOT NULL,
DocId        INT64 NOT NULL,
Author       STRING(1024),
DocContents  BYTES,
DocEmbedding ARRAY<FLOAT32>
) PRIMARY KEY (UserId, DocId);

PostgreSQL

CREATE TABLE Documents (
UserId       bigint primary key,
DocId        bigint primary key,
Author       varchar(1024),
DocContents  bytea,
DocEmbedding float4[]
);

Dengan asumsi bahwa input embedding untuk "bisbol, tetapi bukan bisbol profesional" adalah array [0.3, 0.3, 0.7, 0.7], Anda dapat menemukan lima dokumen terdekat yang cocok, dengan kueri berikut:

GoogleSQL

SELECT DocId, DocEmbedding FROM Documents
ORDER BY EUCLIDEAN_DISTANCE(DocEmbedding,
ARRAY<FLOAT32>[0.3, 0.3, 0.7, 0.8])
LIMIT 5;

PostgreSQL

SELECT DocId, DocEmbedding FROM Documents
ORDER BY spanner.euclidean_distance(DocEmbedding,
'{0.3, 0.3, 0.7, 0.8}'::float4[])
LIMIT 5;

Hasil yang diharapkan dari contoh ini:

Documents
+---------------------------+-----------------+
| DocId                     | DocEmbedding    |
+---------------------------+-----------------+
| 24                        | [8, ...]        |
+---------------------------+-----------------+
| 25                        | [6, ...]        |
+---------------------------+-----------------+
| 26                        | [3.2, ...]      |
+---------------------------+-----------------+
| 27                        | [38, ...]       |
+---------------------------+-----------------+
| 14229                     | [1.6, ...]      |
+---------------------------+-----------------+

Contoh 2: Penelusuran KNN pada data yang dipartisi

Kueri pada contoh sebelumnya dapat diubah dengan menambahkan kondisi ke klausa WHERE untuk membatasi penelusuran vektor ke subset data Anda. Salah satu penerapan umumnya adalah untuk menelusuri data yang dipartisi, seperti baris yang termasuk dalam UserId tertentu.

GoogleSQL

SELECT UserId, DocId, DocEmbedding FROM Documents
WHERE UserId=18
ORDER BY COSINE_DISTANCE(DocEmbedding,
ARRAY<FLOAT32>[0.3, 0.3, 0.7, 0.8])
LIMIT 5;

PostgreSQL

SELECT UserId, DocId, DocEmbedding FROM Documents
WHERE UserId=18
ORDER BY spanner.cosine_distance(DocEmbedding,
'{0.3, 0.3, 0.7, 0.8}'::float4[])
LIMIT 5;

Hasil yang diharapkan dari contoh ini:

Documents
+-----------+-----------------+-----------------+
| UserId    | DocId           | DocEmbedding    |
+-----------+-----------------+-----------------+
| 18        | 234             | [12, ...]       |
+-----------+-----------------+-----------------+
| 18        | 12              | [1.6, ...]      |
+-----------+-----------------+-----------------+
| 18        | 321             | [22, ...]       |
+-----------+-----------------+-----------------+
| 18        | 432             | [3, ...]        |
+-----------+-----------------+-----------------+

Contoh 3: Penelusuran KNN pada rentang indeks sekunder

Jika filter klausa WHERE yang Anda gunakan bukan bagian dari kunci utama tabel, Anda dapat membuat indeks sekunder untuk mempercepat operasi dengan pemindaian khusus indeks.

GoogleSQL

CREATE INDEX DocsByAuthor
ON Documents(Author)
STORING (DocEmbedding);

SELECT Author, DocId, DocEmbedding FROM Documents
WHERE Author="Mark Twain"
ORDER BY EUCLIDEAN_DISTANCE(DocEmbedding,
   <embeddings for "book about the time traveling American">)
LIMIT 5;

PostgreSQL

CREATE INDEX DocsByAuthor
ON Documents(Author)
INCLUDE (DocEmbedding);

SELECT Author, DocId, DocEmbedding FROM Documents
WHERE Author="Mark Twain"
ORDER BY spanner.euclidean_distance(DocEmbedding,
   <embeddings for "that book about the time traveling American">)
LIMIT 5;

Hasil yang diharapkan dari contoh ini:

Documents
+------------+-----------------+-----------------+
| Author     | DocId           | DocEmbedding    |
+------------+-----------------+-----------------+
| Mark Twain | 234             | [12, ...]       |
+------------+-----------------+-----------------+
| Mark Twain | 12              | [1.6, ...]      |
+------------+-----------------+-----------------+
| Mark Twain | 321             | [22, ...]       |
+------------+-----------------+-----------------+
| Mark Twain | 432             | [3, ...]        |
+------------+-----------------+-----------------+
| Mark Twain | 375             | [9, ...]        |
+------------+-----------------+-----------------+

Langkah selanjutnya