벡터 DB 유사도 측정 방식 총 정리
1. L2 Distance (유클리드 거리)
- 요약 : 유클리드 거리는 벡터 간의 직선 거리를 측정하므로, 크기와 방향 모두가 유사도 계산에 영향을 줍니다.
- 수학적 원리: 두 벡터 간의 직선 거리를 계산하며, 각 요소의 차이를 제곱해 합한 후 제곱근을 구하는 방식입니다. 이로 인해 두 벡터 간의 물리적 거리를 나타내며 크기와 방향이 모두 고려됩니다.
- 사용 상황
- 벡터의 크기와 방향이 모두 중요한 경우, 예: 이미지 임베딩 간 거리 계산, 물리적 거리, 픽셀 간 거리 비교 등.
- 이런 상황에 왜 좋은가?
- 이미지 임베딩은 고차원 공간의 특징 벡터로, L2 거리 계산을 통해 시각적 차이를 반영할 수 있습니다.
- 코드
import numpy as np
import faiss
# 128차원 벡터 10,000개를 가진 임베딩 예시
embeddings = np.random.random((10000, 128)).astype('float32')
# L2 거리 기반 인덱스 생성
index = faiss.IndexFlatL2(128)
index.add(embeddings)
# 쿼리 벡터와 가장 가까운 이웃 찾기 (유클리드 거리 기준)
query = np.random.random((1, 128)).astype('float32')
D, I = index.search(query, k=5) # 가장 가까운 5개 검색
print("L2 Distance Neighbors:", I)
2. (MAX) Inner Product (내적)
- 요약 : 내적은 벡터의 크기와 방향을 모두 반영하며, 내적 값이 클수록 두 벡터가 더 유사하다는 의미입니다. MAX가 앞에 붙은 이유는 가장 유사도 높은 문서를 여러개 찾는것. Inner Product 와 똑같은거라고 보면됨
- 수학적 원리: 두 벡터의 대응되는 요소를 곱한 후 모두 더하는 방식으로 계산됩니다. 이는 방향이 비슷하고 크기가 클수록 더 큰 내적 값을 생성합니다.
- 사용 상황
- 추천 시스템에서 사용자와 아이템의 선호도를 매칭할 때, 내적을 통해 선호도 강도와 방향성을 반영할 수 있어 추천 시스템에 유리합니다.
- 이런 상황에 왜 좋은가?
- 추천 시스템에서 유저와 아이템 임베딩 간의 내적을 계산하면 유저의 선호도 강도가 반영됩니다. 예를 들어, 유저가 특정 아이템을 강하게 선호할수록 해당 아이템 임베딩과 유저 임베딩 간의 내적이 커져, 추천의 우선순위가 높아짐.
- 또한, 내적을 통해 높은 선호도와 방향성이 맞는 아이템이 자동으로 선택되므로, 유저와 아이템의 관계를 직접적으로 반영하는 데 유리.
- 코드
import numpy as np
import faiss
# 임베딩 벡터 데이터 예시 (정규화되지 않은 벡터)
data = np.array([
[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0]
], dtype=np.float32)
# 쿼리 벡터 (정규화되지 않음)
query = np.array([[2.0, 3.0, 4.0]], dtype=np.float32)
# MAX_INNER_PRODUCT 방식 - 정규화 없이 내적 계산
index_ip = faiss.IndexFlatIP(data.shape[1]) # Inner Product (IP) 인덱스 생성
index_ip.add(data) # 데이터 추가
# 쿼리 벡터와 유사한 벡터 검색
scores_ip, indices_ip = index_ip.search(query, k=2)
print("MAX_INNER_PRODUCT 방식 (정규화되지 않은 벡터)")
print("유사도 점수:", scores_ip)
print("인덱스:", indices_ip)
3. Cosine Similarity (코사인 유사도)
- 요약 : 코사인 유사도는 두 벡터의 각도만 고려하고 크기는 무시합니다. 두 벡터의 방향이 유사할수록 코사인 유사도가 높아집니다.
- 수학적 원리: 벡터의 각도를 계산하여 벡터가 얼마나 같은 방향을 가리키는지 평가하며, 벡터가 같은 방향일 때 1, 반대 방향일 때 -1에 가까운 값을 갖습니다.
- 사용 상황
- 벡터 크기를 무시하고 방향만으로 유사성을 파악할 때, 예: 텍스트 임베딩 간 의미 비교, 문서 유사도 분석.
- 이런 상황에 왜 좋은가?
- 텍스트 임베딩에서 코사인 유사도는 문장 간의 의미적 유사성을 비교하는 데 효과적입니다. 두 문장의 의미가 비슷할 때 임베딩 벡터의 방향이 유사하게 나타나기 때문에, 크기 차이를 무시하고 방향만 비교하는 코사인 유사도를 사용하는 것이 적합합니다.
- 예를 들어, "고양이가 창문을 보고 있다"와 "고양이가 창문 너머를 바라보고 있다"는 같은 의미이지만, 단어 수 차이로 인해 벡터의 크기는 다를 수 있습니다. 이때 코사인 유사도를 사용하면 크기와 상관없이 방향만 비교하여 높은 유사도를 얻을 수 있습니다.
- 코드
import numpy as np
import faiss
# 128차원 벡터 10,000개를 가진 임베딩 예시 생성
embeddings = np.random.random((10000, 128)).astype('float32')
# L2 정규화를 적용하여 각 벡터의 크기를 1로 고정
faiss.normalize_L2(embeddings) # embeddings는 이제 정규화된 상태입니다.
# 내적 기반 인덱스 생성
index = faiss.IndexFlatIP(128) # 128차원 내적 인덱스 생성
index.add(embeddings) # 정규화된 벡터 추가
# 쿼리 벡터 예시 (정규화 필요)
query = np.random.random((1, 128)).astype('float32')
faiss.normalize_L2(query) # 쿼리도 정규화
# 코사인 유사도와 유사한 방식으로 유사한 벡터 검색
D, I = index.search(query, k=5) # 가장 유사한 5개의 벡터 검색
print("유사도 점수:", D)
print("인덱스:", I)
4. Jaccard 유사도
- 요약 : Jaccard Similarity는 집합 기반 유사도로, 두 집합이 공통 요소를 얼마나 많이 공유하는지 평가합니다.
- 수학적 원리: 두 집합의 교집합의 크기를 합집합의 크기로 나눈 값으로, 0과 1 사이의 값을 가집니다. 0이면 두 집합에 공통 요소가 없고, 1이면 두 집합이 동일.
- 사용 상황
- 두 뉴스 기사가 #정치, #경제, #사회와 같은 해시태그를 가지고 있을 때, Jaccard Similarity를 통해 주제의 유사성을 평가. 두 사용자가 관심 있는 상품 목록을 0과 1로 나타냈다면, Jaccard 유사도를 통해 유사한 관심사를 가진 사용자를 찾을 수 있음.
- 추천 시스템에서 사용자 행동을 기록한 희소 벡터를 비교하여 유사한 행동 패턴을 가진 사용자나 아이템을 찾는 데 사용할 수 있음. 두 이미지가 #자연, #산, #하늘과 같은 태그를 공유하는 정도에 따라 Jaccard 유사도를 사용해 유사한 이미지를 찾을 수 있음.
- 이런 상황에 왜 좋은가?
- Jaccard 유사도는 집합 기반 데이터에서 공통 항목 비율을 빠르게 계산하여 유사도를 판단할 수 있기 때문에, 태그, 이진 벡터, 범주형 데이터에서 유용
- 코드
import numpy as np
import faiss
# 두 집합을 이진 벡터로 표현
# 예: 128차원 이진 벡터 10,000개 생성 (각 원소는 0 또는 1)
binary\_embeddings = np.random.randint(2, size=(10000, 128)).astype('uint8')
# FAISS의 IndexBinaryFlat를 사용하여 Hamming 거리 기반으로 유사도 계산
# IndexBinaryFlat는 이진 벡터(0과 1로만 구성된 벡터) 간의 유사성을 Hamming 거리를 통해 비교하는 인덱스
index = faiss.IndexBinaryFlat(128) # 128차원 이진 인덱스 생성
index.add(binary\_embeddings) # 이진 벡터 추가
# 쿼리 벡터 예시 (이진 벡터로 표현)
query = np.random.randint(2, size=(1, 128)).astype('uint8')
# FAISS의 IndexBinaryFlat는 이진 벡터를 처리할 때, 벡터 간 유사도를 Hamming 거리로 측정하고, 이 거리를 **D**에 저장해 반환
# 유사도 검색: Hamming 거리를 사용하여 가장 유사한 5개 항목 검색
# Hamming 거리 : 두 벡터에서 서로 다른 위치에 있는 값의 개수
D, I = index.search(query, k=5)
# Jaccard 유사도 변환: Jaccard = 1 - (Hamming distance / 벡터 길이)
jaccard\_similarity = 1 - D / 128 # 128은 벡터 길이
print("Hamming 거리:", D)
print("Jaccard 유사도:", jaccard\_similarity)
print("인덱스:", I)
표정리
유사도/거리 측정 방식 | 정의 | 적합한 사용 예 | 설명 |
---|---|---|---|
Inner Product | 벡터 내적 계산 | - 추천 시스템에서 유저와 아이템의 매칭 - 같은 방향성을 가지는 대형 벡터 간 비교 | 내적 값이 클수록 벡터의 방향과 크기가 비슷함을 의미하며, 추천 시스템 등에서 유사한 아이템을 찾는 데 활용됨. |
L2 Distance | 두 벡터 간의 유클리드 거리 | - 물리적 거리 계산 - 얼굴 인식 및 이미지 매칭 | 벡터 간의 절대적 거리를 측정하므로, 실제 좌표상의 물리적 거리를 평가하는 데 유리함. |
Cosine Similarity | 벡터 간의 각도 기반 유사도 | - 텍스트 데이터 유사도 - 문서 및 키워드 매칭 - 추천 시스템에서 선호도 예측 | 벡터 크기와 상관없이 방향성만 비교하므로, 문서 간 주제 유사성을 파악하거나, 크기 차이를 무시한 유사도 측정에 유리함. |
Jaccard Similarity | 두 집합의 겹치는 비율 | - 태그, 키워드 기반 검색 - 고객의 공통 관심사 분석 - 바이너리 속성 데이터 비교 | 두 집합의 겹치는 정도를 측정하여 유사도를 계산하므로, 이진 속성이나 범주형 데이터 간 유사도 측정에 적합함. |
요약
- Inner Product는 크기와 방향을 모두 고려하므로, 추천 시스템처럼 특정 벡터와 내적 값이 최대가 되도록 최적화된 매칭에서 유용합니다.
- L2 Distance는 절대적인 거리 계산에 유리하여, 이미지 매칭이나 물리적 거리 평가에 적합합니다.
- Cosine Similarity는 크기를 무시하고 방향만 비교하므로, 문서나 텍스트의 주제 유사성을 파악하는 데 효과적입니다.
- Jaccard Similarity는 집합 기반 데이터에서 유용하며, 태그나 이진 속성 데이터를 비교하는 데 주로 사용됩니다.
P.S Hamming 거리는 뭐지?
'langchain 공부' 카테고리의 다른 글
Faiss 모듈 내 코드 분석2 (1) | 2024.11.13 |
---|---|
Faiss 모듈 내 코드 분석1 (0) | 2024.11.11 |
Document, BaseMedia 내부 분석 (1) | 2024.11.09 |
InMemoryDocstore 내부 코드 분석 (1) | 2024.11.07 |
invoke와 get_relevant_documents의 차이 (1) | 2024.10.16 |