🔹 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 |
|---|