티스토리 뷰
오늘은 문서 간 유사도를 측정하는 다양한 방법을 학습했습니다.
코사인 유사도, 유클리드 거리, 자카드 유사도를 활용하여 문서 간의 관계를 분석하고,
이를 기반으로 추천 시스템을 구현하는 방법도 실습했습니다.

1. 코사인 유사도 (Cosine Similarity)
코사인 유사도는 두 벡터 간의 각도를 이용하여 유사도를 측정하는 방법입니다.
벡터의 크기가 아닌 방향(패턴)에 초점을 맞추기 때문에 문서 길이에 영향을 받지 않습니다.
1.1 코사인 유사도 공식
cos(θ)=A⋅B∣∣A∣∣×∣∣B∣∣\cos(\theta) = \frac{A \cdot B}{||A|| \times ||B||}
1.2 문서 간 코사인 유사도 계산
from numpy import dot
from numpy.linalg import norm
import numpy as np
def cos_sim(A, B):
return dot(A, B) / (norm(A) * norm(B))
# 예제 문서 벡터
doc1 = np.array([0, 1, 1, 1]) # "저는 사과 좋아요"
doc2 = np.array([1, 0, 1, 1]) # "저는 바나나 좋아요"
doc3 = np.array([2, 0, 2, 2]) # "저는 바나나 좋아요 저는 바나나 좋아요"
# 문서 유사도 계산
print('문서 1과 문서 2의 유사도:', cos_sim(doc1, doc2)) # 0.6667
print('문서 1과 문서 3의 유사도:', cos_sim(doc1, doc3)) # 0.6667
print('문서 2와 문서 3의 유사도:', cos_sim(doc2, doc3)) # 1.0000
문서 2와 문서 3의 유사도가 1에 가까운 것은 문서 3이 문서 2의 단어 빈도를 단순 증가시킨 형태이기 때문입니다.
2. 코사인 유사도를 이용한 추천 시스템
코사인 유사도를 활용하면 문서(영화 줄거리 등) 간 유사도를 비교하여 비슷한 문서를 추천할 수 있습니다.
예제에서는 영화 줄거리를 기반으로 유사한 영화를 추천하는 시스템을 구축했습니다.
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# 데이터 로드
data = pd.read_csv('movies_metadata.csv', low_memory=False).head(20000)
# 줄거리(overview) 결측값 처리
data['overview'] = data['overview'].fillna('')
# TF-IDF 행렬 생성
tfidf = TfidfVectorizer(stop_words='english')
tfidf_matrix = tfidf.fit_transform(data['overview'])
# 코사인 유사도 계산
cosine_sim = cosine_similarity(tfidf_matrix, tfidf_matrix)
# 영화 제목을 key, 인덱스를 value로 하는 딕셔너리 생성
title_to_index = dict(zip(data['title'], data.index))
# 영화 추천 함수
def get_recommendations(title, cosine_sim=cosine_sim):
idx = title_to_index[title]
sim_scores = list(enumerate(cosine_sim[idx]))
sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)[1:11]
movie_indices = [idx[0] for idx in sim_scores]
return data['title'].iloc[movie_indices]
# 특정 영화와 유사한 영화 추천
print(get_recommendations('The Dark Knight Rises'))
코사인 유사도를 이용해 특정 영화와 유사한 영화 목록을 추천할 수 있습니다.
3. 유클리드 거리 (Euclidean Distance)
유클리드 거리는 두 벡터 간의 직선 거리를 계산하는 방법입니다.
값이 작을수록 문서 간 유사성이 높다는 의미를 가집니다.
3.1 유클리드 거리 공식
d(A,B)=∑(Ai−Bi)2d(A, B) = \sqrt{\sum (A_i - B_i)^2}
3.2 문서 간 유클리드 거리 계산
import numpy as np
def euclidean_dist(x, y):
return np.sqrt(np.sum((x - y) ** 2))
# 예제 문서 벡터
doc1 = np.array([2, 3, 0, 1])
doc2 = np.array([1, 2, 3, 1])
doc3 = np.array([2, 1, 2, 2])
docQ = np.array([1, 1, 0, 1])
# 문서 유사도 계산
print('문서 1과 문서 Q의 유사도:', euclidean_dist(doc1, docQ)) # 2.236
print('문서 2과 문서 Q의 유사도:', euclidean_dist(doc2, docQ)) # 3.162
print('문서 3과 문서 Q의 유사도:', euclidean_dist(doc3, docQ)) # 2.449
문서 1이 문서 Q와 가장 가까운 거리(2.236)를 가지므로 문서 Q와 가장 유사한 문서입니다.
4. 자카드 유사도 (Jaccard Similarity)
자카드 유사도는 집합 간 유사도를 측정하는 방법입니다.
교집합을 합집합으로 나눈 값으로 계산되며, 값이 클수록 두 문서가 비슷하다는 의미를 가집니다.
4.1 자카드 유사도 공식
J(A,B)=∣A∩B∣∣A∪B∣J(A, B) = \frac{|A \cap B|}{|A \cup B|}
4.2 문서 간 자카드 유사도 계산
# 예제 문서
doc1 = "apple banana everyone like likey watch card holder"
doc2 = "apple banana coupon passport love you"
# 단어 토큰화
tokenized_doc1 = set(doc1.split())
tokenized_doc2 = set(doc2.split())
# 교집합과 합집합
intersection = tokenized_doc1.intersection(tokenized_doc2)
union = tokenized_doc1.union(tokenized_doc2)
# 자카드 유사도 계산
jaccard_similarity = len(intersection) / len(union)
print('자카드 유사도:', jaccard_similarity) # 0.1667
문서 간 공통 단어가 많을수록 유사도가 증가하는 특징이 있습니다.
5. 결론 및 정리
5.1 오늘 배운 내용
오늘은 코사인 유사도, 유클리드 거리, 자카드 유사도를 활용하여 문서 간 유사도를 측정하는 방법을 학습했습니다.
각 기법은 서로 다른 방식으로 유사도를 평가하며, 코사인 유사도는 방향을, 유클리드 거리는 거리 차이를, 자카드 유사도는 단어 집합을 비교하는 특징이 있습니다.
또한, 코사인 유사도를 활용한 영화 추천 시스템을 구현하며, 추천 시스템의 기본 원리를 이해할 수 있었습니다.
5.2 추가 분석 가능성
추가적으로 Word2Vec, FastText 같은 단어 임베딩 기법을 활용하면 단어 간 의미 기반 유사도를 평가할 수 있습니다.
또한, BERT나 GPT 모델을 활용하면 문장의 문맥까지 고려한 유사도 분석이 가능합니다.
앞으로 다양한 기법을 적용하여 문서 유사도를 더 정교하게 분석해 보면 좋을 것 같습니다.
'LG U+ Why Not SW 부트캠프 5기' 카테고리의 다른 글
| 상관분석과 회귀분석 실습 (Python 기초부터 통계 이론까지) (0) | 2025.03.27 |
|---|---|
| [Python] 타이타닉 생존자 예측 모델 실습 (0) | 2025.03.27 |
| [Python] 한국어 전처리와 단어 표현 기법 (0) | 2025.03.11 |
| 파이썬을 이용한 미국 항공 운항 데이터 분석(실습) (1) | 2025.02.28 |
| 주식 시세 분석 및 데이터 처리 (0) | 2025.02.21 |
