자연어 처리에서 크롤링 등으로 얻어낸 corpus data가 필요에 맞게 전처리되지 않은 상태라면, 용도에 맞게 토큰화(tokenization) & 정제(cleaning) & 정규화(normalization)하는 일을 하게 된다. 

이중 토큰화에 대해 알아보자.

 

토큰화(tokenization): 주어진 코퍼스(corpus)에서 토큰(token)이라 불리는 단위로 나뉘는 작업(보통 의미있는 단위로 토큰을 정의한다)

 

1. 단어 토큰화(Word Tokenization)

토큰의 기준을 단어(word)로 하는 경우, 단어 토큰화(word tokenization)라고 한다. 

*단어(word)는 단어 단위 외에도 단어구, 의미를 갖는 문자열로도 간주되기도 한다.

 

input) Time is an illusion. Lunchtime double so!

 

위 입력으로부터 토큰화 작업을 시키면 다음과 같다.

 

output) 'Time', 'is', 'an', 'illusion', 'Lunchtime', 'double', 'so'

 

위 출력을 나타내기 위해, 구두점을 지운 뒤에 띄어쓰기(whitespace)를 기준으로 잘라냈다.(가장 기초)

보통 토큰화 작업은 단순히 구두점이나 특수문자를 전부 제거하는 정제(cleaning) 작업을 수행하는 것만으로 해결되지 않는다. 구두점이나 특수문자를 전부 제거하면 토큰의 의미를 잃어버리는 경우가 발생하기도 한다. 심지어 띄어쓰기 단위로 자르면 사실상 단어 토큰이 구분되는 영어와 달리, 한국어는 띄어쓰기만으로는 단어 토큰을  구분하기 어렵다.

 

2. 토큰화 중 생기는 선택의 순간

토큰화를 하다보면, 예상하지 못한 경우가 있어 토큰화의 기준을 생각해봐야 하는 경우가 발생한다. 물론, 이러한 선택은 해당 데이터를 가지고 어떤 용도로 사용할 것인가에 따라 그 용도에 영향이 없는 기준으로 정하면 된다.

 

ex) Don't be fooled by the dark sounding name, Mr. Jone's Orphanage is as cheery as cheery goes for a pastry shop.

 

" ' " 가 들어간 상황에서 Dont't 와 Jone's는 어떻게 토큰화할 수 있을까?

 

[Dont't, Dont t, Dont, Do n't, Jone's, Jone s, Jone, Jones]

 

원하는 결과가 나오도록 토큰화 도구를 직접 설계할 수 있겠지만, 기존에 공개된 도구들을 사용하였을 때의 결과가 사용자의 목적과 일치한다면 해당 도구를 사용할 수 있을 것이다. NLTK는 영어 코퍼스를 토큰화하기 위한 도구들을 제공한다.

 

word_tokenize를 사용한 예를 살펴보자.

 

from nltk.tokenize import word_tokenize

print(word_tokenize("Don't be fooled by the dark sounding name, Mr. Jone's Orpanage is as cheery as cheery goes for a pastry shop."))

['Do', "n't", 'be', 'fooled', 'by', 'the', 'dark', 'sounding', 'name', ',', 'Mr.', 'Jone', "'s", 'Orpanage', 'is', 'as', 'cheery', 'as', 'cheery', 'goes', 'for', 'a', 'pastry', 'shop', '.']

word_tokenize는 Dont't 를 Do 와 n't로 불리하였으며, 반면 Jone's는 Jone과 's로 분리한 것을 확인할 수 있다.

 

wordPunctTokenizer를 사용한 예를 살펴보자

 

from nltk.tokenize import WordPunctTokenizer
print(WordPunctTokenizer().tokenize("Don't be fooled by the dark sounding name, Mr. Jone's Orpanage is as cheery as cheery goes for a pastry shop."))

['Don', "'", 't', 'be', 'fooled', 'by', 'the', 'dark', 'sounding', 'name', ',', 'Mr', '.', 'Jone', "'", 's', 'Orpanage', 'is', 'as', 'cheery', 'as', 'cheery', 'goes', 'for', 'a', 'pastry', 'shop', '.']

WordPunctTokenizer는 구두점을 별도로 분류하는 특징을 갖고 있기 때문에, word_tokenize와 달리 Don't를 Don과 '와 t로 분리하였으며, 이와 마찬가지로 Jone's를 Jone과 '와 s로 분리한 것을 확인할 수 있다.

 

케라스 또한 토큰화 도구로서 text_to_word_sequence를 지원한다. 

text_to_word_sequence를 사용한 예를 살펴보자

 

from tensorflow.keras.preprocessing.text import text_to_word_sequence
print(text_to_word_sequence("Don't be fooled by the dark sounding name, Mr. Jone's Orphanage is as cheery as cheery goes for a pastry shop."))

["don't", 'be', 'fooled', 'by', 'the', 'dark', 'sounding', 'name', 'mr', "jone's", 'orphanage', 'is', 'as', 'cheery', 'as', 'cheery', 'goes', 'for', 'a', 'pastry', 'shop']

text_to_word_sequence는 기본적으로 모든 알파벳을 소문자로 바꾸면서 마침표나 컴마, 느낌표 등의 구두점을 제거한다. 하지만 어퍼스트로피는 보존하는 것을 볼 수 있다.

 

 

토큰화에서 고려해야할 사항

토큰화작업은 단순하게 코퍼스에서 구두점을 제외하고 공백 기준으로 잘라내는 작업이라 생각하면 안된다. 

이유는 다음과 같다.

1) 구두점이나 특수 문자를 단순 제외해서는 안된다.

코퍼스에 대한 정제 작업을 진행하다보면, 구두점 조차도 하나의 토큰으로 분류하기도 한다. 

이러한 점에 있어 해결법은 단어의 빈도수 확인 및 직접 확인을 통해 사전을 만들어주는 경우, 혹은 오픈소스로 되어있는 단어집을 사용하는 방법이 있다.

2) 줄임말과 단어 내에 띄어쓰기가 있는 경우.

토큰화 작업에서 종종 영어권 언어의 "'"는 압축된 단어를 다시 펼치는 역할을 하기도 한다.

사용 용도에 따라, 하나의 단어 사이에 띄어쓰기가 있는 경우도 하나의 토큰으로 봐야하는 경우가 있을 수 있다. 

 

3) 표준 토큰화 예제

표준으로 쓰이는 토큰화 방법 중 하나인 Peen Treebank Tokenization의 규칙을 알아보자.

Rule 1) 하이푼으로 구성된 단어는 하나로 유지.

Rule 2) dont't 와 같이 아포스토로피가 함께하는 단어는 분리해준다.

 

예를 살펴보자.

input) "Starting a home-based restaurant may be an ideal. it doesn't have a food chain or restaurant of their own."

 

from nltk.tokenize import TreebankWordTokenizer
tokenizer=TreebankWordTokenizer()
text="Starting a home-based restaurant may be an ideal. it doesn't have a food chain or restaurant of their own"
print(tokenizer.tokenize(text))

['Starting', 'a', 'home-based', 'restaurant', 'may', 'be', 'an', 'ideal.', 'it', 'does', "n't", 'have', 'a', 'food', 'chain', 'or', 'restaurant', 'of', 'their', 'own']

결과는, 각 Rule1)과 Rule2)에 따라 home-based는 하나의 토큰으로 취급하고 있으며, doesn't의 경우 does와 n't로 분리되었음을 볼 수 있다.

 

4. 문장 토큰화(Sentence Tokenization)

대부분 갖고있는 코퍼스가 정제되지 않은 상태라면, 코퍼스는 문장 단위로 구분되어있지 않을 가능성이 높다.

이를 사용하고자 하는 용도에 맞게 하기 위해서는 문장 토큰화가 필요할 수 있다.

 

어떤 기준으로 문장을 나누어야할까? 코퍼스가 어떤 국적의 언어인지, 또는 해당 코퍼스 내에서 특수문자들이 어떻게 사용되고 있는지에 따라서 직접 규칙을 정의해야 한다. 이는 또한 100%의 정확성을 얻는 것은 아니다. 

NLTK에서는 영어 문장의 토큰화를 수행하는 sent_tokenize를 지원한다.

 

코드로 살펴보자.

 

from nltk.tokenize import sent_tokenize
text="His barber kept his word. But keeping such a huge secret to himself was driving him crazy. Finally, the barber went up a mountain and almost to the edge of a cliff. He dug a hole in the midst of some reeds. He looked about, to make sure no one was near."
print(sent_tokenize(text))

['His barber kept his word.', 'But keeping such a huge secret to himself was driving him crazy.', 'Finally, the barber went up a mountain and almost to the edge of a cliff.', 'He dug a hole in the midst of some reeds.', 'He looked about, to make sure no one was near.']

위 코드는 text에 저장된 여러 개의 문장들로부터 문장을 구분하는 코드이다. 

이번에는 마침표가 여러번 등장하는 경우를 살펴보자.

 

from nltk.tokenize import sent_tokenize
text="I am actively looking for Ph.D. students. and you are a Ph.D student."
print(sent_tokenize(text))

['I am actively looking for Ph.D. students.', 'and you are a Ph.D student.']

 

NLTK는 단순히 마침표를 구분자로 하여 문장을 구분하지 않았기 때문에, ph.D.를 문장 내의 단어로 인식하여 성공적으로 인식하는 것을 볼 수 있다.

 

한국어 문장 토큰화 도구 KSS(Korean Sentence Splitter)

import kss

text="대부분 갖고있는 코퍼스가 정제되지 않은 상태라면, 코퍼스는 문장 단위로 구분되어있지 않을 가능성이 높다.이를 사용하고자 하는 용도에 맞게 하기 위해서는 문장 토큰화가 필요할 수 있다."
print(kss.split_sentences(text))

['대부분 갖고있는 코퍼스가 정제되지 않은 상태라면, 코퍼스는 문장 단위로 구분되어있지 않을 가능성이 높다.', '이를 사용하고자 하는 용도에 맞게 하기 위해서는 문장 토큰화가 필요할 수 있다.']

 

5. 토큰화가 어려운 한국어

한국어는 띄어쓰기가 되어있는 단어를 '어절'이라 한다. 어절 토큰화는 NLP에서 지양되고 있다. 어절 토큰화와 단어 토큰화가 같지 않기 때문인데, 그 근본적인 이유는 한국어가 영어와는 다르게 다른 형태를 가지는 언어인 교착어라는 점에서 기인한다.

 

교착어: 언어의 형태적 유형의 하나. 실질적인 의미를 가진 단어 또는 어간에 문법적인 기능을 가진 요소가 차례로 결합함으로써 문장 속에서의 문법적인 역할이나 관계의 차이를 나타내는 언어로, 한국어ㆍ터키어ㆍ일본어ㆍ핀란드어 따위가 여기에 속한다.

 

자연어 처리를 하다보면 같은 단어여도 서로 다른 조사가 붙어 다른 단어로 인식이 되는 경우가 많다. 대부분 한국어 NLP에서 조사는 분리해줄 필요가 있다.

 

한국어 토큰화에서는 형태소(morpheme)란 개념을 반드시 알아야 한다.

 

형태소: 단어를 분석한 단위로, 뜻을 가진 가장 작은 말의 단위

 

또한 한국어는 띄어쓰기가 영어보다 잘 지켜지지 않는다.

대부분의 한국어 경우 띄어쓰기가 틀렸거나, 잘 지켜지지 않은 코퍼스가 많다. 한국어는 영어권 언어와 달리 띄어쓰기가 어렵고 잘 지켜지지 않는 경향이 있다.

하지만, 실제로 잘 이루어지지 않더라도 이해가 가능한것이 또 한국어이다.

 

[한국어]

지금이렇게띄어쓰기를안한다해도이해못하는사람없겠죠?

 

[영어]

Itisdifficulttounderstandenglishbecauseitdidn'tsplitsentence

 

이 차이는 한국어(모아쓰기 방식)와 영어(풀어쓰기 방식)라는 언어적 특성의 차이 때문이다.

 

'Deep Learning > NLP' 카테고리의 다른 글

트랜스포머(Transformer)(2)  (0) 2021.03.04
트랜스포머(Transformer)(1)  (0) 2021.03.04
Transfer Learning(전이 학습)  (0) 2021.03.02

+ Recent posts