ecsimsw

DTM / TF-IDF / 문서 유사도 본문

DTM / TF-IDF / 문서 유사도

JinHwan Kim 2020. 3. 7. 10:32

1. DTM (Document-Term Matrix)

 

   : 문서 단어 행렬(DTM)은 문장 안 각 단어들의 빈도를 행렬로 표현한 것이다. 

 

2. TF-IDF

 

   : TF는 각 문서 안에서의 단어의 빈도, DF는 문서군안에서 각 단어가 등장한 문서의 수를 의미한다. IDF는 DF에 반비례하는 값이다. 이 TF-IDF를 사용하여 문장끼리의 유사도나, 단어의 중요도를 구할 수 있다.

 

#TF : term frequency 
#IDF : inverse document frequency

 

#IDF는 이 DF의 역수인 것은 맞는데, 일반 역수를 사용하면 분자 (전체 문장의 개수)가 늘어짐에 따라 분모 (등장 문장의 수)는 그를 따라가지 못하므로, 그 값이 기하급수적으로 커져 결국 단어들의 중요성을 하향평준화 시켜 비교가 어려워지므로 역수에 로그를 취하여 IDF를 정의한다. (분모가 0이 되는 것을 막기 위해, 등장 문장의 수에 1을 더하여 로그 취함) 

 

  : 한 문서 안에서 단어가 몇번 사용되는지를 구하는 것으로, 문서 안에서의 단어의 중요도를, 전체 문서군에서 단어가 등장하는 문서 비율을 구하는 것으로 특정 단어가 얼마나 희소한지를 나타낼 수 있을 것이다. 문장 안에서의 중요도 (TF)와 전체 문서군에서의 희귀성 (IDF)를 곱하여 TF-IDF를 구한다. 즉 TF-IDF가 높은 단어일수록  특정 문서 내에서 그 단어가 많이 쓰면서도, 전체 문서군에서 희귀하다는 것을 의미한다.  

 

3. Cosine Similarities 

from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(stop_words='english')

meta_file = [
    "he is jin, sorry it's fake", 
    "he is hwan it's no fake",
    "she is hong", 
    "metrix is hey jude ! jhi"]

tfidf_matrix = tfidf.fit_transform(meta_file)
similarities = (tfidf_matrix * tfidf_matrix.T)

print(tfidf.get_feature_names())

print("\ntfidf_matrix : ")
print(tfidf_matrix.toarray())

print("\ntfidf_matrix.T : ")
print(tfidf_matrix.T.toarray())

print("\nsimilarities : ")
print(similarities.toarray())
['fake', 'hey', 'hong', 'hwan', 'jhi', 'jin', 'jude', 'metrix', 'sorry']

tfidf_matrix :
[[0.48693426 0.         0.         0.         0.         0.61761437     0.         0.         0.61761437]
 [0.6191303  0.         0.         0.78528828 0.         0. 		0.         0.         0.        ]
 [0.         0.         1.         0.         0.         0.	        0.         0.         0.        ]
 [0.         0.5        0.         0.         0.5        0.	        0.5        0.5        0.        ]]

tfidf_matrix.T :
[[0.48693426 0.6191303  0.         0.        ]
 [0.         0.         0.         0.5       ]
 [0.         0.         1.         0.        ]
 [0.         0.78528828 0.         0.        ]
 [0.         0.         0.         0.5       ]
 [0.61761437 0.         0.         0.        ]
 [0.         0.         0.         0.5       ]
 [0.         0.         0.         0.5       ]
 [0.61761437 0.         0.         0.        ]]

similarities :
[[1.         0.30147576 0.         0.        ]
 [0.30147576 1.         0.         0.        ]
 [0.         0.         1.         0.        ]
 [0.         0.         0.         1.        ]]

 

4. Search the most similar sentence

# 검색 데이터와 후보군 데이터를 합침
data_file.insert(0, search_string)

# tfidf matrix를 만듦
data_tfidf = tfidf.fit_transform(data_file)

# 전체 행렬을 곱할 필요가 없으므로 검색 열[0]을 분리하고, 후보군 행렬([1:,])의 transposed와 곱함.
# 문자-단어 idf * 단어-문자 idf

similarities =  data_tfidf.toarray()[0] * data_tfidf[1:,].T

# 큰 순으로 정렬
similarities = sorted(similarities, reverse=True)
print(similarities)
[0.5317722537280788, 0.5317722537280788, 0.0, 0.0]

 

Comments