ChatGPT 掀起 AI 熱潮後,「讓模型變成專家」的需求激增,帶動了 RAG 系統的實作熱潮,向量資料庫作為 RAG 的關鍵技術也跟著爆紅。
向量是用來表示多維度資料的數學工具,本質上是一組有順序的數值,每個數值對應一個特定的維度。以描述人為例,可以將其各種特徵(如身高、體重、髮型、年齡、興趣等)轉換成不同維度的數值,再組合成向量,不同向量代表不同的人。
當收集了大量的向量(例如一群人),就可以運用數學或機器學習的方法,找出這些向量之間的規律,建立預測模型,例如輸入身高,年齡,預測體重。
除了儲存向量之外,更重要的是查詢,與 SQL 資料庫以精準或範圍條件查詢不同,向量資料庫的核心功能是「近似向量查詢」,這個近似不是 LIKE 語法,而是使用數學公式找出相近的向量,常見於推薦系統、語意搜尋等應用。
實作電影推薦功能時,若用戶 A 喜歡動作片,簡單方式是依照電影在動作分類的表現分數排序,取最高的推薦給他,但真實用戶喜好是多面向的,例如喜歡愛情動作片,此時排序會失真,例如先用動作排序會找到不可能的任務,先用愛情排序會找到真愛每一天,都不符合愛情動作的喜好。
竟然是多維度的資料,就要用向量運算,假設有兩組向量,一組是用戶對電影類別的喜好分數,一組是電影在不同類別的表現分數,從向量中找出符合用戶喜好的電影,其中一個方式是向量的內積 (inner product) - 不同維度相乘後相加 (1,1,1) * (2,2,2) = (1 * 2) + (1 * 2) + (1 * 2) = 6。
內積能整合所有面向的數值,內積越大代表這兩個向量越相似。
如果 不可能的任務 向量是 (1000, 0) 動作表現分數超高,內積就會失靈,因此衍生 cosine similarity 公式,去除向量大小,只關注向量的角度,將動作維度表現成 x 軸,愛情維度表現成 y 軸,不可能的任務 就是一條貼著 x 軸的直線,角度為 0,假設小明喜好向量是 (5, 5) 角度為 45 度,而 史密斯任務 向量為 (20, 20) 角度一樣 45 度,角度落差越小越相近,依照內積會推薦不可能的任務,但依照 cosine similarity 則會推薦史密斯任務。
實務上內積跟 cosine similarity 不是二選一,因為內積可以篩選表現最好的向量,而 cosine similarity 則篩選傾向最相符的向量,實作推薦系統時,可先用內積找出前 N 個表現最好向量,在用 cosine similarity 找出傾向最相符的。
實際推薦系統中,無法取得用戶對各類型的偏好向量,取而代之是用戶過去的觀影紀錄。假設只知道某位用戶看過的電影,以及這些電影在各類型上的表現分數(例如動作、愛情的強度),那要怎麼推薦新電影?
這時,可將用戶的觀影紀錄向量「平均起來」,形成一個代表整體偏好的向量。而我們希望系統推薦給他一些風格接近過去觀影紀錄的電影,在該情境下,向量值越大不一定越匹配。
以動作片為例,用戶喜歡有打戲但不要太多,因此與其找最高分的,不如找整體分數與用戶過去喜好「距離最接近」的電影。這時可用 L2 Distance(歐式距離)來計算兩個向量在多維空間中的距離,距離越短,代表風格越相似。
計算相似的數學公式雖不複雜,但從海量數據中找出最相似的向量也會花很多時間,就像 SQL DB 有 Index (B+Tree) 加速查詢,向量資料庫也有加速查詢的索引結構,常見的是 Inverted File Index (IVF)。
IVF 使用 K-means 演算法將資料分成 K 組,每組資料有一個 centroid 向量作為代表,查詢近似向量時,先跟 K 個 centroid 做近似運算,找出最近的 centroid 後從該組資料中找出最相近向量,時間複雜從 O(n) 變成 O(n/k)。
而 K-means 分類流程為:
將資料轉換成向量的過程稱為 embedding,常見的 embedding 多為 model embedding,透過機器學習模型訓練出一個向量空間,讓相近的資料在空間中彼此靠近,不相似的資料則分得較遠。
另一種 embedding 為 primitive embedding,是人工定義維度跟規則,例如 one-hot encoding 或基於規則的欄位轉換,缺點是擴展性差,如果出現跳脫規則的資料就會導致預測或是相似查詢出問題。
不過 model embedding 也有缺點,就是不可解釋性,無法說明各維度代表的意思,只知道在這些維度定義中,相似的資料在向量空間中比較靠近。
如果想透過 model embedding 將電影轉成向量,可將電影的劇情描述輸入 BERT 模型獲得語意向量,相同語意的電影會互相靠近,再透過 cosine similarity 找出劇情相似電影推薦給用戶。