Melakukan penelusuran kemiripan vektor di Spanner dengan menemukan K-nearest neighbors

Halaman ini menjelaskan cara melakukan penelusuran kesamaan vektor di Spanner menggunakan fungsi vektor jarak kosinus, jarak Euclidean, dan perkalian titik untuk menemukan tetangga terdekat K. Sebelum membaca halaman ini, Anda harus memahami konsep berikut:

  • Jarak Euclidean: mengukur jarak terpendek antara dua vektor.
  • Jarak kosinus: mengukur kosinus sudut antara dua vektor.
  • Dot product: menghitung kosinus sudut yang dikalikan dengan produk dari magnitudo vektor yang sesuai. Jika Anda tahu bahwa semua penyematan vektor dalam set data Anda dinormalisasi, Anda dapat menggunakan DOT_PRODUCT() sebagai fungsi jarak.
  • Tetangga terdekat (KNN): algoritma machine learning terpandu yang digunakan untuk memecahkan masalah klasifikasi atau regresi.

Anda dapat menggunakan fungsi jarak vektor untuk melakukan penelusuran vektor tetangga terdekat (KNN) untuk kasus penggunaan seperti penelusuran kesamaan atau pembuatan yang ditingkatkan pengambilan. Spanner mendukung fungsi COSINE_DISTANCE(), EUCLIDEAN_DISTANCE(), dan DOT_PRODUCT(), yang beroperasi pada embedding vektor, sehingga Anda dapat menemukan KNN dari embedding input.

Misalnya, setelah membuat dan menyimpan data Spanner operasional sebagai penyematan vektor, Anda dapat menyediakan penyematan vektor ini sebagai parameter input dalam kueri untuk menemukan vektor terdekat dalam ruang berdimensi N untuk menelusuri item yang mirip secara semantik atau terkait.

Ketiga fungsi jarak menggunakan argumen vector1 dan vector2, yang berjenis array<>, dan harus terdiri dari dimensi yang sama dan memiliki panjang yang sama. Untuk mengetahui detail selengkapnya tentang fungsi ini, lihat:

Contoh

Contoh berikut menunjukkan penelusuran KNN, penelusuran KNN pada data yang dipartisi, dan menggunakan indeks sekunder dengan KNN.

Semua contoh menggunakan EUCLIDEAN_DISTANCE(). Anda juga dapat menggunakan COSINE_DISTANCE(). Selain itu, jika semua embedding vektor dalam set data Anda dinormalisasi, Anda dapat menggunakan DOT_PRODUCT() sebagai fungsi jarak.

Pertimbangkan tabel Documents yang memiliki kolom (DocEmbedding) dari penyematan teks yang telah dihitung sebelumnya 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 NOT NULL,
DocId        bigint NOT NULL,
Author       varchar(1024),
DocContents  bytea,
DocEmbedding float4[],
PRIMARY KEY  (UserId, DocId)
);

Dengan asumsi bahwa penyematan input untuk "baseball, but not professional baseball" 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 dalam contoh sebelumnya dapat diubah dengan menambahkan kondisi ke klausa WHERE untuk membatasi penelusuran vektor ke sebagian data Anda. Salah satu aplikasi umum untuk hal ini adalah menelusuri data yang dipartisi, seperti baris yang termasuk dalam UserId tertentu.

GoogleSQL

SELECT UserId, DocId, DocEmbedding FROM Documents
WHERE UserId=18
ORDER BY EUCLIDEAN_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.euclidean_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 di seluruh 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