559. 코사인 유사도 (Cosine Similarity)

⚠️ 이 문서는 생성형 AI 모델(LLM)이 문장이나 단어를 숫자의 나열(벡터, 임베딩)로 변환한 후, **두 문장의 의미가 얼마나 비슷한지(유사도)를 수학적으로 판단하기 위해 가장 널리 쓰이는 거리 계측 연산 방식인 '코사인 유사도'**를 다룹니다.

핵심 인사이트 (3줄 요약)

  1. 본질: 두 개의 벡터(화살표)가 공간상에서 가리키는 '방향'이 얼마나 일치하는지를 두 화살표 사이의 각도(사잇각 $\theta$)의 코사인값으로 측정하는 방법이다.
  2. 가치: 문서의 길이나 단어의 출현 빈도(크기)에 영향을 받지 않고 오직 문장의 '주제(방향성)'만을 순수하게 비교할 수 있어, 텍스트 검색(RAG)이나 추천 시스템에서 압도적인 성능을 낸다.
  3. 기술 체계: 유사도는 -1(완전 반대)부터 1(완전 동일) 사이의 값을 가지며, 벡터의 크기를 1로 통일하는 '정규화(Normalization)'를 거치면 코사인 유사도는 내적(Dot Product) 연산과 완전히 동일해져 연산 속도가 극대화된다.

Ⅰ. 유클리디안 거리(L2)의 한계와 방향성의 중요성

단순히 두 점 사이의 거리를 재는 것은 텍스트 분석에서 치명적인 오류를 낳는다.

  1. 유클리디안 거리 (Euclidean Distance):
    • 두 점 사이의 절대적인 물리적 거리(자(Ruler)로 잰 길이)를 뜻한다.
  2. 문서 길이에 따른 오류:
    • A 문서: "사과가 맛있어." (단어 수: 2)
    • B 문서: "사과가 맛있어. 사과가 정말 맛있어. 사과 짱." (단어 수: 6)
    • C 문서: "자동차가 빨라." (단어 수: 2)
    • A와 B는 똑같이 사과를 극찬하는 완벽하게 동일한 주제의 문서다. 하지만 유클리디안 거리로 계산하면, A 문서는 길이가 비슷한 C 문서(자동차)와 거리가 더 가깝게(유사하게) 나오는 어처구니없는 결과가 발생한다.
  3. 방향성의 도입:
    • 텍스트의 '주제'는 벡터의 **길이(단어 빈도수)**가 아니라 벡터의 **방향(비율)**에 있다. 코사인 유사도는 길이를 완전히 무시하고 오직 두 화살표가 벌어진 각도만 본다.

📢 섹션 요약 비유: 어떤 사람의 정치 성향을 평가할 때, 보수 집회에 1번 나간 사람(짧은 문서)과 100번 나간 사람(긴 문서)은 유클리디안 거리로 재면 매우 다른 사람 같지만, 코사인 유사도(방향성)로 재면 둘 다 정확히 똑같은 '보수(방향)'를 향하고 있음을 완벽하게 잡아내는 원리입니다.


Ⅱ. 코사인 유사도의 수학적 원리와 특징

$\cos(\theta)$의 성질을 그대로 가져온다.

  1. 수학적 공식:
    • $ \text{Cosine Similarity} = \frac{A \cdot B}{||A|| ||B||} $
    • (두 벡터의 내적을 두 벡터의 크기를 곱한 값으로 나눈다)
  2. 결과값의 의미:
    • +1: 두 화살표의 각도가 0도. (완벽하게 같은 방향 = 100% 똑같은 주제)
    • 0: 두 화살표의 각도가 90도 (직교). (주제가 전혀 연관성 없음)
    • -1: 두 화살표의 각도가 180도. (주제가 완벽하게 정반대임)
  3. 희소 벡터(Sparse Vector)에서의 강점:
    • 자연어 처리에서는 단어가 1만 개면 벡터 차원이 1만 차원이 되고, 문서 하나에 포함된 단어는 기껏해야 100개라 나머지 9,900개 차원의 값은 0이 된다. 코사인 유사도는 이 0값들을 계산에서 깔끔하게 무시해 버리기 때문에 희소한 데이터에서 극도로 효율적이다.

📢 섹션 요약 비유: 내비게이션에서 서울에서 부산으로 가는 길을 물었을 때, "비행기를 타고 가든(길이 긺), 자전거를 타고 가든(길이 짧음) 결국 둘 다 '남쪽(각도 0도)'을 향해 가고 있으니 방향(주제)은 100% 똑같다!"라고 판정해 주는 아주 실용적인 나침반입니다.


Ⅲ. 정규화(Normalization)와 내적(Dot Product) 가속

데이터베이스(Vector DB)가 이 연산을 수백만 번 수행하기 위한 꼼수다.

  1. 정규화의 마법 (L2 Normalization):
    • AI 모델(OpenAI 등)에서 임베딩 벡터를 뽑아낼 때, 모든 벡터 화살표의 길이(크기)를 강제로 '1'로 통일시켜 버리는 과정이다.
  2. 내적(Dot Product)과의 일치:
    • 길이를 모두 1로 만들어버리면, 앞선 공식에서 분모($||A|| \times ||B||$)가 $1 \times 1 = 1$이 되어 사라져 버린다.
    • 즉, 코사인 유사도 연산이 곧바로 단순한 내적(요소끼리의 곱셈 후 덧셈) 연산으로 치환된다. ($ \text{Cosine} = A \cdot B $)
  3. 검색 속도의 비약적 향상:
    • Milvus, Pinecone 같은 벡터 DB에서 수억 건의 데이터 유사도를 계산할 때, 복잡한 나눗셈과 루트 연산 없이 단순한 행렬 곱셈(내적)만으로 코사인 유사도를 완벽하게 구할 수 있어 하드웨어(GPU/CPU) 가속 효율이 극대화된다.

📢 섹션 요약 비유: 사람들의 달리기 방향을 비교할 때 뚱뚱한 사람(큰 벡터)과 마른 사람(작은 벡터)이 섞여 있으면 덩치(분모)로 나눠주는 복잡한 계산이 필요합니다. 그래서 아예 애초부터 모든 사람의 덩치를 똑같은 60kg(정규화)으로 맞춰놓고 뛰게 하면, 복잡한 나눗셈 없이 단순 곱셈(내적)만으로 1초 만에 1등을 찾아낼 수 있는 데이터베이스의 잔머리입니다.