본문 바로가기

공부방/Upstage AI Lab 4기

[IR] 벡터 유사도를 계산하는 다양한 방법들

내가 사용했던 엘라스틱서치의 KNN 검색 과정:

  1. 주어진 쿼리 벡터와 모든 문서 벡터 간의 L2 거리를 계산
  2. num_candidates 개수만큼의 후보를 먼저 선정 (코드에서는 100개)
    • 이는 성능과 정확도의 트레이드오프를 위한 것
    • 후보군이 많을수록 정확도는 높아지지만 검색 속도는 느려짐
  3. 후보군 중에서 거리가 가장 가까운 k개(코드에서는 size 파라미터)를 최종 선택
  4. 거리가 가까운 순서대로 정렬하여 결과 반환

예를 들어, 768차원의 임베딩 벡터가 있다면:

  • 쿼리: [0.1, 0.2, ..., 0.7]
  • 문서1: [0.2, 0.3, ..., 0.6]
  • 문서2: [0.8, 0.7, ..., 0.1] 이런 식으로 각 차원의 차이를 계산하여 전체 거리를 구합니다.

 

mappings = {
    "properties": {
        "content": {"type": "text", "analyzer": "nori"},
        "embeddings": {
            "type": "dense_vector",
            "dims": 768,
            "index": True,
            "similarity": "l2_norm" ## 여기서 L2 norm 사용을 지정 / "cosine"도 가능
        }
    }
}

# Vector 유사도를 이용한 검색
def dense_retrieve(query_str, size):
    # 벡터 유사도 검색에 사용할 쿼리 임베딩 가져오기
    query_embedding = get_embedding([query_str])[0]

    # KNN을 사용한 벡터 유사성 검색을 위한 매개변수 설정
    knn = {
        "field": "embeddings",
        "query_vector": query_embedding.tolist(),
        "k": size,
        "num_candidates": 100
    }

    # 지정된 인덱스에서 벡터 유사도 검색 수행
    return es.search(index="test", knn=knn)

 

 

  1. 코사인 유사도 (Cosine Similarity)
  • 두 벡터 간의 각도를 기반으로 유사도 측정
  • -1에서 1 사이의 값 (-1: 반대 방향, 1: 같은 방향)
  • 벡터의 크기에 영향을 받지 않음
  • 문서 길이가 다른 경우에도 잘 동작
  1. 유클리디안 거리 (L2 Distance)
  • 두 벡터 간의 실제 거리를 계산
  • 값이 작을수록 더 유사함. 각 차원에서 벡터 값의 차이를 제곱하고, 모든 차이의 제곱값을 더한 뒤 제곱근을 구함
  • 수식으로는: √((q₁-d₁)² + (q₂-d₂)² + ... + (qₙ-dₙ)²)
  • 벡터의 크기에 영향을 받음
  • 현재 코드에서 사용 중인 방식 (l2_norm)
  1. 내적 (Dot Product)
  • 두 벡터의 요소별 곱의 합
  • 계산이 간단하고 빠름
  • 벡터의 크기에 영향을 받음
  • 값이 클수록 더 유사함

 

참고사항

 

  • dot_product를 사용할 경우 벡터가 정규화되어 있어야 정확한 결과를 얻을 수 있습니다.
  • cosine은 내부적으로 벡터를 정규화하여 계산합니다.
  • l2_norm은 벡터의 정규화 여부와 관계없이 실제 거리를 계산합니다.

 

===>

다른 유사도 계산 방식을 시도해보고 싶다면, 각각 다른 similarity 설정으로 여러 개의 인덱스를 만들어서 비교해봐야 합니다.

 

 

여기까지는 엘라스틱서치에서 사용해볼 수 있는 유사도 계산법들이고, 아래는 엘라스틱서치에서 지원하지 않음. 

 

  1. 맨해튼 거리 (L1 Distance)
  • 각 차원에서의 절대 차이의 합
  • 이상치에 덜 민감
  • 희소 벡터(sparse vector)에 효과적
  1. FAISS나 Annoy 같은 근사 최근접 이웃(Approximate Nearest Neighbor) 알고리즘
  • 대규모 데이터셋에서 효율적인 검색 가능
  • 정확도와 속도의 트레이드오프 조절 가능
  • 엘라스틱서치 외부에서 구현 필요