본문 바로가기
머신러닝, 딥러닝/머신러닝

TF-IDF (Term Frequency - Inverse Document Frequency)

by 장찐 2022. 5. 15.

📚 TF-IDF 란 

 TF-IDF는 단어의 빈도와 역 문서 빈도를 사용하여 단어들마다 중요한 정도에 따라서 가중치를 부여하는 방법이다. 모든 문서에서 등장하는 단어는 중요도가 낮으며, 특정 문서에서만 자주 등장하는 단어는 중요도가 높다. 

 

 TF-IDF 생성을 위해서는 문서를 사용된 단어의 벡터로 나타내야 한다. 즉, 각 문서들을 하나의 문자열로 나타내야 한다. 

위의 세 가지 문서의 경우 apple/banana/carrot/eggplant/mango/orange로 구성된 벡터로 나타낼 수 있다. 각 문서마다 벡터의 차원은 동일하다. 이 때 벡터의 원소들로 단순 corpus의 빈도를 사용할 수도 있고, TF-IDF 를 사용할 수도 있다. 

 

Term Frequency  : 단순 빈도 

 각 문서에서 나타난 전체 단어를 알파벳 순으로 배열하고, 각 문서별로 사용된 단어(term)를 카운팅해서 vector로 표현할 수 있다. 이를 DTM(Document Term Matrix)라고 한다. DTM을 만들기 위해서는 각 문서의 vector size를 동일하게 맞춰야 한다. 

위의 문서 3개는 아래와 같이 단어 벡터로 나타낼 수 있다.

 

하지만 이렇게 단순 빈도로 나타낸 DTM은 각 단어가 해당 문서에서 가지는 상대적 중요성을 표현하지 못한다는 단점이 있다. 

 

 

✅ TF-IDF (Term Frequency - Inverse Document Frequency) 

 특정 단어가 해당 문서에서 얼마나 unique 한가를 나타내기 위한 방식이다. TF-IDF가 높을수록 해당 단어가 다른 문서에서는 적게 사용된다는 것을 의미한다(=해당 문서에서 uniqueness가 높다) 

위의 예시에서 word1은 doc1, doc2에 모두 10회 등장하지만 doc1에서 상대적 중요도가 높다고 볼 수 있다. 

 

IDF는 DF의 역수(1/DF)이다. DF는 전체 문서들 중에서 해당 문서를 제외한 나머지 문서에서 해당 단어가 몇 번 사용되었는지를 의미한다. 

 

TF IDF를 계산하는 간단한 예시는 아래와 같다. 

 DF 표

• word1 의 경우 Doc1 입장에서 다른 문서(Doc2)에도 사용되었기 때문에 DF=1 

word2의 경우 Doc1 입장에서 Doc2에도 사용되었기 때문에 DF=1, Doc2 입장에서는 Doc1에 사용되지 않았기 때문에 0. 

 

실제로 IDF를 계산할 때에는 분모가 0이 되는 것을 방지하기 위해서 1을 더하고, 로그를 취한다. 

 

df(t) : 특정 단어 t가 등장한 문서의 수 

idf(d,t) : df(t) 의 역수 (TFIDF 최종 계산 값 아님)

D : 총 문서의 수 

 

그리고 TF-IDF의 최종 값은 아래와 같이 TF * IDF 로 계산된다. 

 

 여기서 로그를 붙이는 이유는 총 document의 수인 n이 커질수록 IDF 값이 기하급수적으로 커지기 때문이다.

아래 예시를 참고 (https://wikidocs.net/31698)

 

 

 

 

• n : 문서 수

• df(t) : 특정 단어 t가 등장한 문서의 수

• idf(d,t) : df(t) 의 역수 (TFIDF 최종 계산 값 아님)

 

로그 없이 계산을 하면 희소한 단어의 IDF 값이 지나치게 커지게 된다. 

 

 

 

 

 

 

 

 

 

 

 

여기에 로그를 붙이면 전체 단어들의 IDF 값 편차가 줄어든다. 

 

 

 

 

 

 

 

 

  위의 표에서 df(t) 값이 작을수록 다른 문서에서 적게 사용되어서 희귀한 변수임을 나타낸다. 정관사와 같은 불용어는 희귀한 단어들보다 훨씬 많이 사용되는데, log를 씌우지 않으면 희귀한 단어에 지나치게 많은 가중치가 부여된다. 로그를 씌우면 이 편차를 감소시킬 수 있다. 

 


 

✅ 예시 : CountVectorizer() 

 python에서 사용할 경우에 단순 빈도(TF)는 Counvectorizer 클래스를, TF IDF의 경우 TfidVectorizer클래스를 사용한다. 

import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer # frequency based DTM
from sklearn.feature_extraction.text import TfidfVectorizer # tf-idf based DTM

#예시 문서 
TEXT = ['banana apple apple eggplant', 
        'orange carrot banana eggplant', 
        'apple carrot banana banana', 
        'orange banana grape'
]

위와 같이 필요한 라이브러리를 불러오고 예시 문서를 설정한다. 

 

#CountVectorizer
tf_vectorizer = CountVectorizer()
tf_features = tf_vectorizer.fit_transform(TEXT)
tf_features

#DTM 생성
features = np.array(tf_features.todense())
features

DTM을 나타내면 위와 같다. 각 행은 개별 문서에 대한 벡터를 나타낸다.

 number of rows = 문서의 수 / number of columns = 단어의 수 

 

feature_names = tf_vectorizer.get_feature_names_out()
feature_names

위와 같이 get_feature_names_out 함수를 사용해서 피쳐 이름을 출력할 수도 있다. 

 

 

 

📌 문서간 유사도 계산 : Euclidean Distance  

#문서1과 문서0의 유사도 계산 
np.linalg.norm(features[1]-features[0])

#문서1과 문서2의 유사도 계산
np.linalg.norm(features[1]-features[2])

유클리디안 거리를 이용해서 각 문서들 간의 거리(유사도)를 계산할 수 있다. 

 

 

📌문서간 유사도 계산 : 코사인 유사도 

np.dot(features[0], features[1])/(np.linalg.norm(features[0])*np.linalg.norm(features[1]))

np.dot(features[0], features[2])/(np.linalg.norm(features[0])*np.linalg.norm(features[2]))

내적 값을 원점으로부터의 거리의 곱으로 나누면 코사인 유사도 계산 가능 

 

 

✅ 예시 : TfidfVectorizer() 

tfidf_vectorizer = TfidfVectorizer()
tfidf_features = tfidf_vectorizer.fit_transform(TEXT)

tfidf_features = np.array(tfidf_features.todense())
tfidf_features

 

 


📚  Reference

 

 이상엽, 연세대학교 언론홍보영상학부 부교수, 22-1학기 기계학습 이론과 실습 

https://wikidocs.net/31698

댓글