[STUDY/ML(Machine Learning)] - [ML] TF-IDF(Term Frequency-Inverse Document Frequency)
[ML] TF-IDF(Term Frequency-Inverse Document Frequency)
1. TF-IDF?정의단어의 빈도(TF)와 역문서빈도(IDF)를 곱해서, 문서 내 각 단어의 "중요도"를 가중치로 매기는 방법단순히 "몇 번 나왔는가"만 세는 빈도수 카운트(Bag of Words)의 한계를 보완쓰임문서 간
blog.chaenii.me
TF-IDF든 임베딩이든, 텍스트를 벡터로 바꿨다면 그다음 필요한 건
"이 두 벡터가 얼마나 비슷한가"를 숫자 하나로 표현하는 방법이다.
가장 많이 쓰는 두 가지가 코사인 유사도와 유클리드 거리인데, 이 둘은 측정하는 대상이 다르다.
1. 코사인 유사도: 방향이 비슷한가
$$\cos\theta = \frac{a \cdot b}{|a||b|}$$
분자 $a \cdot b$는 내적(dot product), 분모는 각 벡터의 길이(norm)를 곱한 것.
결과는 두 벡터 사이의 각도의 코사인 값이다.
- 두 벡터가 같은 방향이면 $\cos\theta = 1$ (완전히 유사)
- 직각이면 $\cos\theta = 0$ (무관)
- 반대 방향이면 $\cos\theta = -1$ (반대)
핵심: 벡터의 크기(길이)는 무시하고 방향만 본다.
e.g.) 문서 A가 짧고 문서 B가 길어도,둘 다 "환불"이라는 단어가 같은 비율로 들어가 있다면 방향이 같음
-> 코사인 유사도가 높게 나온다.
-> 텍스트 비교에서 코사인 유사도를 선호하는 이유. 문서 길이에 영향을 안 받는다.

$$|a \cdot b| \le |a||b|$$
에서 양변을 $|a||b|$로 나누면:
$$-1 \le \frac{a \cdot b}{|a||b|} \le 1$$
이므로 코사인 유사도는 별도의 정규화 없이도 항상 $[-1, 1]$ 사이로 깔끔하게 떨어진다.
(직접 새로운 유사도 지표를 설계할 때 이 성질이 없으면 값의 범위를 따로 정규화해줘야 해서 번거롭다.)
주의: 0 벡터에는 코사인 유사도가 정의되지 않는다.
분모에 $|a||b|$가 들어가므로, 둘 중 하나라도 모든 값이 0인 벡터라면 나눗셈을 할 수 없다. 실전 코드에서는 빈 문서, 전처리 후 단어가 하나도 남지 않은 문서, 희소 벡터가 전부 0이 된 케이스를 따로 처리해야 한다.
2. 유클리드 거리: 절대적인 위치가 얼마나 가까운가
$$d = \sqrt{\sum_i (a_i - b_i)^2}$$
두 점 사이의 "직선 거리".
코사인과 달리 크기(magnitude)도 함께 본다.
벡터의 길이가 다르면 방향이 같아도 거리가 멀게 나올 수 있다.
3. 언제 뭘 쓰는가
| 코사인 유사도 | 유클리드 거리 | |
| 보는 것 | 방향(각도) | 절대 위치 |
| 길이(크기) 영향 | 없음 | 있음 |
| 주로 쓰이는 곳 | 텍스트(TF-IDF, 임베딩) 비교 | 군집화의 중심점 거리 (KMeans), SOM |
텍스트 유사도 비교는 거의 항상 코사인.
반면 KMeans나 SOM처럼 "공간상의 위치"를 다루는 군집화 알고리즘은 보통 유클리드 거리를 쓴다.
(단, KMeans도 코사인 거리로 평가 가능. 평가지표인 실루엣 스코어는 메트릭을 선택할 수 있음).

정규화된 벡터에서는 내적·코사인·유클리드 거리가 연결된다.
벡터를 L2 정규화해서 길이를 모두 1로 맞추면, 두 벡터의 내적은 곧 코사인 유사도와 같아진다.
또한 이때 유클리드 거리도 코사인 유사도와 단조 관계를 갖는다.
그래서 임베딩 검색 시스템에서는 벡터를 미리 정규화해두고 내적 검색으로 코사인 검색을 빠르게 구현하는 경우가 많다.
다른 유사도 측정 방법들
코사인과 유클리드 외에도 상황에 따라 쓰이는 측정법들이 있다.
Jaccard 유사도
- 두 집합이 얼마나 겹치는가.
$$
J(A, B) = \frac{|A \cap B|}{|A \cup B|}
$$
벡터가 아니라 집합 간 유사도다.
e.g) 문서 A의 단어 집합과 문서 B의 단어 집합이 얼마나 겹치는지.
단어 순서나 빈도는 무시하고 "이 단어가 나왔는가/안 나왔는가"만 본다.
중복 제거 집합을 쓰므로 같은 단어가 10번 나오든 1번 나오든 동일 취급.
- 값 범위: 0(겹치는 단어 없음) ~ 1(완전히 같은 단어 집합)
- 주로 쓰이는 곳: 짧은 텍스트(태그, 키워드 목록) 비교, 추천 시스템에서 아이템 유사도
맨해튼 거리(Manhattan / L1 distance)
- 격자를 따라 이동하는 거리
$$
d_1 = \sum_i |a_i - b_i|
$$
유클리드 거리(직선)가 아니라, 각 차원의 차이를 절댓값으로 더한 것.
"블록을 따라 걷는 거리"라서 맨해튼(뉴욕 격자 도로)이라는 이름이 붙었다.
- 이상치(outlier)에 유클리드보다 덜 민감하다.
- 유클리드는 차이를 제곱하므로 큰 차이가 과도하게 증폭되지만, 맨해튼은 그냥 더한다
- 고차원 데이터에서 유클리드보다 안정적으로 동작하는 경우가 있다
상황별 선택 기준
| 측정법 | 보는 것 | 주로 쓰이는 곳 |
| 코사인 유사도 | 방향(각도) | 텍스트 벡터(TF-IDF, 임베딩) 비교 |
| 유클리드 거리 | 절대 위치 | 군집화 중심점 거리, 저차원 dense 벡터 |
| Jaccard 유사도 | 집합 겹침 | 태그·키워드 집합 비교 |
| 맨해튼 거리 | L1 절대 거리 | 이상치에 강건한 거리 계산 필요 시 |
4. 거리를 유사도로 변환
- 유사도: 군집화에서 "이 데이터가 이 중심점과 얼마나 가까운가"를 직관적으로 나타낸 0~1 사이의 점수.
- 유사도 변환:
$$\text{similarity} = \frac{1}{1+d}$$
- $d$: (유클리드) 거리.
- $d = 0$ : 유사도 1(완전 일치),
- 거리가 커질수록 유사도가 0에 가까워지지만 절대 음수가 되지 않으며 절대 0이 되지도 않는다(부드럽게 감소).
- 거리라는 "작을수록 좋은" 지표를 "클수록 좋은" 점수로 바꿔주는 간단하지만 실용적인 트릭.
5. 정리
- 코사인 유사도는 벡터의 "방향"만 보고, 유클리드 거리는 "절대 위치(크기 포함)"를 봄
- 텍스트 비교는 거의 항상 코사인, 군집화의 중심점 거리는 유클리드가 일반적
- 코사인 값은 코시-슈바르츠 부등식에 의해 항상 $[-1,1]$ 범위로 깔끔하게 떨어짐
- Jaccard 유사도는 집합 겹침을 보며 태그·키워드 비교에 적합, 맨해튼 거리는 이상치에 강건
- 거리를 0~1 사이 유사도 점수로 바꿀 때는 $1/(1+d)$ 같은 변환을 씀
벡터 사이 거리를 계산할 수 있게 됐다면, 이제 "비슷한 벡터들을 그룹으로 묶는" 작업을 할 수 있다.
그게 K-Means 클러스터링이다.
GitHub 댓글