Vektor Jarang

Vektor jarang merepresentasikan kata atau frasa menggunakan penyematan vektor yang sebagian besar elemennya bernilai nol, dengan hanya satu elemen bukan nol yang menunjukkan keberadaan kata tertentu. Model vektor jarang, seperti SPLADEv2, mengungguli model padat dalam pencarian pengetahuan di luar domain, kesadaran akan kata kunci, dan kemampuan penafsiran. Model-model ini sangat berguna dalam pencarian informasi, pemrosesan bahasa alami, dan sistem rekomendasi, di mana menggabungkan vektor yang jarang untuk mengingat dengan model yang besar untuk pemeringkatan dapat secara signifikan meningkatkan hasil pencarian.

Di Milvus, penggunaan vektor jarang mengikuti alur kerja yang mirip dengan vektor padat. Ini melibatkan pembuatan koleksi dengan kolom vektor jarang, memasukkan data, membuat indeks, dan melakukan pencarian kemiripan dan kueri skalar.

Dalam tutorial ini, Anda akan belajar bagaimana caranya:

  • Menyiapkan penyisipan vektor jarang;
  • Membuat koleksi dengan kolom vektor jarang;
  • Menyisipkan entitas dengan sematan vektor jarang;
  • Mengindeks koleksi dan melakukan pencarian ANN pada vektor jarang.

Untuk melihat vektor jarang beraksi, lihat hello_sparse.py.

Catatan

Saat ini, dukungan untuk vektor jarang adalah fitur beta di 2.4.0, dengan rencana untuk membuatnya tersedia secara umum di 3.0.0.

Menyiapkan penyematan vektor jarang

Untuk menggunakan vektor jarang di Milvus, siapkan penyematan vektor dalam salah satu format yang didukung:

  • Matriks Jarang: Manfaatkan keluarga kelas scipy.sparse untuk merepresentasikan embedding jarang Anda. Metode ini efisien untuk menangani data berskala besar dan berdimensi tinggi.

  • Daftar Kamus: Merepresentasikan setiap sematan jarang sebagai kamus, terstruktur sebagai {dimension_index: value, ...}, di mana setiap pasangan kunci-nilai merepresentasikan indeks dimensi dan nilai yang sesuai.

    Contoh:

    {2: 0.33, 98: 0.72, ...}
    
  • Daftar Iterasi Tupel: Mirip dengan daftar kamus, tetapi menggunakan iterable tuple, [(dimension_index, value)], untuk menentukan hanya dimensi yang tidak nol dan nilainya.

    Contoh:

    [(2, 0.33), (98, 0.72), ...]
    

Contoh berikut ini menyiapkan sematan jarang dengan membuat matriks jarang acak untuk 10.000 entitas, masing-masing dengan 10.000 dimensi dan kerapatan jarang 0,005.

# Prepare entities with sparse vector representation
import numpy as np
import random

rng = np.random.default_rng()

num_entities, dim = 10000, 10000

# Generate random sparse rows with an average of 25 non-zero elements per row
entities = [
    {
        "scalar_field": rng.random(),
        # To represent a single sparse vector row, you can use:
        # - Any of the scipy.sparse sparse matrices class family with shape[0] == 1
        # - Dict[int, float]
        # - Iterable[Tuple[int, float]]
        "sparse_vector": {
            d: rng.random() for d in random.sample(range(dim), random.randint(20, 30))
        },
    }
    for _ in range(num_entities)
]

# print the first entity to check the representation
print(entities[0])

# Output:
# {
#     'scalar_field': 0.520821523849214,
#     'sparse_vector': {
#         5263: 0.2639375518635271,
#         3573: 0.34701499565746674,
#         9637: 0.30856525997853057,
#         4399: 0.19771651149001523,
#         6959: 0.31025067641541815,
#         1729: 0.8265339135915016,
#         1220: 0.15303302147479103,
#         7335: 0.9436728846033107,
#         6167: 0.19929870545596562,
#         5891: 0.8214617920371853,
#         2245: 0.7852255053773395,
#         2886: 0.8787982039149889,
#         8966: 0.9000606703940665,
#         4910: 0.3001170013981104,
#         17: 0.00875671667413136,
#         3279: 0.7003425473001098,
#         2622: 0.7571360018373428,
#         4962: 0.3901879090102064,
#         4698: 0.22589525720196246,
#         3290: 0.5510228492587324,
#         6185: 0.4508413201390492
#     }
# }

Catatan

Dimensi vektor harus bertipe Python int atau numpy.integer, dan nilainya harus bertipe Python float atau numpy.floating.

Untuk menghasilkan embeddings, Anda juga bisa menggunakan paket model yang dibangun di dalam pustaka PyMilvus, yang menawarkan berbagai fungsi penyematan. Untuk detailnya, lihat Embeddings.

Membuat koleksi dengan bidang vektor yang jarang

Untuk membuat koleksi dengan bidang vektor jarang, atur tipe data bidang vektor jarang ke DataType.SPARSE_FLOAT_VECTOR. Tidak seperti vektor padat, tidak perlu menentukan dimensi untuk vektor jarang.

from pymilvus import MilvusClient, DataType

# Create a MilvusClient instance
client = MilvusClient(uri="http://localhost:19530")

# Create a collection with a sparse vector field
schema = client.create_schema(
    auto_id=True,
    enable_dynamic_fields=True,
)

schema.add_field(field_name="pk", datatype=DataType.VARCHAR, is_primary=True, max_length=100)
schema.add_field(field_name="scalar_field", datatype=DataType.DOUBLE)
# For sparse vector, no need to specify dimension
schema.add_field(field_name="sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR) # set `datatype` to `SPARSE_FLOAT_VECTOR`

client.create_collection(collection_name="test_sparse_vector", schema=schema)

Untuk detail tentang parameter koleksi umum, lihat create_collection().

Menyisipkan entitas dengan penyematan vektor jarang

Untuk menyisipkan entitas dengan penyematan vektor jarang, cukup berikan daftar entitas ke metode insert() metode.

# Insert entities
client.insert(collection_name="test_sparse_vector", data=entities)

Mengindeks koleksi

Sebelum melakukan pencarian kemiripan, buatlah indeks untuk koleksi. Untuk informasi lebih lanjut mengenai jenis dan parameter indeks, lihat add_index() dan create_index().

# Index the collection

# Prepare index params
index_params = client.prepare_index_params()

index_params.add_index(
    field_name="sparse_vector",
    index_name="sparse_inverted_index",
    index_type="SPARSE_INVERTED_INDEX", # the type of index to be created. set to `SPARSE_INVERTED_INDEX` or `SPARSE_WAND`.
    metric_type="IP", # the metric type to be used for the index. Currently, only `IP` (Inner Product) is supported.
    params={"drop_ratio_build": 0.2}, # the ratio of small vector values to be dropped during indexing.
)

# Create index
client.create_index(collection_name="test_sparse_vector", index_params=index_params)

Untuk membuat indeks pada vektor yang jarang, perhatikan yang berikut ini:

  • index_type: Jenis indeks yang akan dibangun. Opsi-opsi yang memungkinkan untuk vektor jarang:

    • SPARSE_INVERTED_INDEX: Indeks terbalik yang memetakan setiap dimensi ke vektor non-nol, memfasilitasi akses langsung ke data yang relevan selama pencarian. Ideal untuk set data dengan data yang jarang namun berdimensi tinggi.

    • SPARSE_WAND: Memanfaatkan algoritme Weak-and (WAND) untuk melewatkan kandidat yang tidak mungkin dengan cepat, memfokuskan evaluasi pada kandidat yang memiliki potensi peringkat yang lebih tinggi. Memperlakukan dimensi sebagai istilah dan vektor sebagai dokumen, sehingga mempercepat pencarian dalam set data yang besar dan jarang.

  • metric_type: Hanya metrik jarak IP (Inner Product) yang didukung untuk vektor yang jarang.

  • params.drop_ratio_build: Parameter indeks yang digunakan secara khusus untuk vektor jarang. Parameter ini mengontrol proporsi nilai vektor kecil yang dikecualikan selama proses pengindeksan. Parameter ini memungkinkan penyetelan yang baik dari trade-off antara efisiensi dan akurasi dengan mengabaikan nilai-nilai kecil saat membangun indeks. Sebagai contoh, jika drop_ratio_build = 0.3, selama pembangunan indeks, semua nilai dari semua vektor yang jarang dikumpulkan dan diurutkan. Nilai terkecil 30% dari nilai-nilai ini tidak disertakan dalam indeks, sehingga mengurangi beban kerja komputasi selama pencarian.

Untuk informasi lebih lanjut, lihat Indeks dalam memori.

Setelah koleksi diindeks dan dimuat ke dalam memori, gunakan metode search() untuk mengambil dokumen yang relevan berdasarkan kueri.

# Load the collection into memory
client.load_collection(collection_name="test_sparse_vector")

# Perform ANN search on sparse vectors

# for demo purpose we search for the last inserted vector
query_vector = entities[-1]["sparse_vector"]

search_params = {
    "metric_type": "IP",
    "params": {"drop_ratio_search": 0.2}, # the ratio of small vector values to be dropped during search.
}

search_res = client.search(
    collection_name="test_sparse_vector",
    data=[query_vector],
    limit=3,
    output_fields=["pk", "scalar_field"],
    search_params=search_params,
)

for hits in search_res:
    for hit in hits:
        print(f"hit: {hit}")
        
# Output:
# hit: {'id': '448458373272710786', 'distance': 7.220192909240723, 'entity': {'pk': '448458373272710786', 'scalar_field': 0.46767865218233806}}
# hit: {'id': '448458373272708317', 'distance': 1.2287548780441284, 'entity': {'pk': '448458373272708317', 'scalar_field': 0.7315987515699472}}
# hit: {'id': '448458373272702005', 'distance': 0.9848432540893555, 'entity': {'pk': '448458373272702005', 'scalar_field': 0.9871869181562156}}

Saat mengonfigurasi parameter pencarian, perhatikan hal-hal berikut ini:

  • params.drop_ratio_search: Parameter pencarian yang digunakan secara khusus untuk vektor yang jarang. Opsi ini memungkinkan penyempurnaan proses pencarian dengan menentukan rasio nilai terkecil dalam vektor kueri yang akan diabaikan. Ini membantu menyeimbangkan ketepatan pencarian dan kinerja. Semakin kecil nilai yang ditetapkan untuk drop_ratio_search, semakin sedikit nilai kecil ini berkontribusi pada skor akhir. Dengan mengabaikan beberapa nilai kecil, kinerja pencarian dapat ditingkatkan dengan dampak minimal pada akurasi.

Melakukan kueri skalar

Selain pencarian ANN, Milvus juga mendukung kueri skalar pada vektor yang jarang. Kueri ini memungkinkan Anda mengambil dokumen berdasarkan nilai skalar yang terkait dengan vektor jarang. Untuk informasi lebih lanjut mengenai parameter, lihat query().

Menyaring entitas dengan scalar_field lebih besar dari 3:

# Perform a query by specifying filter expr
filter_query_res = client.query(
    collection_name="test_sparse_vector",
    filter="scalar_field > 0.999",
)

print(filter_query_res[:2])

# Output:
# [{'pk': '448458373272701862', 'scalar_field': 0.9994093623822689, 'sparse_vector': {173: 0.35266244411468506, 400: 0.49995484948158264, 480: 0.8757831454277039, 661: 0.9931875467300415, 1040: 0.0965644046664238, 1728: 0.7478245496749878, 2365: 0.4351981580257416, 2923: 0.5505295395851135, 3181: 0.7396837472915649, 3848: 0.4428485333919525, 4701: 0.39119353890419006, 5199: 0.790219783782959, 5798: 0.9623121619224548, 6213: 0.453134149312973, 6341: 0.745091438293457, 6775: 0.27766478061676025, 6875: 0.017947908490896225, 8093: 0.11834774166345596, 8617: 0.2289179265499115, 8991: 0.36600416898727417, 9346: 0.5502803921699524}}, {'pk': '448458373272702421', 'scalar_field': 0.9990218525410719, 'sparse_vector': {448: 0.587817907333374, 1866: 0.0994109958410263, 2438: 0.8672442436218262, 2533: 0.8063794374465942, 2595: 0.02122959867119789, 2828: 0.33827054500579834, 2871: 0.1984412521123886, 2938: 0.09674275666475296, 3154: 0.21552987396717072, 3662: 0.5236313343048096, 3711: 0.6463911533355713, 4029: 0.4041993021965027, 7143: 0.7370485663414001, 7589: 0.37588241696357727, 7776: 0.436136394739151, 7962: 0.06377989053726196, 8385: 0.5808192491531372, 8592: 0.8865005970001221, 8648: 0.05727503448724747, 9071: 0.9450633525848389, 9161: 0.146037295460701, 9358: 0.1903032660484314, 9679: 0.3146636486053467, 9974: 0.8561339378356934, 9991: 0.15841573476791382}}]

Memfilter entitas berdasarkan kunci utama:

# primary keys of entities that satisfy the filter
pks = [ret["pk"] for ret in filter_query_res]

# Perform a query by primary key
pk_query_res = client.query(
    collection_name="test_sparse_vector", filter=f"pk == '{pks[0]}'"
)

print(pk_query_res)

# Output:
# [{'scalar_field': 0.9994093623822689, 'sparse_vector': {173: 0.35266244411468506, 400: 0.49995484948158264, 480: 0.8757831454277039, 661: 0.9931875467300415, 1040: 0.0965644046664238, 1728: 0.7478245496749878, 2365: 0.4351981580257416, 2923: 0.5505295395851135, 3181: 0.7396837472915649, 3848: 0.4428485333919525, 4701: 0.39119353890419006, 5199: 0.790219783782959, 5798: 0.9623121619224548, 6213: 0.453134149312973, 6341: 0.745091438293457, 6775: 0.27766478061676025, 6875: 0.017947908490896225, 8093: 0.11834774166345596, 8617: 0.2289179265499115, 8991: 0.36600416898727417, 9346: 0.5502803921699524}, 'pk': '448458373272701862'}]

Batas

Ketika menggunakan vektor jarang di Milvus, pertimbangkan batas-batas berikut ini:

TANYA JAWAB

  • Metrik jarak apa yang didukung untuk vektor jarang?

    Vektor jarang hanya mendukung metrik jarak Inner Product (IP) karena dimensi vektor jarang yang tinggi, sehingga jarak L2 dan jarak kosinus menjadi tidak praktis.

  • Dapatkah Anda menjelaskan perbedaan antara SPARSE_INVERTED_INDEX dan SPARSE_WAND, dan bagaimana cara memilih di antara keduanya?

    SPARSE_INVERTED_INDEX adalah indeks terbalik tradisional, sedangkan SPARSE_WAND menggunakan algoritme Weak-AND untuk mengurangi jumlah evaluasi jarak IP penuh selama pencarian. SPARSE_WAND biasanya lebih cepat, tetapi kinerjanya dapat menurun dengan meningkatnya kepadatan vektor. Untuk memilih di antara keduanya, lakukan eksperimen dan tolok ukur berdasarkan dataset dan kasus penggunaan spesifik Anda.

  • Bagaimana cara memilih parameter drop_ratio_build dan drop_ratio_search?

    Pilihan drop_ratio_build dan drop_ratio_search bergantung pada karakteristik data Anda dan kebutuhan Anda untuk latensi/throughput dan akurasi pencarian.

  • Tipe data apa yang didukung untuk penyematan jarang?

    Bagian dimensi harus berupa bilangan bulat 32-bit yang tidak ditandatangani, dan bagian nilai dapat berupa bilangan floating-point 32-bit non-negatif.

  • Dapatkah dimensi embedding jarang berupa nilai diskrit dalam ruang uint32?

    Ya, dengan satu pengecualian. Dimensi dari embedding jarang dapat berupa nilai apa pun dalam kisaran [0, maximum of uint32). Ini berarti Anda tidak dapat menggunakan nilai maksimum uint32.

  • Apakah pencarian pada ruas yang sedang tumbuh dilakukan melalui indeks atau dengan brute force?

    Pencarian pada segmen yang sedang tumbuh dilakukan melalui indeks dengan tipe yang sama dengan indeks segmen yang disegel. Untuk segmen baru yang sedang tumbuh sebelum indeks dibangun, pencarian brute force digunakan.

  • Apakah mungkin untuk memiliki vektor yang jarang dan padat dalam satu koleksi?

    Ya, dengan dukungan beberapa jenis vektor, Anda dapat membuat koleksi dengan kolom vektor jarang dan padat serta melakukan pencarian hibrida pada koleksi tersebut.

  • Apa saja persyaratan agar sematan jarang dapat disisipkan atau dicari?

    Sematan jarang harus memiliki setidaknya satu nilai bukan nol, dan indeks vektor harus non-negatif.

Diterjemahkan olehDeepL

Coba Milvus yang Dikelola secara Gratis

Zilliz Cloud bebas masalah, didukung oleh Milvus dan 10x lebih cepat.

Mulai
Umpan balik

Apakah halaman ini bermanfaat?