노름과 거리(Norms and Distances)

거리 함수는 무엇을 "비슷하다"라고 볼지 정의합니다. 잘못 선택하면 그 뒤의 모든 것이 흔들립니다.

유형: Build 언어: Python 선수 지식: Phase 1, Lesson 01(Linear Algebra Intuition), 02(Vectors, Matrices & Operations) 예상 시간: 약 90분

학습 목표

  • L1, L2, 코사인(cosine), 마할라노비스(Mahalanobis), 자카드(Jaccard), 편집 거리(edit distance) 함수를 처음부터 구현합니다.
  • 주어진 머신러닝 과제(ML task)에 적절한 거리 척도(distance metric)를 선택하고, 다른 선택지가 왜 실패하는지 설명합니다.
  • L1 노름(L1 norm)과 L2 노름(L2 norm)을 LASSO, Ridge 정규화(regularization) 및 기하학적 제약 영역(constraint region)과 연결합니다.
  • 같은 데이터셋(dataset)이 척도(metric)에 따라 서로 다른 최근접 이웃(nearest neighbor)을 만들 수 있음을 보여줍니다.

문제

두 벡터(vector)가 있습니다. 단어 임베딩(word embedding)일 수도 있고, 사용자 프로필(user profile)일 수도 있고, 픽셀 배열(pixel array)일 수도 있습니다. 이제 알아야 할 것은 하나입니다. 둘은 얼마나 가까운가요?

답은 어떤 거리 함수(distance function)를 선택하느냐에 전적으로 달려 있습니다. 두 데이터 포인트(data point)는 어떤 척도에서는 최근접 이웃(nearest neighbor)일 수 있고, 다른 척도에서는 멀리 떨어져 있을 수 있습니다. KNN 분류기(KNN classifier), 추천 엔진(recommendation engine), 벡터 데이터베이스(vector database), 클러스터링 알고리즘(clustering algorithm), 손실 함수(loss function)는 모두 이 선택에 의존합니다. 잘못 선택하면 모델은 잘못된 것을 최적화합니다.

보편적으로 가장 좋은 거리는 없습니다. L2는 공간 데이터(spatial data)에 잘 맞습니다. 코사인 유사도(cosine similarity)는 NLP에서 지배적입니다. 자카드(Jaccard)는 집합(set)을 다룹니다. 편집 거리(edit distance)는 문자열(string)을 다룹니다. 마할라노비스(Mahalanobis)는 상관관계(correlation)를 고려합니다. 바서슈타인(Wasserstein)은 확률 질량(probability mass)을 이동합니다. 각각은 "유사하다(similar)"의 의미에 대해 서로 다른 가정을 부호화(encoding)합니다.

이 강의에서는 주요 거리 함수를 처음부터 구현하고, 각 함수가 언제 적절한 도구인지 보여주며, 같은 데이터가 척도 선택에 따라 완전히 다른 최근접 이웃을 낼 수 있음을 확인합니다.

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.코사인 유사도(cosine similarity)는 두 벡터 사이에서 무엇을 측정하나요?

2.L1 거리(L1 distance)를 '맨해튼 거리(Manhattan distance)'라고 부르는 이유는 무엇인가요?

0/2 답변 완료

개념

노름(Norm): 벡터 크기(Vector Magnitude) 측정

노름(norm)은 벡터의 "크기"를 측정합니다. 두 벡터 사이의 거리 함수는 모두 두 벡터 차이의 노름으로 쓸 수 있습니다. d(a, b) = ||a - b||입니다. 따라서 노름을 이해하는 것은 거리를 이해하는 일입니다.

L1 노름(L1 Norm, Manhattan Distance)

L1 노름은 모든 성분(component)의 절댓값(absolute value)을 더합니다.

||x||_1 = |x_1| + |x_2| + ... + |x_n|

축을 따라만 움직일 수 있는 도시 격자(city grid)에서 걷는 거리를 재기 때문에 맨해튼 거리(Manhattan distance)라고 부릅니다. 대각선 이동은 없습니다.

Point A = (1, 1)
Point B = (4, 5)

L1 distance = |4-1| + |5-1| = 3 + 4 = 7

격자(grid) 위에서는 동쪽으로 3 블록, 북쪽으로 4 블록 걸어갑니다.

L1을 사용할 때:

  • 고차원 희소 데이터(high-dimensional sparse data; 텍스트 특징, 원-핫 인코딩)
  • 이상치(outlier)에 강건(robust)해야 할 때
  • 특징 선택(feature selection) 문제(L1 정규화는 희소성(sparsity)을 촉진함)

L1 정규화(L1 regularization, Lasso)와의 연결: 손실 함수에 ||w||_1을 더하면 가중치 절댓값(absolute weight value)의 합에 페널티(penalty)를 줍니다. 이 페널티는 작은 가중치를 정확히 0으로 밀어 자동 특징 선택을 수행합니다. L1 페널티는 가중치 공간(weight space)에 다이아몬드 모양의 제약 영역(diamond-shaped constraint region)을 만들며, 다이아몬드의 모서리(corner)는 일부 가중치가 0인 축(axis) 위에 놓입니다.

손실 함수와의 연결: 평균 절대 오차(Mean Absolute Error; MAE)는 예측(prediction)과 목표(target) 사이 L1 거리의 평균입니다. 모든 오차(error)를 선형으로 페널라이즈(penalize)하므로 MSE보다 이상치에 강건합니다.

L2 노름(L2 Norm, Euclidean Distance)

L2 노름은 직선 거리(straight-line distance)입니다. 성분 제곱합의 제곱근입니다.

||x||_2 = sqrt(x_1^2 + x_2^2 + ... + x_n^2)

기하 시간에 배운 거리입니다. n차원에서의 피타고라스(Pythagoras) 정리입니다.

Point A = (1, 1)
Point B = (4, 5)

L2 distance = sqrt((4-1)^2 + (5-1)^2) = sqrt(9 + 16) = sqrt(25) = 5.0

격자를 대각선으로 가로지르는 직선 거리입니다.

L2를 사용할 때:

  • 저차원에서 중간 차원의 연속 데이터(low-to-medium dimensional continuous data)
  • 특징 척도(feature scale)가 서로 비교 가능할 때
  • 물리적 거리(physical distance; 공간 데이터, 센서 측정값)
  • 픽셀 수준의 이미지 유사도(pixel level image similarity)

L2 정규화(L2 regularization, Ridge)와의 연결: 손실 함수에 ||w||_2^2를 더하면 큰 가중치에 페널티를 줍니다. L1과 달리 가중치를 0으로 밀지는 않습니다. 모든 가중치를 비례적으로 0에 가깝게 줄입니다. L2 페널티는 원형 제약 영역(circular constraint region)을 만들기 때문에 축 위의 모서리가 없습니다. 가중치는 작아지지만 정확히 0이 되는 경우는 드뭅니다.

손실 함수와의 연결: 평균 제곱 오차(Mean Squared Error; MSE)는 L2 거리 제곱의 평균입니다. 제곱은 작은 오차보다 큰 오차를 훨씬 강하게 페널라이즈합니다.

MAE (L1 loss):  |y - y_hat|         선형 페널티. 이상치에 강건.
MSE (L2 loss):  (y - y_hat)^2       2차 페널티. 이상치에 민감.

Lp 노름(Lp Norm): 일반화된 계열

L1과 L2는 Lp 노름의 특수 사례(special case)입니다.

||x||_p = (|x_1|^p + |x_2|^p + ... + |x_n|^p)^(1/p)

p 값에 따라 단위 공(unit ball), 즉 원점(origin)에서 거리 1인 모든 점의 집합 모양이 달라집니다.

p=1:    다이아몬드 모양     (축 위에 모서리)
p=2:    원/구             (일반적인 둥근 공)
p=3:    초타원체          (둥근 사각형)
p=inf:  정사각형/초입방체   (축을 따라 평평한 면)

L-infinity 노름(L-infinity Norm, Chebyshev Distance)

p가 무한대(infinity)에 가까워지면 Lp 노름은 성분 절댓값의 최댓값으로 수렴합니다.

||x||_inf = max(|x_1|, |x_2|, ..., |x_n|)

두 점 사이의 거리는 가장 크게 다른 단일 차원으로 결정됩니다. 다른 차원은 무시됩니다.

Point A = (1, 1)
Point B = (4, 5)

L-inf distance = max(|4-1|, |5-1|) = max(3, 4) = 4

L-infinity를 사용할 때:

  • 어떤 단일 차원에서의 최악 편차(worst-case deviation)가 중요한 경우
  • 게임 보드(체스에서 킹은 한 방향으로 한 칸 움직이는 비용이 1이므로 L-infinity로 움직임)
  • 제조 공정의 허용 오차(manufacturing tolerance; 모든 차원이 규격(spec) 안에 있어야 함)

코사인 유사도와 코사인 거리(Cosine Similarity and Cosine Distance)

코사인 유사도(cosine similarity)는 두 벡터의 크기(magnitude)를 무시하고 각도(angle)를 측정합니다.

cos_sim(a, b) = (a . b) / (||a||_2 * ||b||_2)

값은 -1(반대 방향)에서 +1(같은 방향) 사이입니다. 수직(perpendicular)인 두 벡터의 코사인 유사도는 0입니다.

코사인 거리(cosine distance)는 유사도를 거리로 바꾼 값입니다. cosine_distance = 1 - cosine_similarity이며, 0(동일 방향)에서 2(반대 방향) 사이입니다.

a = (1, 0)    b = (1, 1)

cos_sim = (1*1 + 0*1) / (1 * sqrt(2)) = 1/sqrt(2) = 0.707
cos_dist = 1 - 0.707 = 0.293

왜 NLP와 임베딩(embedding)에서 코사인이 지배적일까요? 텍스트에서는 문서 길이(document length)가 유사도에 영향을 주면 안 됩니다. 고양이에 관한 문서가 다른 고양이 문서보다 두 배 길다고 해서 "덜 비슷"해지는 것은 아닙니다. 코사인 유사도는 크기(길이)를 무시하고 방향(direction)만 봅니다. 같은 단어 분포(word distribution)를 가진 두 문서는 길이가 달라도 같은 방향을 가리키며 코사인 유사도 1.0을 얻습니다.

코사인 유사도를 사용할 때:

  • 텍스트 유사도(TF-IDF 벡터, 단어 임베딩, 문장 임베딩)
  • 크기가 잡음(noise)이고 방향이 신호(signal)인 도메인(domain)
  • 추천 시스템(recommendation system; 사용자 선호 벡터)
  • 임베딩 검색(embedding search; 벡터 데이터베이스는 거의 항상 코사인 또는 내적(dot product)을 사용함)

내적 유사도와 코사인 유사도(Dot Product Similarity vs Cosine Similarity)

두 벡터의 내적(dot product)은 다음과 같습니다.

a . b = a_1*b_1 + a_2*b_2 + ... + a_n*b_n
      = ||a|| * ||b|| * cos(angle)

코사인 유사도는 내적을 두 크기로 정규화(normalize)한 값입니다. 두 벡터가 이미 단위 정규화(unit-normalized; 크기 = 1)되어 있다면 내적과 코사인 유사도는 동일합니다.

||a|| = 1 그리고 ||b|| = 1 이면:
    a . b = cos(a와 b 사이의 각도)

차이는 크기 정보(magnitude information)입니다. 내적은 크기가 큰 벡터에 더 높은 점수를 줍니다. 일부 검색 시스템(retrieval system)에서는 "인기 있는(popular)" 항목을 더 높게 순위 매기고 싶을 수 있으므로 이 특성이 의미가 있습니다. 크기가 암묵적인 품질 또는 중요도 신호(implicit quality or importance signal)처럼 작동합니다.

a = (3, 0)    b = (1, 0)    c = (0, 1)

dot(a, b) = 3     dot(a, c) = 0
cos(a, b) = 1.0   cos(a, c) = 0.0

둘 다 방향 판단은 같지만, 내적은 크기도 반영합니다.

실무에서는 다음처럼 선택합니다.

  • 순수한 방향 유사도(directional similarity)가 필요하면 코사인 유사도를 사용합니다.
  • 크기가 의미 있는 정보를 담고 있으면 내적을 사용합니다.
  • 많은 벡터 데이터베이스(Pinecone, Weaviate, Qdrant)는 둘 중 하나를 선택할 수 있게 합니다.
  • 임베딩이 L2 정규화되어 있다면 선택은 사실상 차이가 없습니다.

마할라노비스 거리(Mahalanobis Distance)

유클리드 거리(Euclidean distance)는 모든 차원을 동일하게 취급합니다. 하지만 특징(feature)이 서로 상관(correlated)되어 있거나 척도가 다르면 L2는 오해를 부르는 결과를 줍니다.

마할라노비스 거리는 데이터의 공분산 구조(covariance structure)를 고려합니다.

d_M(x, y) = sqrt((x - y)^T * S^(-1) * (x - y))

여기서 S는 데이터의 공분산 행렬(covariance matrix)입니다.

직관적으로는 먼저 데이터의 상관을 제거(decorrelate)하고 정규화하는 백색화(whitening)를 수행한 뒤, 그 변환된 공간(transformed space)에서 L2 거리를 계산합니다. S가 단위 행렬(identity matrix)이라면 마할라노비스 거리는 유클리드 거리와 같습니다.

예: 키(height)와 몸무게(weight)는 서로 상관되어 있습니다.
6'2"에 180 lbs인 사람은 이상하지 않습니다.
5'0"에 180 lbs인 사람은 이상합니다.

유클리드 거리는 둘을 평균(mean)에서 비슷하게 멀다고 볼 수 있습니다.
마할라노비스 거리는 키-몸무게 상관을 고려하므로 두 번째를 이상치(outlier)로 올바르게 식별합니다.

마할라노비스 거리를 사용할 때:

  • 이상치 탐지(outlier detection; 평균에서 마할라노비스 거리가 큰 점은 이상치)
  • 특징 척도와 상관 구조가 다른 분류(classification)
  • 신뢰할 만한 공분산 행렬을 추정할 충분한 데이터가 있을 때
  • 제조 공정 품질 관리(manufacturing quality control; 다변량 공정 모니터링)

자카드 유사도(Jaccard Similarity, 집합용)

자카드 유사도(Jaccard similarity)는 두 집합의 겹침(overlap)을 측정합니다.

J(A, B) = |A 교집합 B| / |A 합집합 B|

값은 0(겹침 없음)에서 1(동일한 집합) 사이입니다. 자카드 거리는 1 - 자카드 유사도입니다.

A = {cat, dog, fish}
B = {cat, bird, fish, snake}

교집합(intersection) = {cat, fish}          크기 = 2
합집합(union) = {cat, dog, fish, bird, snake}  크기 = 5

자카드 유사도 = 2/5 = 0.4
자카드 거리 = 0.6

자카드를 사용할 때:

  • 태그(tag), 카테고리(category), 특징 집합(feature set) 비교
  • 단어 등장 여부(word presence) 기반 문서 유사도(빈도 아님)
  • 거의 중복 탐지(near-duplicate detection; 자카드의 MinHash 근사)
  • 이진 특징 벡터(binary feature vector; 존재/부재 데이터) 비교
  • 세그멘테이션 모델(segmentation model) 평가(Intersection over Union = 자카드)

편집 거리(Edit Distance, Levenshtein Distance)

편집 거리(edit distance)는 한 문자열을 다른 문자열로 바꾸는 데 필요한 단일 문자 연산(single-character operation)의 최소 개수를 셉니다. 연산은 삽입(insert), 삭제(delete), 치환(substitute)입니다.

"kitten" -> "sitting"

kitten -> sitten  (substitute k -> s)
sitten -> sittin  (substitute e -> i)
sittin -> sitting (insert g)

Edit distance = 3

동적 계획법(dynamic programming)으로 계산합니다. 행렬 항목(matrix entry) (i, j)는 문자열 A의 첫 i개 문자와 문자열 B의 첫 j개 문자 사이 편집 거리입니다.

        ""  s  i  t  t  i  n  g
    ""   0  1  2  3  4  5  6  7
    k    1  1  2  3  4  5  6  7
    i    2  2  1  2  3  4  5  6
    t    3  3  2  1  2  3  4  5
    t    4  4  3  2  1  2  3  4
    e    5  5  4  3  2  2  3  4
    n    6  6  5  4  3  3  2  3

편집 거리를 사용할 때:

  • 맞춤법 검사 및 교정(spell checking and correction)
  • DNA 서열 정렬(DNA sequence alignment; 가중 연산 포함)
  • 퍼지 문자열 매칭(fuzzy string matching)
  • 지저분한 텍스트 데이터의 중복 제거(deduplication)

KL 발산(KL Divergence, 거리는 아니지만 거리처럼 쓰임)

KL 발산(KL divergence)은 한 확률분포(probability distribution)가 다른 분포와 얼마나 다른지 측정합니다. Lesson 09에서 다뤘지만, 사람들이 이를 "거리"처럼 사용하기 때문에 여기에도 포함합니다.

D_KL(P || Q) = sum(p(x) * log(p(x) / q(x)))

중요한 성질: KL 발산은 대칭(symmetric)이 아닙니다.

D_KL(P || Q) != D_KL(Q || P)

따라서 거리 척도(distance metric)의 기본 조건을 만족하지 않습니다. 삼각 부등식(triangle inequality)도 만족하지 않습니다. KL은 거리가 아니라 발산(divergence)입니다.

순방향 KL(Forward KL; D_KL(P || Q))은 평균 추종(mean-seeking)입니다. Q는 P의 모든 모드(mode)를 덮으려 합니다. 역방향 KL(Reverse KL; D_KL(Q || P))은 모드 추종(mode-seeking)입니다. Q는 P의 단일 모드에 집중합니다.

KL 발산이 등장하는 곳:

  • VAE(ELBO의 KL 항이 잠재 분포(latent distribution)를 사전 분포(prior) 쪽으로 밀어줌)
  • 지식 증류(knowledge distillation; 학생(student)이 교사(teacher) 분포를 맞추려 함)
  • RLHF(KL 페널티가 미세 조정된 모델(fine-tuned model)을 기반 모델(base model)에 가깝게 유지함)
  • 정책 경사 기법(policy gradient method; 정책 업데이트 제한)

바서슈타인 거리(Wasserstein Distance, Earth Mover's Distance)

바서슈타인 거리(Wasserstein distance)는 한 확률분포를 다른 분포로 바꾸는 데 필요한 최소 "일(work)"을 측정합니다. 하나의 분포가 흙더미이고 다른 분포가 구덩이라면, 흙을 얼마나 멀리 얼마나 많이 옮겨야 하는지를 묻는 것입니다.

W(P, Q) = inf over all transport plans gamma of E[d(x, y)]

1차원 분포에서는 누적분포함수(cumulative distribution function; CDF)의 절대 차이 적분으로 단순화됩니다.

W_1(P, Q) = integral |CDF_P(x) - CDF_Q(x)| dx

바서슈타인이 중요한 이유:

  • 진정한 척도(true metric)입니다. 대칭이고 삼각 부등식을 만족합니다.
  • 분포가 겹치지 않아도 기울기(gradient)를 제공합니다. KL 발산은 무한대로 갑니다.
  • 이 성질 때문에 원래의 GAN이 가진 학습 불안정성(training instability)을 해결한 바서슈타인 GAN(WGAN)의 중심이 되었습니다.
겹치지 않는 분포:

P: [1, 0, 0, 0, 0]    Q: [0, 0, 0, 0, 1]

KL 발산: 무한대 (log of zero)
바서슈타인: 4 (모든 질량을 4칸 이동)

바서슈타인은 의미 있는 기울기를 줍니다. KL은 그렇지 못합니다.

바서슈타인을 사용할 때:

  • GAN 학습(WGAN, WGAN-GP)
  • 겹치지 않을 수 있는 분포 비교
  • 최적 수송(optimal transport) 문제
  • 이미지 검색(image retrieval; 색상 히스토그램 비교)

서로 다른 과제에는 서로 다른 거리가 필요하다

과제최적 거리이유
텍스트 유사도코사인(Cosine)크기는 잡음이고 방향이 의미입니다.
이미지 픽셀 비교L2공간 관계가 중요하고 특징 척도가 비교 가능합니다.
희소 고차원 특징L1강건하고 드문 큰 차이를 과도하게 증폭하지 않습니다.
집합 겹침(태그, 카테고리)자카드(Jaccard)데이터가 자연스럽게 집합값이며 벡터가 아닙니다.
문자열 매칭편집 거리(Edit distance)연산이 사람이 생각하는 편집 직관과 맞습니다.
이상치 탐지마할라노비스(Mahalanobis)특징의 상관과 척도를 고려합니다.
분포 비교KL 발산(KL divergence)P 대신 Q를 사용할 때 잃는 정보를 측정합니다.
GAN 학습바서슈타인(Wasserstein)분포가 겹치지 않아도 기울기를 제공합니다.
임베딩(벡터 DB)코사인 또는 내적(dot product)임베딩은 의미를 방향에 부호화하도록 학습됩니다.
추천내적(Dot product)크기가 인기도(popularity) 또는 신뢰도(confidence)를 부호화할 수 있습니다.
DNA 서열가중 편집 거리뉴클레오타이드 쌍별 치환 비용이 다릅니다.
제조 품질 관리L-infinity어떤 차원의 최악 편차도 중요합니다.

손실 함수(Loss Function)와의 연결

손실 함수(loss function)는 예측과 목표에 적용된 거리 함수입니다.

손실 함수             사용 거리              동작
MSE                 L2 제곱               큰 오차를 크게 페널라이즈
MAE                 L1                    모든 오차를 동일하게 페널라이즈
Huber loss          큰 오차에는 L1,        둘의 장점: 이상치에 강건하면서
                    작은 오차에는 L2       0 근처에서 부드러운 기울기
Cross-entropy       KL 발산               분포 불일치를 측정
Hinge loss          max(0, margin - d)    margin 미만만 페널라이즈
Triplet loss        L2 (보통)             positive는 가까이, negative는
                                          멀리 밀어냄
Contrastive loss    L2                    유사 쌍은 가까이, 비유사 쌍은
                                          margin 너머로

정규화(Regularization)와의 연결

정규화(regularization)는 가중치의 노름 페널티를 손실 함수에 더합니다.

L1 정규화 (Lasso):     loss + lambda * ||w||_1
  -> 희소 가중치. 일부 가중치가 정확히 0이 됨.
  -> 자동 특징 선택.
  -> 해(solution)에 모서리가 있음(0에서 미분 불가).

L2 정규화 (Ridge):     loss + lambda * ||w||_2^2
  -> 작은 가중치. 모든 가중치가 0 쪽으로 수축.
  -> 특징 선택 없음(정확히 0이 되는 가중치가 없음).
  -> 어디서나 부드러운 해.

Elastic Net:           loss + lambda_1 * ||w||_1 + lambda_2 * ||w||_2^2
  -> L1의 희소성과 L2의 안정성을 결합.
  -> 상관된 특징 그룹을 함께 유지하거나 함께 제거.

L1은 희소성을 만들고 L2는 그렇지 않은 이유는 2차원 가중치 공간의 제약 영역을 보면 이해할 수 있습니다. L1은 다이아몬드이고 L2는 원입니다. 손실 함수의 등고선 타원(contour ellipse)은 다이아몬드의 모서리, 즉 어떤 가중치가 0인 지점에 먼저 닿을 가능성이 큽니다. 원에는 모서리가 없기 때문에 두 가중치가 모두 0이 아닌 부드러운 점에 닿습니다.

모든 거리 함수는 최근접 이웃 탐색(nearest neighbor search) 문제를 정의합니다. 질의 점(query point)이 주어졌을 때 데이터셋에서 가장 가까운 점을 찾는 문제입니다.

정확한 최근접 이웃 탐색(exact nearest neighbor search)은 n개 점과 d차원의 데이터셋에서 질의당 O(n * d)입니다. 큰 데이터셋에서는 너무 느립니다.

근사 최근접 이웃(Approximate Nearest Neighbor; ANN) 알고리즘은 약간의 정확도를 포기하고 큰 속도 향상을 얻습니다.

알고리즘            접근                          사용처
KD-trees          축 정렬 공간 분할              scikit-learn (저차원)
Ball trees        중첩 하이퍼스피어              scikit-learn (중간 차원)
LSH               무작위 해시 투영               near-duplicate detection
HNSW              계층적 내비게이션 가능         FAISS, Qdrant, Weaviate
                  스몰월드 그래프
IVF               역색인 파일과                  FAISS (수십억 단위)
                  클러스터 기반 검색
Product quant.    벡터 압축 후 압축된            FAISS (메모리 제약 환경)
                  공간에서 검색

HNSW(Hierarchical Navigable Small World)는 현대 벡터 데이터베이스의 대표 알고리즘입니다. 각 노드(node)가 근사 최근접 이웃과 연결되는 다층 그래프(multi-layer graph)를 만듭니다. 탐색은 최상위 층(top layer; 희소, 긴 점프)에서 시작해 최하위 층(bottom layer; 밀집, 짧은 점프)으로 내려갑니다.

만들어 보기

Step 1: 모든 노름과 거리 함수

전체 구현은 code/distances.py를 확인합니다. 모든 함수는 기본 Python math만 사용해 처음부터 작성되어 있습니다.

Step 2: 같은 데이터, 다른 거리, 다른 이웃

distances.py의 데모는 데이터셋을 만들고 질의 점을 선택한 뒤, 거리 척도에 따라 최근접 이웃이 어떻게 바뀌는지 보여줍니다. L1에서 "가장 가까운(closest)" 점이 L2나 코사인에서는 가장 가깝지 않을 수 있습니다.

코드에는 코사인 유사도와 L2 거리로 질의와 가장 유사한 "문서(documents)"를 찾는 모의 임베딩 유사도 검색(mock embedding similarity search)이 포함되어 있습니다. 순위(ranking)가 서로 달라질 수 있음을 보여줍니다.

사용하기

가장 흔한 실무 사용처는 벡터 데이터베이스에서 유사한 항목(item)을 찾는 것입니다.

import numpy as np

def cosine_similarity_matrix(X):
    norms = np.linalg.norm(X, axis=1, keepdims=True)
    norms = np.where(norms == 0, 1, norms)
    X_normalized = X / norms
    return X_normalized @ X_normalized.T

embeddings = np.random.randn(1000, 768)

sim_matrix = cosine_similarity_matrix(embeddings)

query_idx = 0
similarities = sim_matrix[query_idx]
top_k = np.argsort(similarities)[::-1][1:6]
print(f"item 0과 가장 유사한 Top 5: {top_k}")
print(f"Similarities: {similarities[top_k]}")

model.encode(text)를 호출한 뒤 벡터 데이터베이스를 검색할 때 내부에서 일어나는 일이 바로 이것입니다. 임베딩 모델은 텍스트를 벡터로 매핑(mapping)합니다. 벡터 데이터베이스는 질의 벡터(query vector)와 저장된 모든 벡터 사이 코사인 유사도 또는 내적을 계산하되, 모든 벡터를 직접 확인하지 않기 위해 ANN 알고리즘을 사용합니다.

산출물 만들기

이 강의의 최종 산출물은 다음입니다.

  • code/distances.py: 주요 노름, 거리, 유사도 함수와 최근접 이웃 데모를 포함합니다.
  • outputs/prompt-distance-chooser.md: 과제에 맞는 거리 척도를 고르는 데 사용하는 프롬프트(prompt)입니다.

연습문제

  1. (1, 2, 3)과 (4, 0, 6) 사이의 L1, L2, L-infinity 거리를 계산합니다. 어떤 두 점 쌍에서도 항상 L-inf <= L2 <= L1이 성립함을 확인합니다. 이 순서가 왜 보장되는지 증명합니다.

  2. 코사인 유사도는 높지만(> 0.9) L2 거리는 큰(> 10) 두 벡터를 만듭니다. 기하적으로 무슨 일이 일어나는지 설명합니다. 그다음 코사인 유사도는 낮지만(< 0.3) L2 거리는 작은(< 0.5) 두 벡터를 만듭니다.

  3. 데이터셋과 질의 점을 받아 L1, L2, 코사인, 마할라노비스 거리 각각에서 최근접 이웃을 반환하는 함수를 구현합니다. 네 척도가 모두 다른 최근접 점을 고르는 데이터셋을 찾습니다.

  4. CDF 방법을 사용해 [0.5, 0.5, 0, 0]과 [0, 0, 0.5, 0.5] 사이 바서슈타인 거리를 손으로 계산합니다. 그다음 [0.25, 0.25, 0.25, 0.25]와 [0, 0, 0.5, 0.5] 사이를 계산합니다. 어느 쪽이 더 크고 왜 그런지 설명합니다.

  5. 근사 자카드 유사도(approximate Jaccard similarity)를 위한 MinHash를 구현합니다. 무작위 집합 100개를 만들고 모든 쌍의 정확한 자카드 값을 계산한 뒤, 해시 함수(hash function)를 50개, 100개, 200개 사용할 때 MinHash 근사와 비교합니다. 근사 오차(approximation error)를 그래프로 그립니다.

핵심 용어

용어흔한 설명실제 의미
노름(Norm)"벡터의 크기"벡터를 음이 아닌 스칼라(non-negative scalar)로 매핑하는 함수입니다. 삼각 부등식, 절대 동차성(absolute homogeneity), 영 벡터에서만 0인 성질을 만족합니다.
L1 노름"맨해튼 거리(Manhattan distance)"성분 절댓값의 합입니다. 최적화에서 희소성(sparsity)을 만들고 이상치에 강건합니다.
L2 노름"유클리드 거리(Euclidean distance)"성분 제곱합의 제곱근입니다. 유클리드 공간(Euclidean space)에서의 직선 거리입니다.
Lp 노름"일반화된 노름"성분 절댓값의 p제곱 합에 p제곱근(p-th root)을 취한 값입니다. L1과 L2가 특수 사례입니다.
L-infinity 노름"최댓값 노름(Max norm)" 또는 "체비셰프 거리(Chebyshev distance)"성분 절댓값의 최댓값입니다. p가 무한대로 갈 때 Lp의 극한(limit)입니다.
코사인 유사도(Cosine similarity)"벡터 사이의 각도"내적을 두 크기로 정규화한 값입니다. -1에서 +1 사이이며 벡터 길이를 무시합니다.
코사인 거리(Cosine distance)"1 빼기 코사인 유사도"코사인 유사도를 거리로 바꾼 값입니다. 0에서 2 사이입니다.
내적(Dot product)"정규화되지 않은 코사인"성분별 곱의 합입니다. 코사인 유사도에 두 크기를 곱한 값과 같습니다.
마할라노비스 거리(Mahalanobis distance)"상관을 고려한 거리"데이터 공분산 행렬로 백색화(whitening; 상관 제거와 정규화)된 공간에서의 L2 거리입니다.
자카드 유사도(Jaccard similarity)"집합의 겹침"교집합 크기를 합집합 크기로 나눈 값입니다. 벡터가 아니라 집합에 사용합니다.
편집 거리(Edit distance)"레벤슈타인 거리(Levenshtein distance)"한 문자열을 다른 문자열로 바꾸는 데 필요한 삽입, 삭제, 치환의 최소 횟수입니다.
KL 발산(KL divergence)"분포 사이의 거리"진정한 거리가 아닙니다. 대칭이 아니며 Q로 P를 부호화(encoding)할 때 추가로 필요한 비트(bit)를 측정합니다.
바서슈타인 거리(Wasserstein distance)"Earth mover's distance"한 분포에서 다른 분포로 질량을 옮기는 최소 일(work)입니다. 진정한 척도입니다.
근사 최근접 이웃(Approximate nearest neighbor)"ANN 탐색"HNSW, LSH, IVF처럼 정확한 탐색보다 훨씬 빠르게 근사 최근접 점을 찾는 알고리즘입니다.
HNSW"벡터 DB 알고리즘"Hierarchical Navigable Small World 그래프입니다. 빠른 근사 최근접 이웃 탐색을 위한 다층 그래프입니다.
L1 정규화"Lasso"가중치의 L1 노름을 손실에 더합니다. 가중치를 0으로 밀어 희소성을 만듭니다.
L2 정규화"Ridge" 또는 "가중치 감쇠(weight decay)"L2 노름의 제곱을 손실에 더합니다. 희소성 없이 가중치를 0 쪽으로 줄입니다.
Elastic Net"L1 + L2"L1과 L2 정규화를 결합합니다. 상관된 특징 그룹을 더 안정적으로 다룹니다.

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

distances
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 1개

prompt-distance-chooser

Guides the user through choosing the right distance metric for their specific task

Prompt

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.L1 정규화(L1 regularization, Lasso)는 희소한 가중치를 만들지만 L2 정규화(L2 regularization, Ridge)는 그렇지 않은 이유는 무엇인가요?

2.확률분포(probability distribution)를 비교할 때 바서슈타인 거리(Wasserstein distance)가 KL 발산(KL divergence)보다 갖는 장점은 무엇인가요?

3.유클리드 거리(Euclidean distance) 대신 마할라노비스 거리(Mahalanobis distance)를 사용하는 상황은 언제인가요?

0/3 답변 완료