Saya rasa tidak ada ekstensi yang melakukan ini, jadi saya menemukan solusi terbatas:
Jika A dan B keduanya dinormalisasi (panjang 1), cos(A, B) = 1 - 0.5 * ||A - B||^2
. ||A - B||
adalah jarak Euclidean, dan cos(A, B)
adalah kesamaan cosinus. Jadi jarak Euclidean yang lebih besar <=> kesamaan kosinus yang lebih rendah (masuk akal secara intuitif jika Anda membayangkan lingkaran satuan), dan jika Anda memiliki vektor non-normal, mengubah besarnya tanpa mengubah arahnya tidak memengaruhi kesamaan kosinusnya. Bagus, jadi saya bisa menormalkan vektor saya dan membandingkan jarak Euclidean mereka...
Ada jawaban yang bagus di sini tentang Kubus , yang mendukung titik n-dimensi dan indeks GiST pada Euclidean jarak, tetapi hanya mendukung 100 atau lebih sedikit dimensi (dapat diretas lebih tinggi, tetapi saya memiliki masalah sekitar 135 dan lebih tinggi, jadi sekarang saya khawatir). Juga membutuhkan Postgres 9.6 atau lebih baru.
Jadi:
- Pastikan saya tidak peduli memiliki paling banyak 100 dimensi. Tingkatkan ke Postgres 9.6 atau lebih baru.
- Isi tabel saya dengan array untuk mewakili vektor.
- Normalkan vektor untuk membuat kolom tambahan
cube
poin. Buat indeks GiST pada kolom ini. - Urutkan berdasarkan jarak Euclidean menaik untuk mendapatkan kemiripan kosinus turun:
EXPLAIN SELECT * FROM mytable ORDER BY normalized <-> cube(array[1,2,3,4,5,6,7,8,9,0]) LIMIT 10;
Jika saya membutuhkan lebih dari 100 dimensi, saya mungkin dapat mencapai ini menggunakan beberapa kolom yang diindeks. Akan memperbarui jawabannya dalam kasus itu.
Pembaruan: Cukup yakin tidak ada yang bisa saya lakukan dengan membagi vektor>100-dimensi menjadi beberapa kolom. Saya akhirnya harus memindai seluruh tabel.