본문 바로가기
Data Science & AI/Data Analysis

코사인 유사도(CountVectorizer , TF-IDF 벡터화)

by skwkiix 2024. 2. 12.
728x90

 

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

 

https://velog.io/@ranyjoon/

 

코사인 유사도란, 벡터 간의 코사인 각도를 이용하여 비교하는 두 벡터간의 유사도이다.

각도 = 유사도로 판별하여 거리가 중요하지 않을 경우에 사용하는 방식으로, 자연어 처리 등에 사용되는 기법이다.

 

코사인 유사도는 -1 ~ 1 사이의 값을 가진다.

 

1 : 두 벡터가 0도의 각을 가짐

0 : 두 벡터가 90 도의 각을 가짐

-1 : 두 벡터가 180도의 각을 가짐

 

예를 들어, 다음과 같은 두 문장을 각각 벡터화해보면

text1 = '파이썬은 쉬워요'

text2 = '파이썬은 쉬워요 파이썬은 쉬워요'

  파이썬은 쉬워요
text1 1 1
text2 2 2

 

단어가 똑같고 빈도수만 다르기 때문에, 코사인 유사도를 계산할 경우 값이 1이 나오게 된다. ( 빈도수는 상관 없다.)

 


2. 벡터화(CountVectorizer vs TF-IDF 차이)

  표현 방법 가중치 정규화
CountVectorizer 단어의 출현빈도 출현빈도 단순 계산  
TF- IDF 상대적인 중요성 평가 출현빈도와 역문서빈도를 곱한 값 문서의 길이에 따라 달라지는 효과 방지

 

TF-IDF

  • 요약 ) 단어의 빈도를 그 단어가 나타난 문서의 수로 나눠쥼
  • TF : Term Frequency(단어 빈도) : 해당단어의 출현 빈도를 전체 단어 수로 나눈 값
  • IDF : Inverse Document Frequency(역문서 빈도) : 특정 단어가 전체 문서집합에서 얼마나 희귀한지 측정, 전체 문서 나누기 해당단어를 포함한 문서의 수에 로그를 취한 값 ( 흔하면 작은 값, 흔하지 않으면 큰값이 발생)

CountVectorizer 처럼 bow 기반으로 벡터화하게 되면, 단어가 많다는 것이 좋다는 뜻이 되므로, TF-IDF 처럼 빈도를 고려하는 것이 더 좋은 접근방법일 수 있다.

 

 

 

소스 코드

다음 4문장에 대해서, 각각 벡터화 방법으로 결과를 비교해본다.

from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer

text1 = '나는 강아지를 좋아한다.'
text2 = '나는 고양이를 좋아한다.'
text3 = '나는 강아지를 좋아하고 고양이를 좋아한다.'
text4 = '나는 강아지를 좋아한다 나는 강아지를 좋아한다.'

sentences = [text1, text2, text3, text4]

# CountVectorizer 벡터화
count_vectorizer = CountVectorizer()
count_vectors = count_vectorizer.fit_transform(sentences)

# TF-IDF 벡터화
tfidf_vectorizer = TfidfVectorizer()
tfidf_vectors = tfidf_vectorizer.fit_transform(sentences)

# 각각의 단어에 대한 인덱스 확인
print("CountVectorizer를 사용하여 벡터화한 결과:")
print(count_vectors.toarray())
print("CountVectorizer에서의 각 단어 인덱스:", count_vectorizer.vocabulary_)
print("\nTF-IDF를 사용하여 벡터화한 결과:")
print(tfidf_vectors.toarray())
print("TF-IDF에서의 각 단어 인덱스:", tfidf_vectorizer.vocabulary_)

 

CountVectorizer 는 bow count 기반이므로 일반적으로 정수 형태를 띄지만, TF-IDF는 빈도기반으로 실수형태를 띈다.

 


3.코사인 유사도 확인( CountVectorizer , TF-IDF)

소스 코드 - 코사인 유사도 계산

from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

# CountVectorizer를 사용하여 벡터화
count_vectorizer = CountVectorizer()
count_vectors = count_vectorizer.fit_transform(texts)

# TF-IDF 벡터화
tfidf_vectorizer = TfidfVectorizer()
tfidf_vectors = tfidf_vectorizer.fit_transform(texts)

# 코사인 유사도 계산
cosine_sim_count = cosine_similarity(count_vectors, count_vectors)
cosine_sim_tfidf = cosine_similarity(tfidf_vectors, tfidf_vectors)

print("CountVectorizer를 사용한 코사인 유사도:")
print(cosine_sim_count)
print("\nTF-IDF를 사용한 코사인 유사도:")
print(cosine_sim_tfidf)

 

결과 화면

 

 


 

소스 코드 - 가장 유사한 문장 찾기

# text1을 제외한 나머지 문장들
texts_except_text1 = [text2, text3, text4]

# text1과 나머지 문장들 간의 코사인 유사도 계산
cosine_sim_text1 = cosine_similarity(tfidf_vectors[0], tfidf_vectorizer.transform(texts_except_text1)).flatten()

# 가장 유사한 문장의 인덱스 찾기
most_similar_text_index = np.argmax(cosine_sim_text1)  # 가장 높은 유사도를 가진 인덱스

# 주어진 텍스트에서 가장 유사한 문장 출력
most_similar_text_to_text1 = texts_except_text1[most_similar_text_index]

print("text1 기준으로 가장 유사한 문장:", most_similar_text_to_text1)

# 해당 문장과 text1 간의 코사인 유사도 출력
cosine_sim_between_texts = cosine_similarity(tfidf_vectorizer.transform([text1]), tfidf_vectorizer.transform([most_similar_text_to_text1]))
print("text1과 가장 유사한 문장 간의 코사인 유사도:", cosine_sim_between_texts)

 

결과 화면

text1 기준으로 가장 유사한 문장: 나는 강아지를 좋아한다 나는 강아지를 좋아한다.
text1과 가장 유사한 문장 간의 코사인 유사도: [[1.]]

 

728x90