cs 텍스트 유사도 Text Similarity 개요
본문 바로가기
  • 매일 한걸음씩
  • 매일 한걸음씩
개발/NLP(Natural Language Processing)

텍스트 유사도 Text Similarity 개요

by 시몬쯔 2020. 8. 11.
728x90

두 단어 혹은 두 문장이 주어졌을 때, 유사도를 어떻게 측정할 수 있을까?

 

대표적인 Text Similarity 측정 metric인 Cosine SimilarityJaccard Similarity를 통해 측정할 수 있을 것이다.

 

 

1. Jaccard Similarity 자카드 유사도 

 

우선 자카드 유사도로 유사도를 측정하기 전에 Lemmatization 과정이 필요하다. 표제어 추출이라 번역될 수 있는 lemmatization이란

단어의 뿌리를 찾아가는 과정이라 볼 수 있다. 예를 들어, had와 has는 스펠링이 다르지만 뿌리는 모두 have이다. 이 때, had와 has의 표제어를 have라고 한다.

이렇게 표제어 추출 후 두 문장의 교집합과 합집합의 크기를 통해 자카드 유사도를 구한다.

 

다음의 두 문장이 주어졌다고 가정하자.

 

https://towardsdatascience.com/overview-of-text-similarity-metrics-3397c4601f50

위의 공식에 따르면 두 문장의 교집합의 단어의 갯수는 5개, 합집합은 10개가 되어서 자카드 유사도는 0.5가 된다.

 

파이썬 코드로는 이렇게 표현할 수 있다.

def get_jaccard_sim(str1, str2): 
    a = set(str1.split()) 
    b = set(str2.split())
    c = a.intersection(b)
    return float(len(c)) / (len(a) + len(b) - len(c))

여기서 짚어볼만한 점은 자카드 유사도는 set을 사용하는 만큼 중복성을 고려하지 않는다.

즉, friend라는 단어가 2번 이상나오는 것은 자카드 유사도 값에 영향을 미치지 않는다.

 

 

 

2. Cosine Similarity 코사인 유사도

 

코사인 유사도는 벡터로 표현된 두 문장의 각의 코사인값이다.

 

즉, 코사인 유사도를 계산하기 위해서는 문장을 벡터로 변환하는 작업이 필요하다.

 

크게 두가지 방법이 있는데,

1)  TF(term frequency)TF-IDF(term frequency-inverse document frequency)를 이용한 bag of words

TF와 TF-IDF 둘 중 무엇을 사용하냐는 어디에 쓸 것인지에 달려있다. TF는 일반적으로 텍스트 유사도를 계산하는데 잘 작동하고,

TF-IDF는 검색 쿼리 적절성 판단에 잘 작동한다.

 

TF-IDF에 관해 더 알고싶다면..

simonezz.tistory.com/18

 

Coursera 강의 리뷰 2 - TFIDF and Content-Based Filtering

= Term Frequency * Inverse Document Frequency Term Frequency : 얼마나 자주 그 용어가 document에서 등장했나? 얼마나 그 document와 관련되었나? Inverse Document Frequency : 얼마나 적은 documents가 이 t..

simonezz.tistory.com

 

2) Word2Vec 또는 custom word embeddings

 


 

두 방법의 큰 차이로는 다음과 같다.

 

1. tf/tf-idf는 한 단어당 한 숫자를 만들어내고 word embeddings는 한 단어당 한 벡터를 만들어낸다.

2. tf/tf-idf는 전체적으로 문서를 분류하는데 잘 작동하지만 word embeddings는 문맥적인 내용을 확인하는데에 잘 작동한다.

 

 

위에서 예시로 들었던 두 문장을 다시 살펴보자.

 

 

 

Step 1> Bag of Words를 사용하여 TF(Term Frequency)를 계산해보면,

 

 

Step 2> 위에서 눈치챘을 수도 있지만, TF는 긴 문장이나 문서일수록(단어가 많을수록) 값이 크게 나온다.

이를 해결할 수 있는 가장 직관적인 방법은 normalization이다.(vector의 norm을 1로 만드는 것)

Normalization을 하고나면, 

 

Step 3>  Cosine Similarity 코사인 유사도를 구해보면,

 

위에서 구한 자카드 유사도와 다르게 나온다.

 

 

scikit-learn을 사용한 python 코드는 다음과 같다.

from collections import Counter
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity
def get_cosine_sim(*strs): 
    vectors = [t for t in get_vectors(*strs)]
    return cosine_similarity(vectors)
    
def get_vectors(*strs):
    text = [t for t in strs]
    vectorizer = CountVectorizer(text)
    vectorizer.fit(text)
    return vectorizer.transform(text).toarray()

 

코사인 유사도와 자카드 유사도의 차이점은 아까도 언급했듯이,

 

자카드 유사도는 중복성을 고려하지 않고, 코사인 유사도는 고려한다는 점이다.

만약, 단어의 빈도수가 중요한 상황이라면 코사인 유사도를 사용하고, 그렇지 않다면 자카드 유사도를 사용하면 되겠다.

 

 

참고아티클: towardsdatascience.com/overview-of-text-similarity-metrics-3397c4601f50

728x90

댓글