Tech Trail

[NLP(자연어 처리)] 검색 엔진을 위한 TF-IDF와 Similarity 연산 본문

AI/NLP

[NLP(자연어 처리)] 검색 엔진을 위한 TF-IDF와 Similarity 연산

_밍지_ 2024. 5. 22. 18:00
728x90
반응형
SMALL

검색 엔진을 위한 TF-IDF와 Similarity 연산

검색 엔진의 핵심은 사용자가 입력한 문장과 유사한 문서를 찾아내는 것입니다. 이를 위해 TF-IDF와 Similarity 연산을 조합하여 활용합니다.

 

TF-IDF란?

TF-IDF(Term Frequency-Inverse Document Frequency)는 문서 내 단어의 중요도를 나타내는 통계적 수치입니다.

  • Term Frequency(TF): 특정 단어가 문서 내에 얼마나 자주 등장하는지 측정합니다.
  • Inverse Document Frequency(IDF): 단어가 전체 문서에서 얼마나 흔하지 않은지를 측정합니다.

TF-IDF를 사용한 키워드 추출

예를 들어, 1000개의 문서에서 각 문서당 10개의 키워드를 TF-IDF로 추출한다고 가정해봅시다. 새로운 문장이 입력되면 이 문장에서도 10개의 키워드를 추출합니다. 이 키워드를 이용해 유사한 문서를 찾는 것이 검색 엔진의 기본적인 작동 방식입니다.

 

Similarity 연산

유사도를 계산하는 방법에는 크게 두 가지가 있습니다: Jaccard Similarity와 Cosine Similarity.

 

Jaccard Similarity

Jaccard Similarity는 두 집합 간의 유사도를 측정합니다. 두 집합이 얼마나 겹치는지를 비율로 나타냅니다.

 

예를 들어, "고려대"와 "고대"는 Similarity가 높지만 "고려"는 Similarity가 낮을 수 있습니다.

만약에 "고려대학교"라고 정확하게 입력해서 일치한 것만 확인하려면 Jaccard Similarity를 사용합니다. 벡터로 변환하지 않고 단어 그대로의 유사성을 봅니다. 유사도가 정말 다르면 0, 정말 똑같으면 1을 출력합니다.

 

Jaccard Similarity 계산은 sklearn 라이브러리를 사용합니다. 두 개의 벡터를 입력받아서 이 둘의 유사도를 보여주는 함수입니다. 주의점은 이 벡터의 사이즈가 동일해야 사용 가능합니다.

 

import numpy as np
from sklearn.metrics import jaccard_score

print('Jaccard similarity:', jaccard_score(np.array([1,3,2]), np.array([1,4,5]), average='weighted'))
print('Jaccard similarity:', jaccard_score(np.array([1,3,2]), np.array([4,1,5]), average='weighted'))
print('Jaccard similarity:', jaccard_score(np.array([1,1,0,0]), np.array([1,1,0,2]), average='weighted'))

결과:

Jaccard similarity: 0.3333333333333333  
Jaccard similarity: 0.0  
Jaccard similarity: 0.75
  • 첫 번째 결과: 두 벡터에서 1이라는 숫자가 동일한 위치에 있어서 Jaccard Similarity가 0.333으로 계산되었습니다.
  • 두 번째 결과: 위치가 달라서 Jaccard Similarity가 0으로 계산되었습니다.
  • 세 번째 결과: 두 벡터에서 대부분의 값이 동일한 위치에 있어 Jaccard Similarity가 0.75로 계산되었습니다.

 

Jaccard Similarity는 위치와 값이 모두 같아야 높은 유사도를 나타내므로, 소수점 차이에도 민감합니다.

 

Cosine Similarity

Cosine Similarity는 두 벡터 간의 각도를 이용하여 유사도를 측정합니다. 벡터의 길이는 고려하지 않고 방향만을 고려합니다. 아까 예시처럼 "고려대"와 "고대"는 Similarity가 높지만 "고려"는 Similarity가 낮을 수 있습니다. 이처럼 유사한 듯 유사하지 않은 단어들이 많은데, 컴퓨터는 이를 이해하지 못합니다. 단어를 먼저 숫자로 변환해야 합니다. 이를 벡터로 변환하여 벡터들 간의 유사도를 측정하는 것이 Cosine Similarity입니다.

import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

sentence = ("오늘도 폭염이 이어졌는데요. 내일은 반가운 비 소식이 있습니다.",
            "오늘도 폭염이 이어졌는데요. 내일은 반가운 비 소식이 있습니다.",
            "폭염을 피해 놀러왔다가 갑작스런 비로 망연자실하고 있습니다.")
tfidf_vectorizer = TfidfVectorizer()
tfidf_matrix = tfidf_vectorizer.fit_transform(sentence) # vectorization

print("Cosine Similarity [1 and 2]:", cosine_similarity(tfidf_matrix[0], tfidf_matrix[1]))
print("Cosine Similarity [1 and 2]:", cosine_similarity(tfidf_matrix[0], tfidf_matrix[2]))

결과:

Cosine Similarity [1 and 2]: [[1.]]
Cosine Similarity [1 and 2]: [[0.07083962]]

 

첫 번째 문장과 두 번째 문장은 완벽히 동일하기 때문에 유사도 1이 출력됩니다. 반면, 첫 번째 문장과 세 번째 문장은 유사도가 낮습니다.

참고로, 유사도가 0이면 아무 상관이 없다는 의미이고, -1이면 많이 다르다는 의미입니다. 

 

결론

검색 엔진에서 중요한 것은 입력된 문장과 유사한 문서를 정확하게 찾아내는 것입니다. 이를 위해 TF-IDF와 Similarity 연산을 결합하여 활용할 수 있습니다. Jaccard Similarity는 단어의 일치 여부를, Cosine Similarity는 단어 간의 유사성을 측정하는 데 유용합니다.

 

이와 같은 방법을 활용하여 효과적인 검색 엔진을 구축할 수 있습니다.

728x90
반응형
LIST