🤔 토큰화 실습
자연어 처리의 전처리에 이어 Tokenizing(토큰화)를 진행해보도록 하겠습니다.
토큰화에 대해 이론적으로 학습하고 싶은 분들은 아래의 링크를 참고해주시면 감사하겠습니다.
https://2t-hong.tistory.com/29
작성하기에 앞서 [ICT COG Academy] 인공지능 고급(언어)과정을 수강하며 복습을 위해 작성한 글임을 명시합니다.
🔎단순한 띄어쓰기로 토큰화하기
영어의 경우에는 띄어쓰기 단위로 토큰화를 해도 단어들 간 구분이 꽤나 명확하기 때문에 토큰화 작업이 쉽습니다.
한국어는 조사, 접사 등으로 인해 단순히 띄어쓰기 단위로 나누면 같은 단어가 다른 단어로 인식되어서 단어 집합(vocabulary)의 크기가 불필요하게 커지기 때문에 토큰화 작업이 까다롭습니다.
아래의 예제와 같이 띄어쓰기를 통해 토큰화를 했을 때 영어가 한글 보다 이해하기 쉽다는 것을 알 수 있습니다.
text = "A Dog Run back corner near spare bedrooms"
print(text.split())
['A', 'Dog', 'Run', 'back', 'corner', 'near', 'spare', 'bedrooms']
kor_text = "사과의 놀라운 효능이라는 글을 봤어. 그래서 오늘 사과를 먹으려고 했는데 사과가 썩어서 슈퍼에 가서 사과랑 오렌지 사왔어"
print(kor_text.split())
['사과의', '놀라운', '효능이라는', '글을', '봤어.', '그래서', '오늘', '사과를', '먹으려고', '했는데', '사과가', '썩어서', '슈퍼에', '가서', '사과랑', '오렌지', '사왔어']
위의 예제에서는 '사과'란 단어가 총 4번 등장했는데 모두 '의', '를', '가', '랑' 등이 붙어있어 이를 제거해주지 않으면 기계는 전부 다른 단어로 인식하게 됩니다.
이런 문제로 한국어를 토큰화 하려면 "형태소 분석기"라는 도구를 사용하는 것이 효율적입니다.
🔎NLTK
NLTK 라이브러리는 최근 한국어를 지원 언어에 포함하고 있습니다.
NLTK는 대표적인 Gloabl Tokenizer이라고 할 수 있습니다.
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data] Package punkt is already up-to-date!
True
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data] Package punkt is already up-to-date!
True
text = "Learning Python is very exciting and fun. Enjoy Python!"
tokens = nltk.word_tokenize(text)
print(tokens)
['Learning', 'Python', 'is', 'very', 'exciting', 'and', 'fun', '.', 'Enjoy', 'Python', '!']
text = "NLTK는 Natural Language Toolkit의 줄임말입니다. Python 프로그래밍 언어로 작성된 영어의 기호 및 통계 자연 언어 처리를 위한 라이브러리 및 프로그램 모음입니다"
word_tokens = nltk.word_tokenize(text)
print(word_tokens)
print("----------------------------------------------------------------------")
sent_tokens = nltk.sent_tokenize(text)
print(sent_tokens)
['NLTK는', 'Natural', 'Language', 'Toolkit의', '줄임말입니다', '.', 'Python', '프로그래밍', '언어로', '작성된', '영어의', '기호', '및', '통계', '자연', '언어', '처리를', '위한', '라이브러리', '및', '프로그램', '모음입니다']
----------------------------------------------------------------------
['NLTK는 Natural Language Toolkit의 줄임말입니다.', 'Python 프로그래밍 언어로 작성된 영어의 기호 및 통계 자연 언어 처리를 위한 라이브러리 및 프로그램 모음입니다']
nltk.tokenize 라이브러리에는 트위터 데이터를 위한 Tokenizer가 따로 존재합니다.
🔎 spaCy
- Python의 고급 자연어 처리를 위한 라이브러리입니다.
- 최신 연구를 기반으로 구축되었으며 처음부터 실제 제품에 사용되도록 설계됐습니다.
- 사전 훈련된 파이프라인과 함께 제공합니다.
- 60개 이상의 언어에 대한 토큰화 및 훈련을 지원합니다.
- 태깅, 구문 분석, 명명된 엔터티 인식, 텍스트 분류 등을 위한 최첨단 속도 및 신경망 모델, BERT와 같은 사전 훈련된 변환기를 통한 다중 작업 학습, 생산 준비 교육에 사용됩니다.
- 시스템 및 쉬운 모델이 특징입니다.
- MIT 라이선스에 따라 출시된 상용 오픈 소스 소프트웨어입니다.
import spacy
nlp = spacy.load('en_core_web_sm')
text = "Mary, don't slap the green witch"
print([str(token) for token in nlp(text.lower())])
['mary', ',', 'do', "n't", 'slap', 'the', 'green', 'witch']
def tokenize(en_text):
return [tok.text for tok in nlp.tokenizer(en_text)]
print(tokenize(text))
['Mary', ',', 'do', "n't", 'slap', 'the', 'green', 'witch']
spaCy도 마찬가지로 한국어를 지원합니다.
from spacy.lang.ko.examples import sentences
sentences
['애플이 영국의 스타트업을 10억 달러에 인수하는 것을 알아보고 있다.',
'자율주행 자동차의 손해 배상 책임이 제조 업체로 옮겨 가다',
'샌프란시스코 시가 자동 배달 로봇의 보도 주행 금지를 검토 중이라고 합니다.',
'런던은 영국의 수도이자 가장 큰 도시입니다.']
text = sentences[0]
print([token for token in nlp(text)])
[애플이, 영국의, 스타트업을, 10억, 달러에, 인수하는, 것을, 알아보고, 있다, .]
아래 예시는 품사 태깅에 관한 예시입니다.
for token in nlp(text):
print(token.text, token.pos_, token.dep_)
애플이 PROPN compound
영국의 PROPN compound
스타트업을 PROPN compound
10억 PROPN compound
달러에 PROPN compound
인수하는 PROPN nsubj
것을 ADP ROOT
알아보고 PROPN compound
있다 PROPN dobj
. PUNCT punct
🔎KoNLPy
- GPL v3 또는 그 이상 버전의 라이센스를 적용했습니다.
- KoNLPy의 개발 철학
- 사용법이 간단해야 한다.
- 누구나 쉽게 이용할 수 있어야 한다.
- “인터넷 민주주의는 효과적이다.”
- 다수의 형태소 분석기 등의 모듈을 통합하여 제공합니다.
- Hannanum, Kkma, Komoran, Mecab, Okt 등
!pip install konlpy
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Collecting konlpy
Downloading konlpy-0.6.0-py2.py3-none-any.whl (19.4 MB)
|████████████████████████████████| 19.4 MB 1.3 MB/s
Collecting JPype1>=0.7.0
Downloading JPype1-1.4.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (453 kB)
|████████████████████████████████| 453 kB 60.9 MB/s
Requirement already satisfied: numpy>=1.6 in /usr/local/lib/python3.7/dist-packages (from konlpy) (1.21.6)
Requirement already satisfied: lxml>=4.1.0 in /usr/local/lib/python3.7/dist-packages (from konlpy) (4.9.1)
Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from JPype1>=0.7.0->konlpy) (4.1.1)
Installing collected packages: JPype1, konlpy
Successfully installed JPype1-1.4.0 konlpy-0.6.0
🔎Kkma
Kkma의 특징에 대해 알아보도록 하겠습니다.
- 서울대학교 지능형 데이터 시스템(IDS) 연구소에서 개발함
- 자바로 작성된 형태소 분석기 및 자연어 처리 시스템
- 참고: Kkma 품사 태그
- NNG: 일반 명사
- JKS: 주격 조사
- JKM: 부사격 조사
- VV: 동사
- EFN: 평서형 종결 어미
- SF: 마침표, 물음표, 느낌표
from konlpy.tag import Kkma
# 꼬꼬마 형태소 분석기 사용
kkma = Kkma()
text = "아버지가 방에 들어가신다."
# 형태소 추출
morphs = kkma.morphs(text)
print(morphs)
['아버지', '가', '방', '에', '들어가', '시', 'ㄴ다', '.']
# 형태소와 품사 태그 추출
pos = kkma.pos(text)
print(pos)
[('아버지', 'NNG'), ('가', 'JKS'), ('방', 'NNG'), ('에', 'JKM'), ('들어가', 'VV'), ('시', 'EPH'), ('ㄴ다', 'EFN'), ('.', 'SF')]
# 명사만 추출
nouns = kkma.nouns(text)
print(nouns)
['아버지', '방']
# 문장 분리
sentences = "오늘 날씨는 어때요? 내일은 덥다던데."
s = kkma.sentences(sentences)
print(s)
['오늘 날씨는 어 때요?', '내일은 덥다 던데.']
🔎Komoran
- 2013년 부터 Shineware가 개발한 형태소 분석기입니다.
- 자바로 개발되었으며 비교적 새로운 오픈소스 한국어 형태소 분석기입니다.
- 참고: Komoran 품사 태그
- NNG: 일반 명사
- JKS: 주격 조사
- JKM: 부사격 조사
- VV: 동사
- EFN: 종결 어미
- SF: 마침표, 물음표, 느낌표
from konlpy.tag import Komoran
komoran = Komoran()
text = "아버지가 방에 들어가신다."
# 형태소 추출
morphs = komoran.morphs(text)
print(morphs)
['아버지', '가', '방', '에', '들어가', '시', 'ㄴ다', '.']
# 형태소와 품사 태그 추출
pos = komoran.pos(text)
print(pos)
[('아버지', 'NNG'), ('가', 'JKS'), ('방', 'NNG'), ('에', 'JKB'), ('들어가', 'VV'), ('시', 'EP'), ('ㄴ다', 'EF'), ('.', 'SF')]
# 명사만 추출
nouns = komoran.nouns(text)
print(nouns)
['아버지', '방']
🔎Okt
Okt의 특징에 대해 알아보겠습니다.
- 스칼라로 작성된 오픈소스 한국어 형태소 분석기
- 참고: Okt 품사 태그
- Noun: 명사
- Verb: 동사
- Adjective: 형용사
- Josa: 조사
- Punctuation: 구두점
from konlpy.tag import Okt
okt = Okt()
text = "아버지가 방에 들어가신다."
# 형태소 추출
morphs = komoran.morphs(text)
print(morphs)
['아버지', '가', '방', '에', '들어가', '시', 'ㄴ다', '.']
# 형태소와 품사 태그 추출
pos = okt.pos(text)
print(pos)
[('아버지', 'Noun'), ('가', 'Josa'), ('방', 'Noun'), ('에', 'Josa'), ('들어가신다', 'Verb'), ('.', 'Punctuation')]
# 명사만 추출
nouns = okt.nouns(text)
print(nouns)
['아버지', '방']
# 정규화, 어구 추출
text = "오늘 날씨가 좋아요 ㅋㅋ"
print(okt.normalize(text))
print(okt.phrases(text))
오늘 날씨가 좋아요 ㅋㅋ
['오늘', '오늘 날씨', '날씨']
🔎Hannanum
Hannanum의 특징에 대해 알아보겠습니다.
- 자바로 작성된 형태소 분석기 및 POS 태거
- 1999년부터 KAIST의 시맨틱 웹 리서치 센터(SWRC)에서 개발함
from konlpy.tag import Hannanum
hannanum = Hannanum()
# 구문 분석
print(hannanum.analyze(u'롯데마트의 흑마늘 양념 치킨이 논란이 되고 있다.'))
[[[('롯데마트', 'ncn'), ('의', 'jcm')], [('롯데마트의', 'ncn')], [('롯데마트', 'nqq'), ('의', 'jcm')], [('롯데마트의', 'nqq')]], [[('흑마늘', 'ncn')], [('흑마늘', 'nqq')]], [[('양념', 'ncn')]], [[('치킨', 'ncn'), ('이', 'jcc')], [('치킨', 'ncn'), ('이', 'jcs')], [('치킨', 'ncn'), ('이', 'ncn')]], [[('논란', 'ncpa'), ('이', 'jcc')], [('논란', 'ncpa'), ('이', 'jcs')], [('논란', 'ncpa'), ('이', 'ncn')]], [[('되', 'nbu'), ('고', 'jcj')], [('되', 'nbu'), ('이', 'jp'), ('고', 'ecc')], [('되', 'nbu'), ('이', 'jp'), ('고', 'ecs')], [('되', 'nbu'), ('이', 'jp'), ('고', 'ecx')], [('되', 'paa'), ('고', 'ecc')], [('되', 'paa'), ('고', 'ecs')], [('되', 'paa'), ('고', 'ecx')], [('되', 'pvg'), ('고', 'ecc')], [('되', 'pvg'), ('고', 'ecs')], [('되', 'pvg'), ('고', 'ecx')], [('되', 'px'), ('고', 'ecc')], [('되', 'px'), ('고', 'ecs')], [('되', 'px'), ('고', 'ecx')]], [[('있', 'paa'), ('다', 'ef')], [('있', 'px'), ('다', 'ef')]], [[('.', 'sf')], [('.', 'sy')]]]
# 형태소 추출
print(hannanum.morphs(u'롯데마트의 흑마늘 양념 치킨이 논란이 되고 있다.'))
['롯데마트', '의', '흑마늘', '양념', '치킨', '이', '논란', '이', '되', '고', '있', '다', '.']
'타고파'를 명사로 잘못 추출한 것을 알 수 있습니다.
# 명사만 추출
print(hannanum.nouns(u'다람쥐 헌 쳇바퀴에 타고파'))
['다람쥐', '쳇바퀴', '타고파']
# POS 태거: HMM 기법을 이용하여 태그의 확률 계산
print(hannanum.pos(u'웃으면 더 행복합니다!'))
[('웃', 'P'), ('으면', 'E'), ('더', 'M'), ('행복', 'N'), ('하', 'X'), ('ㅂ니다', 'E'), ('!', 'S')]
🔎사용자 사전 구축
komoran = Komoran()
text = "우리 챗봇은 엔엘피를 좋아해"
pos = komoran.pos(text)
print(pos)
[('우리', 'NP'), ('챗봇은', 'NA'), ('엔', 'NNB'), ('엘', 'NNP'), ('피', 'NNG'), ('를', 'JKO'), ('좋아하', 'VV'), ('아', 'EC')]
filepath = ROOT_PATH + "user_dic.txt"
komoran = Komoran(userdic=filepath)
pos = komoran.pos(text)
print(pos)
[('우리', 'NP'), ('챗봇은', 'NA'), ('엔', 'NNB'), ('엘', 'NNP'), ('피', 'NNG'), ('를', 'JKO'), ('좋아하', 'VV'), ('아', 'EC')]
위의 예제에는 아래와 같은 문제점이 존재합니다.
- 공식 가이드대로 작성하여도 동작하지 않습니다.
- 각 패키지별로 사용자 사전을 추가하는 기능이 제공되지만 오류로 인해 동작하지 않거나 설치할 수 없는 경우가 많습니다.
- 주로 Java, C++ 등을 기반으로 개발되었고 파이썬으로 사용할 수 있도록 기능 지원을 추가한 형태여서 파이썬 작업만으로는 제대로 사용하지 못하는 경우가 많습니다.
'AI > 자연어 처리' 카테고리의 다른 글
[AI] 자연어 처리 - 단어의 표현(2) (0) | 2022.08.13 |
---|---|
[AI] 자연어 처리 - 단어의 표현(1) (0) | 2022.08.11 |
[AI] 자연어 처리 - 전처리와 토큰화(3) (0) | 2022.08.06 |
[AI] 자연어 처리 - 전처리와 토큰화(2) (2) | 2022.08.05 |
[AI] 자연어 처리 - 전처리와 토큰화(1) (2) | 2022.08.01 |