Pencarian dengan cosine similarity
Diberikan matriks embedding E (satu baris per item) dan vektor query q. Kembalikan indeks k baris yang paling mirip arahnya dengan q menurut cosine similarity, terurut dari yang paling mirip. Jika seri, indeks yang lebih kecil didahulukan.
E = [[1,0], [0,1], [1,1]], q = [1, 0.1], k = 2 → [0, 2]
E = [[1,0], [2,0], [-1,0]], q = [3, 0], k = 3 → [0, 1, 2] // [1,0] dan [2,0] sama arahnya
Klik kata di grafik. cos(a, b) = a·b / (‖a‖‖b‖): 1 = searah, 0 = tegak lurus, −1 = berlawanan.
- 1anjing0.986
- 2singa0.914
- 3sepeda0.566
- 4motor0.387
- 5pria0.212
- 6mobil0.162
- 7wanita-0.134
- 8raja-0.151
Arah, bukan panjang
Cosine similarity hanya melihat sudut antar-vektor. [1, 0] dan [2, 0] punya kemiripan 1, walau jarak Euclid-nya 1. Untuk embedding, panjang vektor sering dipengaruhi hal seperti frekuensi kata, sedangkan arahnya membawa makna. Karena itu cosine adalah ukuran default.
Kalau semua vektor sudah dinormalkan ke panjang 1, cosine similarity sama dengan dot product biasa. Database vektor memanfaatkan sifat ini supaya pencarian menjadi satu perkalian matriks E @ q.
Hubungan dengan attention
Skor attention q⋅k juga mengukur kemiripan arah (ditambah panjang). Attention pada dasarnya adalah pencarian lunak (soft retrieval): bukan mengambil top-k, tapi mengambil rata-rata berbobot dari semua item, dengan bobot softmax dari kemiripannya.
Penjelasan
Yang diminta. Indeks k baris E yang arahnya paling mirip dengan q.
Langkah di kode:
E @ qmemberi dot productqdengan setiap baris,(n,).np.linalg.norm(E, axis=1)memberi panjang setiap baris, dannp.linalg.norm(q)panjang query.- Bagi untuk mendapat cosine similarity,
(n,), nilainya di antara −1 dan 1. np.argsort(-sims, kind="stable"):argsortmengurutkan dari kecil ke besar, jadi kita urutkan negatifnya agar yang terbesar di depan.kind="stable"menjaga urutan asli untuk nilai yang sama, sehingga indeks yang lebih kecil didahulukan saat seri.- Ambil
[:k]dan ubah ke list Python.
Kenapa cosine, bukan jarak? Di case 2, [1, 0] dan [2, 0] sama-sama searah dengan q = [3, 0], sehingga cosine keduanya 1 dan seri. Dengan jarak Euclid, [2, 0] akan lebih dekat. Embedding membawa makna di arah-nya.
Yang dikembalikan: list k bilangan bulat.
Topik
Petunjuk 1
cos(a, b) = a·b / (‖a‖ ‖b‖). Untuk semua baris sekaligus: (E @ q) / (np.linalg.norm(E, axis=1) * np.linalg.norm(q)).
Petunjuk 2
np.argsort(-sims, kind='stable') mengurutkan dari terbesar, dan pada nilai seri indeks kecil tetap di depan.
Nilai ditulis sebagai JSON. Output yang diharapkan dihitung dari solusi referensi.