[NLP] KoNLPy 이용하여 한국어 토큰화, 형태소 분석하기 및 클래스간품사 태그 비교표 [한국어 자연어처리]

2021. 6. 28. 08:36자연어처리 (Natural Language Process)

반응형

[ 자연어처리 ]

 

해당 자료를 참고하여 작성하였습니다

http://konlpy.org/ko/v0.4.3/morph/

 

KoNLPy패키지에는 Hannanum, Kkma, Komoran, Mecab, Okt(Twitter)등의 클래스들이 있습니다

이번 포스팅은 클래스들간 품사 태그 비교를 하고 각 클래스들간 사용방법을 설명해드리겠습니다


Hannanum Class

해당 클래스는 KAIST SWRC(Semantic Web Research Center)에서 개발하였습니다

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'다람쥐 헌 쳇바퀴에 타고파'))
>>> ['다람쥐', '쳇바퀴', '타고파']

print(hannanum.pos(u'웃으면 더 행복합니다!'))
>>> [('웃', 'P'), ('으면', 'E'), ('더', 'M'), ('행복', 'N'), ('하', 'X'), ('ㅂ니다', 'E'), ('!', 'S')]

analyze( text )

  이 분석기는 각 토론에 대해 다양한 형태로 반환하다.

  해당 분석기는 사전검색(차트), 분류되지않은 용어 두 부분으로 분할 구성되어있다.

 

morphs( text )

  텍스트에서 형태소를 반환한다

 

nouns( text )

  텍스트에서 명사를 반환한다

 

pos( text )

  텍스트에서 품사 정보를 부착하여 반환한다


Kkma Class

해당 클래스는 서울대학교 IDS(intelligent Data Systems) 연구실에서 개발하였습니다

from konlpy.tag import Kkma

kkma = Kkma()

print(kkma.morphs(u'공부를 하면할수록 모르는게 많다는 것을 알게 됩니다.'))
>>> ['공부', '를', '하', '면', '하', 'ㄹ수록', '모르', '는', '것', '이', '많', '다는', '것', '을', '알', '게', '되', 'ㅂ니다', '.']

print(kkma.nouns(u'대학에서 DB, 통계학, 이산수학 등을 배웠지만...'))
>>> ['대학', '통계학', '이산', '이산수학', '수학', '등']

print(kkma.pos(u'다 까먹어버렸네요?ㅋㅋ'))
>>> [('다', 'MAG'), ('까먹', 'VV'), ('어', 'ECD'), ('버리', 'VXV'), ('었', 'EPT'), ('네요', 'EFN'), ('?', 'SF'), ('ㅋㅋ', 'EMO')]

print(kkma.sentences(u'그래도 계속 공부합니다. 재밌으니까!'))
>>> ['그래도 계속 공부합니다.', '재밌으니까!']

morphs( text )

  텍스트에서 형태소를 반환한다

 

nouns( text )

  텍스트에서 명사를 반환한다

 

pos( text )

  텍스트에서 품사 정보를 부착하여 반환한다

 

sentences( text )

  텍스트에서 문장별로 변환한다


Komoran Class

해당 클래스는 Shineware에서 개발하였다

from konlpy.tag import Komoran

komoran = Komoran()

print(komoran.morphs(u'우왕 코모란도 오픈소스가 되었어요'))
>>> ['우왕', '코', '모란', '도', '오픈소스', '가', '되', '었', '어요']

print(komoran.nouns(u'오픈소스에 관심 많은 멋진 개발자님들!'))
>>> ['오픈소스', '관심', '개발자']

print(komoran.pos(u'원칙이나 기체 설계와 엔진·레이더·항법장비 등'))
>>> [('원칙', 'NNG'), ('이나', 'JC'), ('기체', 'NNG'), ('설계', 'NNG'), ('와', 'JC'), ('엔진', 'NNG'), ('·', 'SP'), ('레이더', 'NNG'), ('·', 'SP'), ('항법', 'NNP'), ('장비', 'NNG'), ('등', 'NNB')]

morphs(text )

  텍스트에서 형태소를 반환한다

 

nouns(text )

  텍스트에서 명사를 반환한다

 

pos(text )

  텍스트에서 품사 정보를 부착하여 반환한다


Mecab Class

해당 분석기는 일본어용 형태소 분석기를 한국어를 사용할 수 있도록 수정한 것 입니다.. (Windowp에서 설치 복잡)

해당 방법으로 Mecab Class를 이용하실 수 있습니다.

https://github.com/koshort/pyeunjeon

 

※ Mecab 클래스는 Window7에서 지원하지않습니다

# MeCab installation needed
from konlpy.tag import Mecab
# from eunjeon import Mecab

mecab = Mecab()

print(mecab.morphs(u'영등포구청역에 있는 맛집 좀 알려주세요.'))
>>> ['영등포구', '청역', '에', '있', '는', '맛집', '좀', '알려', '주', '세요', '.']

print(mecab.nouns(u'우리나라에는 무릎 치료를 잘하는 정형외과가 없는가!'))
>>> ['우리', '나라', '무릎', '치료', '정형외과']

print(mecab.pos(u'자연주의 쇼핑몰은 어떤 곳인가?'))
>>> [('자연', 'NNG'), ('주', 'NNG'), ('의', 'JKG'), ('쇼핑몰', 'NNG'), ('은', 'JX'), ('어떤', 'MM'), ('곳', 'NNG'), ('인가', 'VCP+EF'), ('?', 'SF')]

morphs(text )

  텍스트에서 형태소를 반환한다

 

nouns(text )

  텍스트에서 명사를 반환한다

 

pos(text )

  텍스트에서 품사 정보를 부착하여 반환한다


Okt (Twitter) Class

해당 분석기는 오픈 소스 한국어 분석기이고, 과거 트위터 형태소 분석기였습니다.

# from konlpy.tag import Twitter
from konlpy.tag import Okt

# twitter = Twitter()
okt = Okt()

# print(twitter.morphs(u'단독입찰보다 복수입찰의 경우'))
print(okt.morphs(u'단독입찰보다 복수입창의 경우'))
>>> ['단독', '입찰', '보다', '복수', '입찰', '의', '경우', '가']

# print(twitter.nouns(u'유일하게 항공기 체계 종합개발 경험을 갖고 있는 KAI는'))
print(okt.nouns(u'유일하게 항공기 체계 종합개발 경험을 갖고 있는 KAI는'))
>>> ['유일하', '항공기', '체계', '종합', '개발', '경험']

# print(twitter.phrases(u'날카로운 분석과 신뢰감 있는 진행으로'))
print(okt.phrases(u'날카로운 분석과 신뢰감 있는 진행으로'))
>>> ['분석', '분석과 신뢰감', '신뢰감', '분석과 신뢰감 있는 진행', '신뢰감 있는 진행', '진행', '신뢰']

# print(twitter.pos(u'이것도 되나욬ㅋㅋ'))
print(okt.pos(u'이것도 되나욬ㅋㅋ'))
>>> [('이', 'Determiner'), ('것', 'Noun'), ('도', 'Josa'), ('되나욬', 'Noun'), ('ㅋㅋ', 'KoreanParticle')]

# print(twitter.pos(u'이것도 되나욬ㅋㅋ', norm=True))
print(okt.pos(u'이것도 되나욬ㅋㅋ', norm=True))
>>> [('이', 'Determiner'), ('것', 'Noun'), ('도', 'Josa'), ('되', 'Verb'), ('나요', 'Eomi'), ('ㅋㅋ', 'KoreanParticle')]

# print(twitter.pos(u'이것도 되나욬ㅋㅋ', norm=True, stem=True))
print(okt.pos(u'이것도 되나욬ㅋㅋ', norm=True, stem=True))
>>> [('이', 'Determiner'), ('것', 'Noun'), ('도', 'Josa'), ('되다', 'Verb'), ('ㅋㅋ', 'KoreanParticle')]

morphs(text )

  텍스트에서 형태소를 반환한다

 

nouns(text )

  텍스트에서 명사를 반환한다

 

phrases(text )

  텍스트에서 어절을 뽑아낸다

 

pos(text )

  텍스트에서 품사 정보를 부착하여 반환한다


품사 태깅 클래스 간 비교

 

Time Analysis

  KoNLPy 문서에 따른 클래스간의 성능을 표시하였습니다

  http://konlpy.org/ko/v0.4.3/morph/

 

1. 로딩 시간 : 사전 로딩을 포함하여 클래스를 로딩하는 시간

  • Kkma : 5.6988 secs
  • Komoran : 5.4866 secs
  • Hannanum : 0.6591 secs
  • Okt(Twitter) : 1.4870 secs
  • Mecab : 0.0007 secs

2. 실행 시간 : 10만 문자의 문서를 대상으로 각 클래스의 pos메소드를 실행하는데 소요되는 시간

  • Kkma : 35.7163 secs
  • Komoran : 25.6008 secs
  • Hannanum : 8.8251 secs
  • Okt(Twitter) : 2.4714 secs
  • Mecab : 0.2838 secs

문자의 개수를 늘려감에 따라 모든 클래스의 실행시간은 증가합니다

http://konlpy.org/ko/v0.4.3/morph/#comparison-between-pos-tagging-classes


성능 분석

성능 검증은 몇 개의 샘플 문장을 비교하는것으로 대체합니다

 

1. "아버지가방에들어가신다"

이 예시를 통해 띄어쓰기 알고리즘의 성능을 확인해볼 수 있습니다. 이상적인 경우, 이 예시에 대해서는 아버지 + 가방에 + 들어가신다 보다는 아버지가 + 방에 + 들어가신다 로 해석하는 것이 바람직합니다.

kkma : [('아버지', 'NNG'), ('가방', 'NNG'), ('에', 'JKM'), ('들어가', 'VV'), ('시', 'EPH'), ('ㄴ다', 'EFN')]

hannanum : [('아버지가방에들어가', 'N'), ('이', 'J'), ('시ㄴ다', 'E')]

komoran : [('아버지', 'NNG'), ('가방', 'NNP'), ('에', 'JKB'), ('들어가', 'VV'), ('시', 'EP'), ('ㄴ다', 'EC')]

Okt : [('아버지', 'Noun'), ('가방', 'Noun'), ('에', 'Josa'), ('들어가신다', 'Verb')]

Mecab : [('아버지', 'NNG'), ('가방', 'NNG'), ('에', 'JKB'), ('들어가', 'VV'), ('신다', 'EP+EC')]

2. "나는 밥을 먹는다" vs "하늘을 나는 자동차"

두 문장에서 “나는“에 집중해서 본다면, 각 분석기가 태깅할 때 단어의 의미와 주변부를 잘 살피는지 확인해볼 수 있습니다. 첫번째 문장에서 “나는“은 나/N + 는/J ,두번째 문장에서는 나(-ㄹ다)/V + 는/E 이 되는것이 바람직합니다.

 

“나는 밥을 먹는다“

kkma : [('나', 'NP'), ('는', 'JX'), ('밥', 'NNG'), ('을', 'JKO'), ('먹', 'VV'), ('는', 'EPT'), ('다', 'EFN')]

hannanum : [('나', 'N'), ('는', 'J'), ('밥', 'N'), ('을', 'J'), ('먹', 'P'), ('는다', 'E')]

komoran : [('나', 'NP'), ('는', 'JX'), ('밥', 'NNG'), ('을', 'JKO'), ('먹', 'VV'), ('는다', 'EC')]

Okt : [('나', 'Noun'), ('는', 'Josa'), ('밥', 'Noun'), ('을', 'Josa'), ('먹는다', 'Verb')]

Mecab : [('나', 'NP'), ('는', 'JX'), ('밥', 'NNG'), ('을', 'JKO'), ('먹', 'VV'), ('는다', 'EC')]

 

"하늘을 나는 자동차"

kkma : [('하늘', 'NNG'), ('을', 'JKO'), ('날', 'VV'), ('는', 'ETD'), ('자동차', 'NNG')]

hannanum : [('하늘', 'N'), ('을', 'J'), ('나', 'N'), ('는', 'J'), ('자동차', 'N')]

komoran : [('하늘', 'NNG'), ('을', 'JKO'), ('나', 'NP'), ('는', 'JX'), ('자동차', 'NNG')]

Okt : [('하늘', 'Noun'), ('을', 'Josa'), ('나', 'Noun'), ('는', 'Josa'), ('자동차', 'Noun')]

Mecab : [('하늘', 'NNG'), ('을', 'JKO'), ('나', 'NP'), ('는', 'JX'), ('자동차', 'NNG')]

3. "아이폰 기다리다 지쳐 애플공홈에서 언락폰질러버렸다 6+ 128기가 실버ㅋ"

각 분석기가 사전에 포함되지 않은 단어를 어떻게 해결하는지 확인해보겠습니다

kkma : [('아이', 'NNG'), ('폰', 'NNG'), ('기다리', 'VV'), ('다', 'ECS'), ('지치', 'VV'), ('어', 'ECS'), ('애플', 'NNP'), ('공', 'NNG'), ('홈', 'NNG'), ('에서', 'JKM'), ('언락', 'NNG'), ('폰', 'NNG'), ('질르', 'VV'), ('어', 'ECS'), ('버리', 'VXV'), ('었', 'EPT'), ('다', 'ECS'), ('6', 'NR'), ('+', 'SW'), ('128', 'NR'), ('기가', 'NNG'), ('실버', 'NNG'), ('ㅋ', 'UN')]

hannanum : [('아이폰', 'N'), ('기다리', 'P'), ('다', 'E'), ('지치', 'P'), ('어', 'E'), ('애플공홈', 'N'), ('에서', 'J'), ('언락폰질러버렸다', 'N'), ('6+', 'N'), ('128기', 'N'), ('가', 'J'), ('실벜', 'N')]

komoran : [('아이폰', 'NNP'), ('기다리', 'VV'), ('다', 'EC'), ('지치', 'VV'), ('어', 'EC'), ('애플', 'NNP'), ('공', 'NNP'), ('홈', 'NNG'), ('에서', 'JKB'), ('언', 'NNG'), ('락', 'NNG'), ('폰', 'NNG'), ('지르', 'VV'), ('어', 'EC'), ('버리', 'VX'), ('었', 'EP'), ('다', 'EC'), ('6', 'SN'), ('+', 'SW'), ('128', 'SN'), ('기가', 'NNP'), ('실버ㅋ', 'NA')]

Okt : [('아이폰', 'Noun'), ('기다리다', 'Verb'), ('지쳐', 'Verb'), ('애플', 'Noun'), ('공홈', 'Noun'), ('에서', 'Josa'), ('언', 'Modifier'), ('락폰', 'Noun'), ('질러', 'Verb'), ('버렸다', 'Verb'), ('6', 'Number'), ('+', 'Punctuation'), ('128', 'Number'), ('기', 'Noun'), ('가', 'Josa'), ('실버', 'Noun'), ('ㅋ', 'KoreanParticle')]

Mecab : [('아이폰', 'NNP'), ('기다리', 'VV'), ('다', 'EC'), ('지쳐', 'VV+EC'), ('애플', 'NNP'), ('공홈', 'NNG'), ('에서', 'JKB'), ('언락', 'NNG'), ('폰', 'NNG'), ('질러', 'VV+EC'), ('버렸', 'VX+EP'), ('다', 'EC'), ('6', 'SN'), ('+', 'SY'), ('128', 'SN'), ('기', 'NNG'), ('가', 'JKS'), ('실버', 'NNP'), ('ㅋ', 'IC')]

 

반응형