Development/AI

자연어 처리(NLP) 개념 잡기 (1) - 말뭉치, 토큰화

고고마코드 2022. 1. 4. 01:38
반응형

자연어 처리(NLP)를 학습할 때 필요한 용어들을 기초적인 지식 수준에서 이해하기 쉽게 정리합니다.
예제 코드는 Google Colab 을 기반으로 작성했습니다.



자연어 처리(NLP) 개념 잡기의 다른 포스팅도 참고하세요.

자연어 처리(NLP) 개념 잡기 (2) - 표제어, 어간

자연어 처리(NLP) 개념 잡기 (3) - 정제, 정규화, 불용어


말뭉치

말뭉치는 원시 텍스트(ASCII나 UTF-8)와 이 텍스트에 연관된 메타데이터를 포함한다.

메타데이터는 식별자, 레이블, 타임스탬프 등 텍스트와 관련된 어떤 부가 정보도 될 수 있다.

즉, 말뭉치는 텍스트를 가공·처리·분석할 수 있는 형태로 모아 놓은 자료의 집합이다.

단순하게 생각하면 우리가 사용하는 텍스트 표본이라고 볼 수 있다.

모두의 말뭉치 (korean.go.kr) 해당 링크에서 여러 말뭉치를 얻을 수 있다.


토큰화

텍스트를 토큰으로 나누는 과정을 의미한다.

토큰화는 문장 토큰화, 단어 토큰화 두 가지로 나눌 수 있다.

문장 토큰화

문장을 분리하는 기준은 일반적으로 마침표(.), 느낌표(!), 물음표(?) 등 일상 생활에서 문장을 나눌 수 있는 기호에 따라 분리한다. 그러나 기호가 항상 문장을 나누는 기준이 되지는 않는다.

예를 들면 Mr.Lee(미스터리)에서 마침표는 문장을 구분하는 기호가 아니다.

nltk(자연어 처리를 위한 파이썬 패키지)를 통한 예제로 추가 설명을 한다.

import nltk
nltk.download('punkt')

from nltk.tokenize import sent_tokenize

text_sample = 'I love apples. I love bananas? I love strawberries!'
tokenized = sent_tokenize(text_sample)
print(tokenized)
['I love apples.', 'I love bananas?', 'I love strawberries!']

마침표(.), 물음표(?), 느낌표(!)를 기준으로 문장이 나누어진 모습을 볼 수 있다.

text_sample = 'I love apples. I am Mr.Lee. I love bananas.'
tokenized = sent_tokenize(text_sample)
print(tokenized)
['I love apples.', 'I am Mr.Lee.', 'I love bananas.']

문장 'I am Mr.Lee.' 에서 Mr.Lee 는 마침표가 포함되는 문장이지만 별도로 문장으로 구분하지 않은 결과를 볼 수 있다.

이처럼 기호가 반드시 문장을 구분하는 것은 아니다.

단어 토큰화

단어를 기준으로 토큰화하지만 단어 외에도 단어구, 의미를 갖는 문자열도 토큰화 대상이 될 수 있다.

예를 들어 마침표(.), 콤마(,), 물음표(?) 등의 기호도 단어 토큰화의 대상 중 하나이다.

그러나 문장 토큰화에서와 마찬가지로 해당 기호들이 반드시 토큰화가 되는 것은 아니다.

예를 들면 Mr.Lee(미스터리)는 만약 설명처럼 토큰화 하게 되면 ['Mr', '.', 'Lee'] 가 되겠지만 일반적으로 우리가 원하는 토큰화는 ['Mr.Lee'] 일 것이다.

예제로 추가 설명을 한다.

from nltk.tokenize import word_tokenize

text_sample = 'I love apples. I love bananas? I love strawberries!'
tokenized = word_tokenize(text_sample)
print(tokenized)
['I', 'love', 'apples', '.', 'I', 'love', 'bananas', '?', 'I', 'love', 'strawberries', '!']

마침표(.), 물음표(?), 느낌표(!) 모두 토큰화 대상이 되었다.

text_sample = 'I love apples. I am Mr.Lee. I love bananas.'
tokenized = word_tokenize(text_sample)
print(tokenized)
['I', 'love', 'apples', '.', 'I', 'am', 'Mr.Lee', '.', 'I', 'love', 'bananas', '.']

Mr.Lee 를 각각 토큰화 하지 않고 하나의 단어로 취급하는 결과를 볼 수 있다.

이처럼 기호가 반드시 토큰화 되어야 하는 대상은 아니라는 것을 알 수 있다.

한국어 토큰화

한국어 토큰화는 영어보다 더 어렵다.

영어는 대부분 단어별로 띄어쓰기가 이루어지기 때문에 토큰화가 띄어쓰기로 나눈 것과 거의 비슷하다고 볼 수 있다.

그러나 한국어는 띄어쓰기만으로 토큰을 구분하기는 어렵다.

'나는 바나나를 좋아한다.' 로 예를 들면 영어로는 'I love bananas.' 이다.

먼저 영어부터 단어 토큰화하면 ['I', 'love', 'bananas', '.'] 이다.

만약 영어처럼 한국어를 단순 토큰화 한다면 ['나는', '바나나를', '좋아한다', '.'] 가 될 것이다.

그러나 이것은 우리가 원하는 단어 토큰화가 아니다.

한국어에서 토큰화를 이해하기 위해서는 형태소(morpheme)를 이해해야 한다.

형태소에는 자립 형태소, 의존 형태소가 있다.

자립 형태소

- 접사, 어미, 조사와 상관없이 자립하여 사용할 수 있는 형태소. 그 자체로 단어가 된다. 체언(명사, 대명사, 수사), 수식언(관형사, 부사), 감탄사 등이 있다.

의존 형태소

- 다른 형태소와 결합하여 사용되는 형태소. 접사, 어미, 조사, 어간를 말한다.

이제 '나는 바나나를 좋아한다' 를 아래와 같이 형태소 분석할 수 있다.

  • 자립 형태소: '나', '바나나'

  • 의존 형태소: '는', '를', '좋-', '-아', '-하다'

즉, 한국어에서는 영어처럼 토큰화 결과를 얻기 위해서 형태소 기반의 토큰화를 수행해야 한다.

한국어 토큰화 예제로 설명을 마무리한다.

!pip install konlpy
import konlpy

from konlpy.tag import Okt
okt = Okt()

str = "나는 바나나를 좋아한다."

print(okt.morphs(str)) #형태소 분석
print(okt.nouns(str)) #명사 추출
['나', '는', '바나나', '를', '좋아한다', '.']
['나', '바나나']

여기서 '좋아한다' 를 하나의 단어 토큰으로 보고 있다.'좋아하다' 는 '좋다' 의 어간에 '하다' 가 '-아하다' 의 형태로 결합한 합성어이다.

우선 형태소 분석에 대한 판단은 문법적 견해에 따라 다를 수 있다고 한다.

그러므로 실질적으로 형태소 분석은 '좋아하다' 가 아닐 수도 있지만,

국립 국어원의 '표준국어대사전' 에는 '좋아-하다' 가 표제어로 등록되어 있다. 그러므로 '좋아' + '-하다' 가 결합된 파생어로 보고 있다고 생각된다.


참고자료

  1. 딥러닝을 이용한 자연어 처리 입문 (지은이: 유원준 외1)

  2. 위키피디아


반응형