문과 열등생 2024. 2. 29. 16:41

Embedding을 위한 vectorizaton에서 신경망을 사용하지 않는 방식을 None-Learned Embedding이라고 한다. None-Learned Embedding 중 문서에 대한 Vectorization 방법으로는 크게 DTM과 TF-IDF가 있다.

 

DTM과 TF-IDF 모두 BoW 방식에 기반한다. BoW는 Bag of Words로, 단어의 순서는 무시하고 오직 단어의 빈도수에만 집중하여 

 

DTM : Document Term Matrix (문서 단어 행렬)

  • 문서 집합을 표현하는 방법 중 하나로, 각 문서에 등장하는 단어들의 빈도를 행렬 형태로 나타내는 방식으로 vectorization을 수행한다.
  • DTM의 (i, j)번 째 원소는 i 번째 문서에 j 번째 단어가 등장한 횟수이다.
  • DTM은 단어의 빈도만을 고려하고 문맥을 고려하지 않은 채로 문서 집합의 특성을 벡터로 표현한다는 점에서, 정보의 손실이 발생하며 이러한 단점을 보완하고자 TF-IDF가 등장하였다.
문서1: "apple banana banana"
문서2: "banana cherry"
문서3: "apple cherry cherry

        apple  banana  cherry
문서1     1       2       0
문서2     0       1       1
문서3     1       0       2
[[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}

 

DTM을 코드로 구현하면 다음과 같다.

from sklearn.feature_extraction.text import CountVectorizer

corpus = [
    'you know I want your love',
    'I like you',
    'what should I do ',
]
# CountVectorizer는 정규표현식을 사용하여 단어를 텍스트에서 추출
# 기본적으로 단어 길이가 2 이상인 것만 추출
vector = CountVectorizer()

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

# 각 단어와 맵핑된 인덱스 출력
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 : Term Frequency-Inverse Document Frequency

  • 문서의 유사도, 검색 시스템 등에서 검색 결과의 순위 등을 구하는 작업에 주로 사용되는 것으로,
  • 단어 빈도(Term Frequency)와 역문서빈도(Inverse Document Frequency)로 구성된다.
  • 단어 빈도 : 문서 내에서 특정 단어의 등장 빈도를 나타내는 것으로, 일반적으로 단어가 문서 내에서 자주 등장할수록 해당 단어의 중요성이 높다고 가정
  • 역문서빈도 : 특정 단어가 여러 문서에 자주 등장할수록 해당 단어의 중요성이 낮다고 판단
  • 결과값 공식 : TF-IDF(t,d)=TF(t,d)×IDF(t)
    • t, d : 단어, 문서
    • TF(t, d) : 단어 t의 문서 d 내에서의 등장 빈도
    • IDF(t) : 단어 t의 역문서 빈도
      • $idf(d, t) = log(n/1+df(t))$
      • 로그를 씌우는 이유는 희귀 단어들에 대한 엄청난 가중치를 줄이기 위함
  • 문서의 벡터화를 통해 문서 클러스터링, 유사한 문서 찾기, 문서의 효과적 분류 등이 중요

 

TF-IDF를 코드로 구현하면 다음과 같다.

# 총 문서의 수
N = len(docs)
print('총 문서의 수', N)

# TF를 구하는 함수
def tf(t, d):
  return d.count(t)
  
  # IDF를 구하는 함수
def idf(t):
  df = 0
  for doc in docs:
    df += t in doc
  return log(N/(df+1))
  
  # TF와 IDF의 값을 곱하는 함수
def tfidf(t, d):
  return tf(t,d)* idf(t)
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_)