문서 단어 행렬(DTM) 의 단점, 중요한 단어에 대해서 가중치를 주지 못하는 단점을 보완한 방법이 단어 빈도-역 문서 빈도(TF-IDF: Term Frequency-Inverse Document Frequency) 이다. 문서의 빈도에 특정 식을 취하여 DTM 내의 각 단어들에 가중치를 주는 방법이다. TF-IDF 의 값이 높을수록 중요도가 높다. TF-IDF 의 특징은 모든 문서에서 자주 등장하는 a 나 the 같은 단어는 중요도가 낮다고 판단하며, 특정 문서에서만 자주 등장하는 단어를 중요도가 높다고 판단한다.
IF-IDF 에 적용되는 특정 식은 TF 값 과 IDF 값을 곱하는 것이다. (IDF 값은 DF 값의 역수이다.)
- tf(d,t) : 특정 문서 d 에서의 특정 단어 t 의 등장 횟수.
- df(t) : 특정 단어 t가 등장한 문서의 수.
- idf(d,t) : df(t)에 반비례하는 수. n 을 총 문서 개수라고 할 때, 자연로그 ln(n/(1+df(t)))
import pandas as pd from math import log docs = [ '먹고 싶은 사과', '먹고 싶은 바나나', '길고 노란 바나나 바나나', '저는 과일이 좋아요' ] vocab = list(set(w for doc in docs for w in doc.split())) # 중복 제거, 단어 토큰화 vocab.sort() # 오름차순 정렬 : ['과일이', '길고', '노란', '먹고', '바나나', '사과', '싶은', '저는', '좋아요'] N = len(docs) # 총 문서 수 def tf(t, d): return d.count(t) def idf(t): df = 0 for doc in docs: df += t in doc # in 연산. True / False... True = 1 return log(N/(df + 1)) def tfidf(t, d): return tf(t, d) * idf(t) result = [] for i in range(N): # 각 문서별 result.append([]) d = docs[i] for j in range(len(vocab)): t = vocab[j] result[-1].append(tf(t,d)) # tf : 문서별 단어 빈도수 구하기 # [[0, 0, 0, 1, 0, 1, 1, 0, 0], [0, 0, 0, 1, ... tf_ = pd.DataFrame(result, columns = vocab) """ DTM 과일이 길고 노란 먹고 바나나 사과 싶은 저는 좋아요 0 0 0 0 1 0 1 1 0 0 1 0 0 0 1 1 0 1 0 0 2 0 1 1 0 2 0 0 0 0 3 1 0 0 0 0 0 0 1 1 """ result = [] for j in range(len(vocab)): t = vocab[j] result.append(idf(t)) idf_ = pd.DataFrame(result, index = vocab, columns = ["IDF"]) """ IDF 과일이 0.693147 길고 0.693147 노란 0.693147 먹고 0.287682 바나나 0.287682 사과 0.693147 싶은 0.287682 저는 0.693147 좋아요 0.693147 """ result = [] for i in range(N): result.append([]) d = docs[i] for j in range(len(vocab)): t = vocab[j] result[-1].append(tfidf(t,d)) tfidf_ = pd.DataFrame(result, columns = vocab) """ 과일이 길고 노란 ... 싶은 저는 좋아요 0 0.000000 0.000000 0.000000 ... 0.287682 0.000000 0.000000 1 0.000000 0.000000 0.000000 ... 0.287682 0.000000 0.000000 2 0.000000 0.693147 0.693147 ... 0.000000 0.000000 0.000000 3 0.693147 0.000000 0.000000 ... 0.000000 0.693147 0.693147 """ | cs |
공교롭게도 바나나가 잘렸지만; 문서2 에서의 바나나 tfidf(0.28) 보다, 문서3 에서의 바나나 tfidf(0.57) 가 높은 것으로 보아 문서3 에서의 바나나가 더 중요하다는 것을 인식해야 한다.
TfidfVectorizer 를 이용한 TF-IDF
from sklearn.feature_extraction.text import TfidfVectorizer corpus = [ 'you know I want your love', 'I like you', 'what should I do ', ] tfidfv = TfidfVectorizer().fit(corpus) print(tfidfv.transform(corpus).toarray()) print(tfidfv.vocabulary_) """ [[0. 0.46735098 0. 0.46735098 0. 0.46735098 0. 0.35543247 0.46735098] [0. 0. 0.79596054 0. 0. 0. 0. 0.60534851 0. ] [0.57735027 0. 0. 0. 0.57735027 0. 0.57735027 0. 0. ]] {'you': 7, 'know': 1, 'want': 5, 'your': 8, 'love': 3, 'like': 2, 'what': 6, 'should': 4, 'do': 0} """ | cs |
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.
,