[NLP] 카운트 기반 단어 표현 - (4) TF-IDF(Term Frequency-Inverse Document Frequency)

김규리·2022년 6월 26일
0

NLP

목록 보기
20/33
post-thumbnail

1. TF-IDF(단어 빈도-역 문서 빈도, Term Frequency-Inverse Document Frequency)

TF-IDF

: TF와 IDF를 곱한 값 의미
: 단어의 빈도와 역 문서 빈도(문서의 빈도에 특정 식을 취함)를 사용하여 DTM 내의 각 단어들마다 중요한 정도를 가중치로 주는 방법
ㄴ 문서의 유사도를 구하는 작업
ㄴ 검색 시스템에서 검색 결과의 중요도를 정하는 작업
ㄴ 문서 내에서 특정 단어의 중요도를 구하는 작업

  • 모든 문서에서 자주 등장하는 단어: 중요도 낮음
  • 특정 문서에서만 자주 등장하는 단어: 중요도 높음

문서: d
단어: t
문서의 총 개수: n

(1) tf(d,t): 특정 문서 d에서의 특정 단어 t의 등장 횟수
ㄴ DTM의 예제에서 각 단어들이 가진 값

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

(3) idf(d,t): df(t)에 반비례하는 수
idf(d,t) = log(n / 1+df(t))
*log를 사용하지 않았을 때, IDF를 DF의 역수로 사용한다면 총 문서의 수 n이 커질 수록, IDF의 값은 기하급수적으로 커지게 됨 (희귀 단어들에 엄청난 가중치 부여)

2. 파이썬으로 TF-IDF 직접 구현하기

import pandas as pd # 데이터프레임 사용을 위해
from math import log # IDF 계산을 위해

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
  return log(N/(df+1))

def tfidf(t, d):
  return tf(t,d)* idf(t)

# TF 구하기: DTM을 데이터프레임에 저장하여 출력
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_ = pd.DataFrame(result, columns = vocab)

# 각 단어에 대한 IDF 구하기
result = []
for j in range(len(vocab)):
    t = vocab[j]
    result.append(idf(t))

idf_ = pd.DataFrame(result, index=vocab, columns=["IDF"])

# TF-IDF 행렬 출력
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)

3. 사이킷런을 이용한 DTM과 TF-IDF 실습

  • 사이킷런 TfidfVectorizer(): TF-IDF 자동 계산
from sklearn.feature_extraction.text import CountVectorizer

corpus = [
    'you know I want your love',
    'I like you',
    'what should I do ',    
]

vector = CountVectorizer()

# 코퍼스로부터 각 단어의 빈도수를 기록
print(vector.fit_transform(corpus).toarray())

# DTM: 각 단어와 맵핑된 인덱스 출력
print(vector.vocabulary_)
[[0 1 0 1 0 1 0 1 1]
 [0 0 1 0 0 0 0 1 0]
 [1 0 0 0 1 0 1 0 0]]
{'you': 7, 'know': 1, 'want': 5, 'your': 8, 'love': 3, 'like': 2, 'what': 6, 'should': 4, 'do': 0}

# 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}
profile
connecting the dots

0개의 댓글