[CH02] 01.토큰화

SoYeong Gwon·2022년 7월 6일
0

Introduction to NLP

목록 보기
3/3
post-thumbnail

본 게시물은 아래 wikidocs의 실습을 참고하여 작성되었습니다. https://wikidocs.net/book/2155

01. 토큰화(Tokenization)


  • 수집된 자연어에서 용도에 맞게 토큰화(tokenization), 정제(cleansing) , 정규화(normalization)하는 일을 하게 됨.
  • 토큰화는 주어진 corpus에서 token이라고 불리는 단위로 나누는 작업이라고 함.
  • token의 단위가 상황에 따라 다르지만, 보통 의미있는 단위로 token을 정의함.
  • 사용하는 패키지 : NLTK, KoNLPY

01. 단어 토큰화(Word Tokenization)

  • Token의 기준을 word로 하는 경우, word tokenization이라고 함.
    • 단순히 단어 외에도 단어구, 의미를 갖는 문자열로도 간주됨.
  • 아래의 입력으로 예를 들어봄.

입력: Time is an illusion. Lunchtime double so!

이러한 입력으로부터 구두점을 제외시킨 토큰화 작업의 결과는 다음과 같음.

출력: "Time", "is", "an", "illusion", "Lunchtime", "double", "so"

  • 단순 띄어쓰기를 기준으로 잘라냈음.
  • 토큰화 작업은 단순히 구두점이나 특수문자를 전부 제거하는 정제 작업을 수행하는 것만으로 해결되지 않음.

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

  • 토큰화의 기준을 생각해봐야 하는 경우 발생
  • 해당 데이터를 가지고 어떤 용도로 사용할 것인지에 따라 용도에 영향이 없는 기준으로 정하면 됨.
  • 영어권의 경우 (')가 들어있는 단어를 어떻게 토큰으로 분류해야하는지에 대해 공부함.
  • 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
    • Don t
    • Dont
    • Do n't
    • Jone's
    • Jone s
    • Jone
    • Jones
  • NLTK 도구를 사용해서 토큰화
    • word_tokenize
    • `WordPunctTokenizer
from nltk.tokenize import word_tokenize
from nltk.tokenize import WordPunctTokenizer
from tensorflow.keras.preprocessing.text import text_to_word_sequence
print('단어 토큰화 1 :', word_tokenize("Don't be fooled by the dark sounding name, Mr.Jone's Orphanage is as cheery as cheery goes for a pastry shop."))
>> 단어 토큰화 1 : ['Do', "n't", 'be', 'fooled', 'by', 'the', 'dark', 'sounding', 'name', ',', 'Mr.Jone', "'s", 'Orphanage', 'is', 'as', 'cheery', 'as', 'cheery', 'goes', 'for', 'a', 'pastry', 'shop', '.']
print('단어 토큰화 2 :', WordPunctTokenizer().tokenize("Don't be fooled by the dark sounding name, Mr.Jone's Orphanage is as cheery as cheery goes for a pastry shop."))
>> 단어 토큰화 2 : ['Don', "'", 't', 'be', 'fooled', 'by', 'the', 'dark', 'sounding', 'name', ',', 'Mr', '.', 'Jone', "'", 's', 'Orphanage', 'is', 'as', 'cheery', 'as', 'cheery', 'goes', 'for', 'a', 'pastry', 'shop', '.']
print('단어 토큰화 3 :', 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."))
>>단어 토큰화 3 : ["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는 기본적으로 모든 알파벳을 소문자로 바꾸면서 마침표나 컴마, 느낌표 등의 구두점 제거
  • don't나 jone's와 같은 ' 는 보존됨.

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

  • 단순하게 corpus에서 구두점을 제외하고 공백 기준으로 잘라내는 작업이라고 간주할 수 없음.
  • 이러한 일은 보다 섬세한 알고리즘이 필요한데 그 이유는 다음과 같음.

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

  • 마침표와 같은 경우 문장의 경계를 알 수 있음.
  • 단어 자체에 구두점을 갖고 있는 경우(Ph.D, AT&T와 같은 경우) 또는 달러($)나 슬래시(/)로 예를 들었을때, $45.55와 같은 가격을 의미하기도 함.
  • 숫자에서 컴마(,)가 있는 경우, 123,456,789,와 같은 세 자리 단위로 컴마가 있음.

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

  • 영어에서 (')는 압축된 단어를 다시 펼치는 역할
  • 예를 들어 what'rewhat are의 줄임말, we'rewe are의 줄임말

(3) 표준 토큰화 예제

  • 표준으로 쓰이는 토큰화 방법 중 하나인 Penn Treebank Tokenization은 다음과 같음.
  • 규칙 1) 하이픈으로 구성된 단어는 하나로 유지한다.
  • 규칙 2) doesn't와 같이 (')로 접어가 함께하는 단어는 분리해준다.
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('Treebank WordTokenizer : ', tokenizer.tokenize(text))
>> Treebank WordTokenizer :  ['Starting', 'a', 'home-based', 'restaurant', 'may', 'be', 'an', 'ideal.', 'it', 'does', "n't", 'have', 'a', 'food', 'chain', 'or', 'restaurant', 'of', 'their', 'own']

04. 문장 토큰화(Sentence Tokenization)

  • 토큰의 단위가 sentence인 경우 corpus 내에서 문장 단위로 구분하는 작업으로 sentence segmentation(문장 분류) 라고도 불림.
  • 정제되지 않은 상태라면, corpus는 문장 단위로 구분되어 있지 않아서 사용하고자하는 용도에 맞게 토큰화가 필요할 수 있음.
  • ! 나 ? 는 문장의 구분이 명확한 boundary(구분자)의 역할을 하지만 마침표는 문장의 끝이 아니더라도 등장할 수 있음.
    • Ex 1) IP 192.168.56.31 서버에 들어가서 로그 파일 저장해서 aaa@gmail.com로 결과 좀 보내줘. 그 후 점심 먹으러 가자.
    • Ex 2) Since I'm actively looking for Ph.D students, I get the same question a dozen times every year.
  • 마침표의 등장으로 문장의 끝을 예상하고자 하지만, 마침표가 이미 여러번 등장하여 예상한 결과가 나오지 않음.
  • 사용하는 코퍼스가 어떤 국적인지, 해당 코퍼스 내 특수문자들이 어떻게 사용되는지에 따라 직접 규칙을 정의할 수 있음.
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 clif. He dug a hole in the midst of some reeds. He looked about, to make sure no one was near.'
print('문장 토큰화 1 : ', sent_tokenize(text))
>> 문장 토큰화 1 :  ['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 clif.', 'He dug a hole in the midst of some reeds.', 'He looked about, to make sure no one was near.']
text = 'I am actively looking for PH.D students. and you are a Ph.D student.'
print('문장 토큰화 2 : ', sent_tokenize(text))
>> 문장 토큰화 2 :  ['I am actively looking for PH.D students.', 'and you are a Ph.D student.']
import kss

text ='딥 러닝 자연어 처리가 재밌기는 합니다. 그런데 문제는 영어보다 한국어로 할 때 너무 어렵습니다. 이제 해보면 알걸요?'
print('한국어 문장 토큰화 : ',kss.split_sentences(text))
>> [Korean Sentence Splitter]: Initializing Pynori...
한국어 문장 토큰화 :  ['딥 러닝 자연어 처리가 재밌기는 합니다.', '그런데 문제는 영어보다 한국어로 할 때 너무 어렵습니다.', '이제 해보면 알걸요?']

05. 한국어에서의 토큰화의 어려움

01. 교착어의 특성

  • 영어와 달리 형태소 토큰화를 수행해야 함.
  • 문장 : 에디가 책을 읽었다.
  • 분리: ['에디가', '책을', '읽었다.']
    • 자립 형태소 : 에디, 책
    • 의존 형태소 : -가, -을, 읽-, -었, -다.

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

  • 띄어쓰기가 없어도 글을 쉽게 이해할 수 있기 때문임.
  • 한글 : 내가이렇게써도무슨말인지다알잖아요?
  • 영어 : Tobeornottobethatisthequestion.

06. 품사 태깅(Part-of-speech tagging)

  • 단어는 표기는 같지만 품사에 따라서 의미가 달라짐.
  • 각 단어가 어떤 품사로 쓰였는지 구분하는 작업을 품사 태깅(part-of-speech tagging)이라고 함.

07. NLTK와 KonNLPY를 이용한 토큰화 실습

01. 영어

from nltk.tokenize import word_tokenize
from nltk.tag import pos_tag

text = 'I am actively looking for PH.D students. and you are a Ph.D student.'
tokenized_sentence = word_tokenize(text)

print('단어 토큰화 : ', tokenized_sentence)
print('품사 태깅 : ',pos_tag(tokenized_sentence))
>> 단어 토큰화 :  ['I', 'am', 'actively', 'looking', 'for', 'PH.D', 'students', '.', 'and', 'you', 'are', 'a', 'Ph.D', 'student', '.']
>> 품사 태깅 :  [('I', 'PRP'), ('am', 'VBP'), ('actively', 'RB'), ('looking', 'VBG'), ('for', 'IN'), ('PH.D', 'NNP'), ('students', 'NNS'), ('.', '.'), ('and', 'CC'), ('you', 'PRP'), ('are', 'VBP'), ('a', 'DT'), ('Ph.D', 'NNP'), ('student', 'NN'), ('.', '.')]

2) 한글

from konlpy.tag import Okt
from konlpy.tag import Kkma

okt = Okt()
kkma = Kkma()

print('OKT 형태소 분석 : ', okt.morphs('열심히 코딩한 당신, 연휴에는 여행을 가봐요.'))
print('OKT 품사 태깅 : ', okt.pos('열심히 코딩한 당신, 연휴에는 여행을 가봐요.'))
print('OKT 명사 추출 : ', okt.nouns('열심히 코딩한 당신, 연휴에는 여행을 가봐요.'))

print('꼬꼬마 형태소 분석 : ', kkma.morphs('열심히 코딩한 당신, 연휴에는 여행을 가봐요.'))
print('꼬꼬마 품사 태깅 : ', kkma.pos('열심히 코딩한 당신, 연휴에는 여행을 가봐요.'))
print('꼬꼬마 명사 추출 : ', kkma.nouns('열심히 코딩한 당신, 연휴에는 여행을 가봐요.'))
>> OKT 형태소 분석 :  ['열심히', '코딩', '한', '당신', ',', '연휴', '에는', '여행', '을', '가봐요', '.']
>> OKT 품사 태깅 :  [('열심히', 'Adverb'), ('코딩', 'Noun'), ('한', 'Josa'), ('당신', 'Noun'), (',', 'Punctuation'), ('연휴', 'Noun'), ('에는', 'Josa'), ('여행', 'Noun'), ('을', 'Josa'), ('가봐요', 'Verb'), ('.', 'Punctuation')]
>> OKT 명사 추출 :  ['코딩', '당신', '연휴', '여행']
>> 꼬꼬마 형태소 분석 :  ['열심히', '코딩', '하', 'ㄴ', '당신', ',', '연휴', '에', '는', '여행', '을', '가보', '아요', '.']
>> 꼬꼬마 품사 태깅 :  [('열심히', 'MAG'), ('코딩', 'NNG'), ('하', 'XSV'), ('ㄴ', 'ETD'), ('당신', 'NP'), (',', 'SP'), ('연휴', 'NNG'), ('에', 'JKM'), ('는', 'JX'), ('여행', 'NNG'), ('을', 'JKO'), ('가보', 'VV'), ('아요', 'EFN'), ('.', 'SF')]
>> 꼬꼬마 명사 추출 :  ['코딩', '당신', '연휴', '여행']

0개의 댓글