milvus-logo
LFAI
홈페이지
  • 사용자 가이드

스파스 벡터

스파스 벡터는 대부분의 요소가 0인 벡터 임베딩을 사용하여 단어 또는 구문을 나타내며, 0이 아닌 요소 하나만 특정 단어의 존재를 나타냅니다. SPLADEv2와 같은 희소 벡터 모델은 도메인 외 지식 검색, 키워드 인식 및 해석 가능성에서 고밀도 모델보다 성능이 뛰어납니다. 정보 검색, 자연어 처리, 추천 시스템에서 특히 유용하며, 리콜을 위한 스파스 벡터와 랭킹을 위한 대규모 모델을 결합하면 검색 결과를 크게 개선할 수 있습니다.

Milvus에서 스파스 벡터의 사용은 밀도 벡터와 유사한 워크플로우를 따릅니다. 여기에는 희소 벡터 열로 컬렉션을 만들고, 데이터를 삽입하고, 인덱스를 만들고, 유사도 검색과 스칼라 쿼리를 수행하는 것이 포함됩니다.

이 튜토리얼에서는 그 방법을 배웁니다:

  • 스파스 벡터 임베딩 준비하기;
  • 스파스 벡터 필드가 있는 컬렉션 만들기;
  • 스파스 벡터 임베딩으로 엔티티 삽입하기;
  • 컬렉션 색인화 및 희소 벡터에 대한 ANN 검색을 수행합니다.

스파스 벡터가 실제로 작동하는 모습을 보려면 hello_sparse.py를 참조하세요.

참고

현재 스파스 벡터 지원은 2.4.0의 베타 기능으로 제공되며, 3.0.0에서 정식으로 제공될 예정입니다.

스파스 벡터 임베딩 준비하기

Milvus에서 스파스 벡터를 사용하려면 지원되는 형식 중 하나로 벡터 임베딩을 준비하세요:

  • 스파스 행렬: scipy.sparse 클래스 패밀리를 활용하여 희소 임베딩을 표현합니다. 이 방법은 대규모의 고차원 데이터를 처리하는 데 효율적입니다.

  • 사전 목록: 각 스파스 임베딩을 {dimension_index: value, ...} 로 구조화된 사전으로 표현하며, 각 키-값 쌍은 차원 인덱스와 해당 값을 나타냅니다.

    예시:

    {2: 0.33, 98: 0.72, ...}
    
  • 튜플의 이터러블 목록: 사전 목록과 유사하지만 0이 아닌 차원과 해당 값만 지정하기 위해 튜플의 이터러블인 [(dimension_index, value)] 을 사용합니다.

    예제:

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

다음 예는 각각 10,000개의 차원과 0.005의 희소성 밀도를 가진 10,000개의 엔티티에 대해 무작위 희소 행렬을 생성하여 스파스 임베딩을 준비합니다.

# 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
#     }
# }

참고 사항

벡터 차원은 Python int 또는 numpy.integer 유형이어야 하며, 값은 Python float 또는 numpy.floating 유형이어야 합니다.

임베딩을 생성하려면 다양한 임베딩 함수를 제공하는 PyMilvus 라이브러리에 내장된 model 패키지를 사용할 수도 있습니다. 자세한 내용은 임베딩을 참조하세요.

스파스 벡터 필드로 컬렉션 만들기

스파스 벡터 필드가 있는 컬렉션을 만들려면 스파스 벡터 필드의 데이터 타입을 DataType.SPARSE_FLOAT_VECTOR로 설정합니다. 고밀도 벡터와 달리 스파스 벡터에는 차원을 지정할 필요가 없습니다.

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)

일반적인 컬렉션 매개변수에 대한 자세한 내용은 create_collection() 을 참조하십시오 .

스파스 벡터 임베딩으로 엔티티 삽입하기

스파스 벡터 임베딩이 있는 엔티티를 삽입하려면 엔티티의 목록을 insert() 메서드에 엔티티 목록을 전달하면 됩니다.

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

컬렉션 색인 생성

유사도 검색을 수행하기 전에 컬렉션에 대한 색인을 만드세요. 인덱스 유형 및 매개변수에 대한 자세한 내용은 add_index()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)

스파스 벡터에 인덱스를 구축하려면 다음 사항에 유의하세요:

  • index_type: 작성할 인덱스 유형입니다. 스파스 벡터에 사용할 수 있는 옵션:

    • SPARSE_INVERTED_INDEX: 각 차원을 0이 아닌 벡터에 매핑하는 역 인덱스로, 검색 중에 관련 데이터에 직접 액세스할 수 있습니다. 희소하지만 고차원 데이터로 구성된 데이터 세트에 이상적입니다.

    • SPARSE_WAND: WAND(Weak-AND) 알고리즘을 사용해 가능성이 낮은 후보를 빠르게 우회하여 순위 가능성이 높은 후보에 평가의 초점을 맞춥니다. 차원을 용어로, 벡터를 문서로 취급하여 대규모의 희박한 데이터 세트에서 검색 속도를 높입니다.

  • metric_type: 희소 벡터에 대해서는 IP (내부 제품) 거리 메트릭만 지원됩니다.

  • params.drop_ratio_build: 희소 벡터에 특별히 사용되는 인덱스 매개변수입니다. 인덱싱 과정에서 제외되는 작은 벡터 값의 비율을 제어합니다. 이 매개변수를 사용하면 인덱스를 구성할 때 작은 값을 무시함으로써 효율성과 정확성 사이의 균형을 미세 조정할 수 있습니다. 예를 들어 drop_ratio_build = 0.3 인 경우 인덱스를 구성하는 동안 모든 스파스 벡터의 모든 값이 수집되고 정렬됩니다. 이 중 가장 작은 30%의 값은 인덱스에 포함되지 않으므로 검색 시 계산 작업량이 줄어듭니다.

자세한 내용은 인메모리 인덱스를 참조하세요.

컬렉션이 색인화되어 메모리에 로드된 후에는 search() 메서드를 사용하여 쿼리를 기반으로 관련 문서를 검색합니다.

# 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}}

검색 매개변수를 구성할 때 다음 사항에 유의하세요:

  • params.drop_ratio_search: 스파스 벡터에 특별히 사용되는 검색 매개변수입니다. 이 옵션을 사용하면 쿼리 벡터에서 무시할 가장 작은 값의 비율을 지정하여 검색 프로세스를 미세 조정할 수 있습니다. 검색 정확도와 성능의 균형을 맞추는 데 도움이 됩니다. drop_ratio_search 에 설정된 값이 작을수록 이러한 작은 값이 최종 점수에 기여하는 비중이 줄어듭니다. 일부 작은 값을 무시하면 정확도에 미치는 영향을 최소화하면서 검색 성능을 향상시킬 수 있습니다.

스칼라 쿼리 수행

Milvus는 ANN 검색 외에도 스파스 벡터에 대한 스칼라 쿼리도 지원합니다. 이러한 쿼리를 사용하면 희소 벡터와 연관된 스칼라 값을 기반으로 문서를 검색할 수 있습니다. 매개변수에 대한 자세한 내용은 query()를 참조하세요.

scalar_field가 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}}]

기본 키를 기준으로 엔터티를 필터링합니다:

# 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'}]

제한

Milvus에서 스파스 벡터를 사용할 때는 다음 제한 사항을 고려하세요:

  • 현재 스파스 벡터에는 IP 거리 메트릭만 지원됩니다.

  • 스파스 벡터 필드의 경우, SPARSE_INVERTED_INDEXSPARSE_WAND 인덱스 유형만 지원됩니다.

  • 현재 스파스 벡터에는 범위 검색, 그룹화 검색, 검색 반복기가 지원되지 않습니다.

FAQ

  • 스파스 벡터에는 어떤 거리 메트릭이 지원되나요?

    스파스 벡터의 차원이 높기 때문에 L2 거리와 코사인 거리는 비현실적이기 때문에 스파스 벡터는 내적 곱(IP) 거리 메트릭만 지원합니다.

  • SPARSE_INVERTED_INDEX와 SPARSE_WAND의 차이점과 둘 중 하나를 선택하려면 어떻게 해야 하나요?

    SPARSE_INVERTED_INDEX는 기존의 반전 인덱스인 반면, SPARSE_WAND는 검색 시 전체 IP 거리 평가 횟수를 줄이기 위해 Weak-AND 알고리즘을 사용합니다. SPARSE_WAND는 일반적으로 더 빠르지만 벡터 밀도가 증가하면 성능이 저하될 수 있습니다. 이 중 하나를 선택하려면 특정 데이터 세트와 사용 사례에 따라 실험과 벤치마크를 수행하세요.

  • drop_ratio_build 및 drop_ratio_search 매개변수는 어떻게 선택해야 하나요?

    drop_ratio_builddrop_ratio_search의 선택은 데이터의 특성과 검색 지연 시간/처리량 및 정확도에 대한 요구 사항에 따라 달라집니다.

  • 스파스 임베딩에 지원되는 데이터 유형은 무엇인가요?

    차원 부분은 부호가 없는 32비트 정수여야 하며, 값 부분은 음수가 아닌 32비트 부동 소수점 숫자일 수 있습니다.

  • 희소 임베딩의 치수는 uint32 공간 내의 모든 불연속형 값이 될 수 있나요?

    예, 한 가지 예외가 있습니다. 희소 임베딩의 차원은 [0, maximum of uint32) 범위의 모든 값이 될 수 있습니다. 즉, 최대값인 uint32를 사용할 수 없습니다.

  • 증가하는 세그먼트에 대한 검색은 인덱스를 통해 수행되나요 아니면 무차별 대입으로 수행되나요?

    증가하는 세그먼트에 대한 검색은 봉인된 세그먼트 인덱스와 동일한 유형의 인덱스를 통해 수행됩니다. 인덱스가 구축되기 전에 새로 증가하는 세그먼트의 경우 무차별 대입 검색이 사용됩니다.

  • 하나의 컬렉션에 희소 벡터와 고밀도 벡터를 모두 포함할 수 있나요?

    예. 여러 벡터 유형을 지원하므로 스파스 및 고밀도 벡터 열이 모두 포함된 컬렉션을 생성하고 하이브리드 검색을 수행할 수 있습니다.

  • 스파스 임베딩을 삽입하거나 검색하려면 어떤 요건을 충족해야 하나요?

    스파스 임베딩에는 0이 아닌 값이 하나 이상 있어야 하며, 벡터 인덱스는 음수가 아니어야 합니다.

번역DeepLogo

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
피드백

이 페이지가 도움이 되었나요?