본문 바로가기
Archive/자연어처리

[밑딥2] 시소러스(thesaurus)와 기본적인 전처리

by 다람이도토리 2021. 7. 19.

앞으로, 밑딥 2를 통해 자연어 처리에 대해 기본적인 공부를 진행하고자 합니다.
크게 2장부터 내용을 시작하며, 내용 요약 및 추가로 찾은 내용을 정리합니다.

추가로, 패키지들의 사용법 또한 정리합니다.

-----------------------------------------------------------------------

 

시소러스란?

앞으로 NLP에서 단어의 의미는 '사전적 의미'보다는, 유의어에 집중하려고 한다.

유의어 집단을 통하여, 단어들과의 연관관계를 파악한다.

이러한 시소러스의 문제점은 다음과 같다.

- 사람이 직접 레이블링해야 하므로, 시대의 변화에 대응하기는 어렵다.
- 단어의 미묘한 차이를 표현하기 어렵다.

토큰화와 id부여

우리는 문장이나 긴 글을 분석을 위한 작은 단위로 나누어야 하는데, 이를 토큰화라고 한다. 그리고 이러한 토큰들에 단어별로 id를 부여할 수 있다.

# 토큰화 _ 패키지 없이
text = 'The quick brown fox jumps over the lazy dog.'
text = text.lower()
text = text.replace('.',' .')
words = text.split(' ')
print(words)
# 아이디부여 - 패키지 없이
word_to_id = {}
id_to_word = {}

for word in words:
  if word not in word_to_id:
    new_id = len(word_to_id)
    word_to_id[word] = new_id
    id_to_word[new_id] = word

 

패키지를 사용한 방법은 다음과 같다.

# 토큰화 후 아이디 부여. 패키지 사용

nltk.download('punkt')
# 이 방법을 사용할 경우 말뭉치를 별도로 리스트화로 저장해야 한다.
corpus = ['The quick brown fox jumps over the lazy dog.']

from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer(tokenizer = nltk.word_tokenize).fit(corpus)
vect.vocabulary_

패키지를 보면 Vectorzier라는 말이 있듯이, 단어를 벡터화 하는 것이다. 이를 이해하고자 한다.

 

분포가설

분포 가설은 '단어의 의미는 주변 단어에 의해 형성된다'에서 출발한다. 즉, 단어 자체가 아니라 단어가 사용된 맥락이 의미를 형성한다는 의미이다. 즉 주변의 단어를 통해 맥락을 확인해본다.

N-gram

이러한 맥락에서, 여러개의 단어를 묶어서 이를 토큰화 시킬수 있는데, 이를 N-gram이라고 한다.

# n-gram
vect = CountVectorizer(ngram_range=(2, 2)).fit(corpus)
vect.vocabulary_

한편, 단어의 맥락, 즉 특정 단어가 주변 단어에 어떻게 영향을 주는지 표현하는 행렬을 만들 수 있는데, 이를 동시발생행렬이라 한다.

예시>

I like pasta

I like eating pizza

2개의 문장에 대해서 동시발생행렬을 만들자.
윈도우 크기, 즉 좌우 1단어만 본다고 가정을 하고 행렬을 만들면 다음과 같다.

  I like pasta eating pizza
I 0 2 0 0 0
like 2 0 1 1 0
pasta 0 1 0 0 0
eating 0 1 0 0 1
pizza 0 0 0 1 0

Rmk. 이를 확률론적 방법으로도 접근할 수 있다.

def create_co_matrix(corpus, vocab_size, window_size=1):
  corpus_size = len(corpus)
  co_matrix = np.zeros((vocab_size, vocab_size), dtype = np.int32)

  for idx, word_id in enumerate(corpus):
    for i in range(1, window_size+1):
      left_idx = idx - 1
      right_idx = idx + 1

      if left_idx >= 0:  # 좌측에 단어가 있다면
        left_word_id = corpus[left_idx]
        co_matrix[word_id, left_word_id] += 1
      
      if right_idx < corpus_size:
        right_word_id = corpus[right_idx]
        co_matrix[word_id, right_word_id] += 1
  
  return co_matrix

이를 바탕으로, 문장 내 특정 단어가 어떤 단어들에게 영향을 주었는지 행렬로 나타낼 수 있으며 이를 활용하여 코사인 유사도 등을 활용, 단어간 유사도를 계산할 수 있다.

Stop Words

불용어라고 한다. 보통 영어의 경우 관사나 접속사, 한국어의 경우는 조사를 제외하는 방법이다.

vect = CountVectorizer(stop_words="english").fit(corpus)
vect.vocabulary_