본문 바로가기
Database/DBMS

[ChromaDB] 임베딩 간 유사도, sklearn 라이브러리와의 차이점?

by 찐굴 2025. 10. 14.

🔹 1. Chroma Collection Query

1) HNSW

    • 작동 방식
      • Chroma는 벡터 데이터베이스입니다.
      • 내부적으로 HNSW(approximate nearest neighbor) 알고리즘을 사용합니다.
      • 즉, 완벽한 “정확한 계산(exact search)”이 아니라 근사적 탐색(approximate search) 으로 빠르게 가장 유사한 벡터를 찾아줍니다.
      장점
      • 매우 빠름: 수천~수백만 개의 벡터 중에서도 실시간으로 검색 가능.
      • 확장성 높음: 대규모 이미지/텍스트 임베딩 저장에 적합.
      • 검색 기능 포함: top-N 결과, metadata 필터링, hybrid 검색 등.
      단점
      • 근사값(approximate): HNSW는 탐색 효율을 위해 정확도를 일부 희생.
        • 즉, 실제로는 cosine_similarity가 조금 더 높은 다른 벡터가 있을 수도 있음.
      • embedding 개수가 적을 때는 오히려 오버헤드가 큼.

🔍 Chroma 1.x의 핵심 변화 요약

https://docs.trychroma.com/docs/collections/configure

 

 

The default is l2 (squared L2 norm), and other possible values are cosine (cosine similarity), and ip (inner product).

collection = client.create_collection(
    name="my-collection",
    embedding_function=OpenAIEmbeddingFunction(model_name="text-embedding-3-small"),
    configuration={
        "hnsw": {
            "space": "cosine",
            "ef_construction": 200
        }
    }
)

 

2) 지원되는 metric 종류

distance_function내부 계산식결과 의미비교 기준
즉 👇
  • L2: 절대적인 좌표 거리
  • Cosine: 벡터 방향(각도) 중심
  • Inner product: 코사인과 유사하지만, 벡터 길이 차이까지 반영

3. 수학적으로 정리

(1) L2 distance

  • 벡터 간 “직선 거리”
  • 크기(magnitude) 차이 포함
  • 벡터가 정규화되어 있으면, cosine과 완전 단조 관계

(2) Cosine distance

  • 벡터의 “방향(각도)” 차이
  • 크기는 무시, 각도만 본다
  • 0이면 동일 방향, 1이면 완전 반대

(3) Inner Product (dot product distance)

  • 코사인과 유사하지만, 벡터의 크기도 반영
  • Embedding 모델이 cosine 기반이면 적합하지 않음
  • 예: OpenAI, SentenceTransformers → cosine
       CLIP, Faiss-trained embeddings → IP

4. 언제 어떤 metric을 써야 할까?

 

상황추천 metric이유
얼굴 임베딩 (Facenet, ArcFace 등) ✅ l2 또는 cosine 이 임베딩들은 이미 L2-normalized 되어 있음 → 두 metric 동일
텍스트 임베딩 (BERT, OpenAI, SBERT 등) ✅ cosine 크기보다 방향이 중요
CLIP, Vision-Language embedding ✅ ip 학습 자체가 inner product 기반
벡터가 normalize되지 않은 경우 ⚠️ l2 크기까지 고려해야 정확
“가장 가깝다” 기준이 명확히 거리일 때 l2 물리적 거리 개념에 가까움

5. metric 설정하기 : l2 or cosine

live_emb_array = np.asarray(live_embedding, dtype=np.float32).reshape(1, -1)
live_emb_array = normalize(live_emb_array, norm="l2")

print(f"Live embedding shape: {live_emb_array.shape}")

# Compare against each stored embedding
best_image = image_collection.query(
    query_embeddings=live_emb_array.tolist(),
    n_results=1  # 가까운 top-1 가져오기
)

 

지금은 이 상태이기 때문에 l2 로 비교하기로 했다

 

Chroma Docs

Documentation for ChromaDB

docs.trychroma.com


🔹 2. sklearn cosine_similarity

similarity = float(cosine_similarity(live_emb_array, stored_emb_array)[0][0])

작동 방식

  • 정확한 연산(exact cosine similarity) 을 수행합니다.
  • 두 임베딩 간의 내적을 통해 실제 코사인 유사도를 구함.

장점

  • 정확함: 근사 탐색이 아니라 수학적으로 완전한 코사인 유사도.
  • 디버깅 및 소규모 비교에 적합 (예: 1:1 매칭 검증, threshold 기준 설정 등).

단점

  • 확장성 부족: 수천~수만 개 벡터 비교 시 계산량 급증.
  • 속도 느림: 대량 데이터에서는 비효율적.

⚖️ 성능 비교 요약

Chroma Query (HNSW)    sklearn cosine_similarity(HNSW사용안함)

 

정확도 근사(approximate) 정확(exact)
속도 빠름 (log-scale search) 느림 (O(n))
확장성 매우 높음 낮음
적합한 상황 DB 전체에서 가장 유사한 벡터 찾기 두 벡터 간 직접 유사도 비교
결과 차이 약간의 오차 가능 (0.001~0.01 정도) 수학적으로 정확

💡 결론

  • 대규모 임베딩 검색: → chroma_client.query() (HNSW : 근사 검색으로 빠르고 효율적)
  • 정확도 평가나 디버깅: → cosine_similarity() (HNSW(x) : 정확한 계산)

'Database > DBMS' 카테고리의 다른 글

[ChromaDB] sqlite3, duckdb로 조회하기  (0) 2025.10.14