בדף הזה מוסבר איך לבצע חיפוש של דמיון בין וקטורים ב-Spanner באמצעות פונקציות וקטוריות של מרחק קוסינוס, מרחק אוקלידי ומכפלה סקלרית, כדי למצוא את השכנים הקרובים ביותר (K-nearest neighbors). המידע הזה רלוונטי גם למסדי נתונים של ניב GoogleSQL וגם למסדי נתונים של ניב PostgreSQL. לפני שקוראים את הדף הזה, חשוב להבין את המושגים הבאים:
- מרחק אוקלידי: מדידת המרחק הקצר ביותר בין שני וקטורים.
- מרחק קוסינוס: מדידת הקוסינוס של הזווית בין שני וקטורים.
- מכפלה סקלרית: מחשבת את קוסינוס הזווית כפול מכפלת הגדלים של הווקטורים התואמים. אם אתם יודעים שכל ההטמעות הווקטוריות במערך הנתונים שלכם מנורמלות, אתם יכולים להשתמש ב-
DOT_PRODUCT()כפונקציית מרחק. - K-nearest neighbors (KNN): אלגוריתם ללמידה חישובית מבוקרת שמשמש לפתרון בעיות של סיווג או רגרסיה.
אתם יכולים להשתמש בפונקציות של מרחק וקטורי כדי לבצע חיפוש וקטורי של K-nearest neighbors (KNN) לתרחישי שימוש כמו חיפוש דמיון או יצירה משופרת של אחזור. Spanner תומך בפונקציות , ו-, שפועלות על הטמעות של וקטורים ומאפשרות למצוא את ה-KNN של ההטמעה של הקלט.COSINE_DISTANCE()EUCLIDEAN_DISTANCE()DOT_PRODUCT()
לדוגמה, אחרי שיוצרים ושומרים את נתוני Spanner התפעוליים כהטבעות וקטוריות, אפשר לספק את ההטבעות הווקטוריות האלה כפרמטר קלט בשאילתה כדי למצוא את הווקטורים הקרובים ביותר במרחב N-ממדי, ולחפש פריטים דומים או קשורים מבחינה סמנטית.
כל שלוש פונקציות המרחק מקבלות את הארגומנטים vector1 ו-vector2, שהם מסוג array<>, וצריכים להיות בעלי אותם ממדים ואותו אורך. מידע נוסף על הפונקציות האלה זמין במאמרים הבאים:
-
COSINE_DISTANCE()ב-GoogleSQL -
EUCLIDEAN_DISTANCE()ב-GoogleSQL -
DOT_PRODUCT()ב-GoogleSQL - פונקציות מתמטיות ב-PostgreSQL
(
spanner.cosine_distance(),spanner.euclidean_distance()ו-spanner.dot_product()) - אפשר לבחור מבין פונקציות המרחק בין וקטורים כדי למדוד את הדמיון בין הטמעות וקטוריות.
דוגמאות
בדוגמאות הבאות מוצגות שאילתות חיפוש KNN, שאילתות חיפוש KNN על נתונים מחולקים ושימוש באינדקס משני עם KNN.
בכל הדוגמאות נעשה שימוש ב-EUCLIDEAN_DISTANCE(). אפשר גם להשתמש ב-COSINE_DISTANCE(). בנוסף, אם כל ההטמעות של הווקטורים במערך הנתונים שלכם מנורמלות, אתם יכולים להשתמש ב-DOT_PRODUCT() כפונקציית מרחק.
דוגמה 1: חיפוש KNN
נניח שיש לכם טבלה Documents עם עמודה (DocEmbedding) של הטמעות טקסט שחושבו מראש מהעמודה DocContents bytes.
GoogleSQL
CREATE TABLE Documents (
UserId INT64 NOT NULL,
DocId INT64 NOT NULL,
Author STRING(1024),
DocContents BYTES(MAX),
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)
);
בהנחה שהטמעת הקלט של 'בייסבול, אבל לא בייסבול מקצועי' היא המערך [0.3, 0.3, 0.7, 0.7], אפשר למצוא את חמשת המסמכים הקרובים ביותר שתואמים לשאילתה הבאה:
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;
התוצאות הצפויות של הדוגמה הזו:
Documents
+---------------------------+-----------------+
| DocId | DocEmbedding |
+---------------------------+-----------------+
| 24 | [8, ...] |
+---------------------------+-----------------+
| 25 | [6, ...] |
+---------------------------+-----------------+
| 26 | [3.2, ...] |
+---------------------------+-----------------+
| 27 | [38, ...] |
+---------------------------+-----------------+
| 14229 | [1.6, ...] |
+---------------------------+-----------------+
דוגמה 2: חיפוש KNN בנתונים שחולקו למחיצות
אפשר לשנות את השאילתה בדוגמה הקודמת על ידי הוספת תנאים לסעיף WHERE כדי להגביל את החיפוש הווקטורי לקבוצת משנה של הנתונים. אחד השימושים הנפוצים הוא חיפוש בנתונים מחולקים, כמו שורות ששייכות לUserId ספציפי.
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;
התוצאות הצפויות של הדוגמה הזו:
Documents
+-----------+-----------------+-----------------+
| UserId | DocId | DocEmbedding |
+-----------+-----------------+-----------------+
| 18 | 234 | [12, ...] |
+-----------+-----------------+-----------------+
| 18 | 12 | [1.6, ...] |
+-----------+-----------------+-----------------+
| 18 | 321 | [22, ...] |
+-----------+-----------------+-----------------+
| 18 | 432 | [3, ...] |
+-----------+-----------------+-----------------+
דוגמה 3: חיפוש KNN בטווחים של אינדקס משני
אם מסנן משפטי ה-WHERE שבו אתם משתמשים לא מהווה חלק מהמפתח הראשי של הטבלה,
אפשר ליצור אינדקס משני כדי להאיץ את הפעולה באמצעות סריקה של אינדקס בלבד.
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;
התוצאות הצפויות של הדוגמה הזו:
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, ...] |
+------------+-----------------+-----------------+
המאמרים הבאים
מידע נוסף על הפונקציות של GoogleSQL
COSINE_DISTANCE(),EUCLIDEAN_DISTANCE(),DOT_PRODUCT()מידע נוסף על הפונקציות PostgreSQL
spanner.cosine_distance(),spanner.euclidean_distance(),spanner.dot_product()מידע נוסף על בחירה בין פונקציות של מרחק וקטורי למדידת הדמיון בין הטמעות וקטוריות