오늘은 konlpy(코엔엘파이)의 4개의 라이브러리(Okt, Kkma, Komoran, Hannanum)로
한국어 형태소를 분석해 보도록 하겠습니다.
그 전에 국어에서 사용하는 용어들을 정리해 보도록 하겠습니다.
형태소란?
형태소(形態素)는 '뜻을 가진 가장 작은 말의 단위'로(출처: 국립국어원 표준국어대사전),
더 이상 나누게 되면 그 의미가 없어지는 것들을 말합니다.
예를 들어,
'책가방' 은 '책', '가방' 이 두가지가 형태소라고 말 할 수 있습니다.
가방에서 가/방 으로 나누면 더이상 가방의 의미가 아니게 되니까 최소 단위가 '가방'이 된다고 볼 수 있습니다.
어간이란?
어간(語幹)은 '활용어가 활용할 때에 변하지 않는 부분'을 말합니다.(출처: 국립국어원 표준국어대사전)
예를 들어, 동사 '보다'의 경우 '보았다(과거), 보니, 보고' 등으로 활용될 수 있는데
이들의 어간은 '보-'가 된다고 볼 수 있습니다.
어절이란?
어절(語節)은 '문장을 구성하고 있는 각각의 마디'를 말하며,
문장 성분의 최소 단위로서 띄어쓰기의 단위가 됩니다.(출처: 국립국어원 표준국어대사전)
'나는 자연어 처리 공부를 한다.'
위의 문장을 보면
'나는 / 자연어/ 처리/ 공부를/ 한다.'
이렇게 5개로 나눌 수 있는데 이것이 각각 어절이 된다고 볼 수 있습니다.
품사란?
품사(品詞)는 '단어를 기능, 형태, 의미에 따라 나눈 갈래' 라고 합니다.(출처: 국립국어원 표준국어대사전)
대표적으로 의미에 따라
- 명사: 사물의 이름을 나타내는 품사 ex) 사과, 달, 별
- 대명사: 사람이나 사물의 이름을 대신 나타내는 말 ex) 무엇, 이것, 저기
- 수사: 사물의 수량이나 순서를 나타내는 품사 ex) 하나, 둘, 셋, 일, 이, 삼
- 조사: 체언이나 부사, 어미 따위에 붙어 그 말과 다른 말과의 문법적 관계를 표시하거나 그 말의 뜻을 도와주는 품사 ex) 은, 는, 이, 가
- 동사: 사물의 동작이나 작용을 나타내는 품사 ex) 보다, 먹다, 자다, 일어나다
- 형용사: 사물의 성질이나 상태를 나타내는 품사 ex) 시원하다, 귀엽다, 기쁘다
- 관형사: 체언 앞에 놓여서, 그 체언의 내용을 자세히 꾸며 주는 품사 ex) 새, 옛, 윗, 뒷
- 부사: 용언 또는 다른 말 앞에 놓여 그 뜻을 분명하게 하는 품사 ex) 빨리, 다행히, 매우
- 감탄사: 말하는 이의 본능적인 놀람이나 느낌, 부름, 응답 따위를 나타내는 말의 부류 ex)아이고, 아차, 와
이렇게 9가지로 분류할 수 있습니다. (출처: 국립국어원 표준국어대사전)
형태소 분석 개체 생성
간단히 용어를 알아보았으니, 이제는 형태소 단위로 토크나이징 하는 방법을 알아보도록 합시다.
토크나이징(tokenizing)은 텍스트 정보를 단위별로 나누는 것을 말합니다.
konlpy의 분석기 종류는 총 5가지가 있습니다.
- Kkma
- Okt
- Komoran
- Hannanum
- Mecab
위의 5개인데, Mecab은 윈도우에서 작동이 불가능해
이번 포스팅에는 Mecab을 제외한 4가지를 사용하여 형태소를 분석해 보겠습니다.
####한국어 형태소 분석기####
from konlpy.tag import Kkma, Komoran, Okt, Hannanum #Mecab은 윈도우에서 작동 불가능
okt = Okt()
kkma = Kkma()
komoran = Komoran()
hannanum = Hannanum()
그 다음, 텍스트를 준비해 줍니다. 여기서는 '훈민정음'의 서문의 일부 내용을 준비하였습니다.
text = '나랏말이 중국과 달라 한자와 서로 통하지 아니하므로, \
우매한 백성들이 말하고 싶은 것이 있어도 마침내 제 뜻을 잘 표현하지 못하는 사람이 많다.\
내 이를 딱하게 여기어 새로 스물여덟 자를 만들었으니, \
사람들로 하여금 쉬 익히어 날마다 쓰는 데 편하게 할 뿐이다.'
morphs로 형태소 분석
.morphs 함수는 텍스트를 형태소 단위로 나누어 줍니다.
#### .morphs()함수: 텍스트를 형태소 단위로 나누어준다.####
print("[Kkma morphs 함수]")
print(kkma.morphs(text))
print("[Okt 함수]")
print(okt.morphs(text))
print("[Komoran 함수]")
print(komoran.morphs(text))
print("[Hannanum 함수]")
print(hannanum.morphs(text))
[Kkma morphs 함수]
['나랏말', '이', '중국', '과', '닿', 'ㄹ라', '한자', '와', '서로', '통하', '지', '아니하', '므로', ',', '우매', '하', 'ㄴ', '백성', '들', '이', '말하', '고', '싶', '은', '것', '이', '있', '어도', '마침내', '저', '의', '뜻', '을', '잘', '표현', '하', '지', '못하', '는', '사람', '이', '많', '다', '.', '내', '이르', 'ㄹ', '딱하', '게', '여기', '어', '새로', '스물', '여덟', '자', '를', '만들', '었', '으니', ',', '사람', '들', '로', '하여금', '쉬', '익히', '어', '날', '마다', '쓰', '는', '데', '편하', '게', '하', 'ㄹ', '뿐', '이', '다', '.']
[Okt 함수]
['못', '하는', '사람', '이', '많다', '.', '내', '이를', '딱하게', '여기어', '새로', '스물', '여덟', '자를', '만들었으니', ',', '사람', '들', '로', '하여금', '쉬', '익히어', '날', '마다', '쓰는', '데', '편하게', '할', '뿐', '이 다', '.'] [Komoran 함수] ['나랏말이', '중국', '과', '다르', '아', '한자', '와', '서로', '통하', '지', '아니하', '므로', ',', '우매', '하', 'ㄴ', '백성', '들', '이', '말', '하', '고', '싶', '은', '것', '이', '있', '어도', '마침내', '제', '뜻', '을', '잘', '표현', '하', '지', '못하', '는', '사람', '이', '많', '다', '.', '내', '이', '를', '딱하', '게', '여기', '어', '새로', '스물', '여덟', '자', '를', '만들', '었', '으니', ',', '사람', '들', '로', '하여금', '쉬', '익히', '어', '날', '마다', '쓰', '는', '데', '편하', '게', '하', 'ㄹ', '뿐', '이', '다', '.']
[Hannanum 함수]
['나랏말', '이', '중국', '과', '다르', '아', '하', 'ㄴ', '자', '와', '서로', '통하', '지', '아니하', '므로', ',', '우매', '하', 'ㄴ', '백성들', '이', '말', '하고', '싶', '은', '것', '이', '있', '어도', '마침내', '저', '의', '뜻', '을', '잘', '표현', '하', '지', '못하', '는', '사람', '이', '많', '다', '.', '내', '이', '를', '딱하', '게', '여기', '이', '어', '새로', '스물여덟', '자', '를', '만들', '었으니', ',', '사람들', '로', '하여금', '쉬', '
각각의 라이브러리로 형태소 분석이 완료되었습니다.
조금씩 차이가 있지만 대부분 비슷하게 분석이 되었습니다.
Okt에는 추가로 norm과 stem이라는 옵션이 있습니다.
norm은 문장을 정규화해주고, stem은 각 단어에서 어간을 추출해 줍니다.
오늘은 stem을 사용해 어간을 추출해 보겠습니다.
stem = True로 파라미터를 추가해 주면 적용됩니다.
##### stem: 각 단어에서 어간 추출 #####
print("[Okt 함수: stem사용하여 어간 추출]")
print(okt.morphs(text, stem= True))
[Okt 함수: stem사용하여 어간 추출]
['나랏말', '이', '중국', '과', '달라', '한자', '와', '서로', '통', '하다', '아니다', ',', '우매', '한', '백성', '들', '이', '말', '하고', '싶다', '것', '이', '있다', '마침내', '제', '뜻', '을', '자다', '표현', '하다', '못', 다', '.']
morphs와 비교해 보면 아니하므로 -> 아니하다, 딱하게-> 딱하다 등의 어간으로 바뀐것을 확인할 수 있습니다.
nouns로 명사 추출
.nouns는 품사 중 명사를 추출해 주는 함수입니다.
#### .nouns()함수: 명사를 추출 ####
print("[Kkma nouns 함수]")
print(kkma.nouns(text))
print("[OKt nouns 함수]")
print(okt.nouns(text))
print("[Komoran nouns 함수]")
print(komoran.nouns(text))
print("[Hannanum nouns 함수]")
print(hannanum.nouns(text))
[Kkma nouns 함수]
['나랏말', '중국', '한자', '우매', '백성', '저', '뜻', '표현', '사람', '내', '스물', '스물여덟', '여덟', '자', '로', '날', '데', '뿐'] [OKt nouns 함수]
['나랏말', '중국', '달라', '한자', '서로', '통', '우매', '백성', '말', '것', '마침내', '제', '뜻', '표현', '사람', '내', '스물', '여덟', '사람', '쉬', '날', '데', '뿐']
[Komoran nouns 함수]
['중국', '한자', '우매', '백성', '말', '것', '뜻', '표현', '사람', '자', '사람', '날', '데', '뿐']
[Hannanum nouns 함수]
['나랏말', '중국', '자', '우매', '백성들', '말', '것', '저', '뜻', '표현', '사람', '내', '이', '여기', '스물여덟', '자', '사람들', '데', '뿐']
이렇게 명사들이 추출됨을 확인할 수 있습니다.
phrases로 어절 추출하기
.phrases는 어절을 뽑아주는 함수입니다. Okt 라이브러리에만 있어 okt를 사용하여 어절 추출을 하겠습니다.
print("[Okt phrases 함수]")
print(okt.phrases(text))
[Okt phrases 함수]
['나랏말', '중국', '중국과 달라', '중국과 달라 한자', '중국과 달라 한자와 서로', '중국과 달라 한자와 서로 통', '우매', '백성들', '마침내', '마침내 제', '마침내 제 뜻', '표현', '못하는 사람', '스물여덟', '사람들', '달라', '한 자', '서로', '사람', '스물', '여덟']
pos를 사용하여 형태소 분석 및 태깅하기
마지막 함수인 .pos는 문장의 각 품사를 태깅해 줍니다.
예를 들어 '애벌레가 사과를 먹는다.' 에서
애벌레 -> 명사
가-> 조사
사과 - >명사
를-> 조사
먹는다-> 동사
위와 같이 각각의 형태소에 품사이름을 붙여 줍니다.
#### .pos()함수: 품사 태깅 ####
print("[Kkma pos 함수]")
print(kkma.pos(text)) #join=True는 형태소와 품사를 붙여서 리스트화
print("[Okt pos 함수]")
print(okt.pos(text))
print("[Komoran pos 함수]")
print(komoran.pos(text))
print("[Hannanum pos 함수]")
print(hannanum.pos(text))
[Kkma pos 함수]
[('나랏말', 'UN'), ('이', 'JKS'), ('중국', 'NNG'), ('과', 'JKM'), ('닿', 'VV'), ('ㄹ라', 'ECD'), ('한자', 'NNG'), ('와', 'JKM'), ('서로', 'MAG'), ('통하', 'VV'), ('지', 'ECD'), ('아니하', 'VXV'), ('므로', 'ECD'), (',', 'SP'), ('우매', 'NNG'), ('하', 'XSV'), ('ㄴ', 'ETD'), ('백성', 'NNG'), ('들', 'XSN'), ('이', 'JKS'), ('말하', 'VV'), ('고', 'ECE'), ('싶', 'VXA'), ('은', 'ETD'), ('것', 'NNB'), ('이', 'JKS'), ('있', 'VV'), ('어도', 'ECD'), ('마침 내', 'MAG'), ('저', 'NP'), ('의', 'JKG'), ('뜻', 'NNG'), ('을', 'JKO'), ('잘', 'MAG'), ('표현', 'NNG'), ('하', 'XSV'), ('지', 'ECD'), ('못하', 'VX'), ('는', 'ETD'), ('사람', 'NNG'), ('이', 'JKS'), ('많', 'VA'), ('다', 'EFN'), ('.', 'SF'), ('내', 'NP'), ('이르', 'VV'), ('ㄹ', 'ETD'), ('딱하', 'VA'), ('게', 'ECD'), ('여기', 'VV'), ('어', 'ECD'), ('새로', 'MAG'), ('스물', 'NR'), ('여덟', 'NR'), ('자', 'NNG'), ('를', 'JKO'), ('만들', 'VV'), ('었', 'EPT'), ('으니', 'ECD'), (',', 'SP'), ('사람', 'NNG'), ('들', 'XSN'), ('로', 'NNG'), ('하여금', 'MAG'), ('쉬', 'MAG'), ('익히', 'VV'), ('어', 'ECD'), ('날', 'NNG'), ('마다', 'JX'), ('쓰', 'VV'), ('는', 'ETD'), ('데', 'NNB'), ('편하', 'VA'), ('게', 'ECD'), ('하', 'VV'), ('ㄹ', 'ETD'), ('뿐', 'NNB'), ('이', 'VCP'), ('다', 'EFN'), ('.', 'SF')]
[Okt pos 함수]
[('나랏말', 'Noun'), ('이', 'Josa'), ('중국', 'Noun'), ('과', 'Josa'), ('달라', 'Noun'), ('한자', 'Noun'), ('와', 'Josa'), ('서로', 'Noun'), ('통', 'Noun'), ('하지', 'Verb'), ('아니하므로', 'Adjective'), (',', 'Punctuation'), ('우매', 'Noun'), ('한', 'Josa'), ('백성', 'Noun'), ('들', 'Suffix'), ('이', 'Josa'), ('말', 'Noun'), ('하고', 'Josa'), ('싶은', 'Verb'), ('것', 'Noun'), ('이', 'Josa'), ('있어도', 'Adjective'), ('마침내', 'Noun'), ('제', 'Noun'), ('뜻', 'Noun'), ('을', 'Josa'), ('잘', 'Verb'), ('표현', 'Noun'), ('하지', 'Verb'), ('못', 'VerbPrefix'), ('하는', 'Verb'), ('사람', 'Noun'), ('이', 'Josa'), ('많다', 'Adjective'), ('.', 'Punctuation'), ('내', 'Noun'), ('이를', 'Verb'), ('딱하게', 'Adjective'), ('여기어', 'Verb'), ('새로', 'Adjective'), ('스물', 'Noun'), ('여덟', 'Noun'), ('자를', 'Verb'), ('만들었으니', 'Verb'), (',', 'Punctuation'), ('사람', 'Noun'), ('들', 'Suffix'), ('로', 'Josa'), ('하여금', 'Adverb'), ('쉬', 'Noun'), ('익히어', 'Verb'), ('날', 'Noun'), ('마다', 'Josa'), ('쓰는', 'Verb'), ('데', 'Noun'), ('편하게', 'Adjective'), ('할', 'Verb'), ('뿐', 'Noun'), ('이다', 'Josa'), ('.', 'Punctuation')]
[Komoran pos 함수]
[('나랏말이', 'NA'), ('중국', 'NNP'), ('과', 'JC'), ('다르', 'VA'), ('아', 'EC'), ('한자', 'NNG'), ('와', 'JC'), ('서로', 'MAG'), ('통하', 'VV'), ('지', 'EC'), ('아니하', 'VX'), ('므로', 'EC'), (',', 'SP'), ('우매', 'NNG'), ('하', 'XSV'), ('ㄴ', 'ETM'), ('백성', 'NNG'), ('들', 'XSN'), ('이', 'JKS'), ('말', 'NNG'), ('하', 'XSV'), ('고', 'EC'), ('싶', 'VX'), ('은', 'ETM'), ('것', 'NNB'), ('이', 'JKS'), ('있', 'VV'), ('어도', 'EC'), ('마침내', 'MAG'), ('제', 'XPN'), ('뜻', 'NNG'), ('을', 'JKO'), ('잘', 'MAG'), ('표현', 'NNG'), ('하', 'XSV'), ('지', 'EC'), ('못하', 'VX'), ('는', 'ETM'), ('사람', 'NNG'), ('이', 'JKS'), ('많', 'VA'), ('다', 'EF'), ('.', 'SF'), ('내', 'NP'), ('이', 'NP'), ('를', 'JKO'), ('딱하', 'VA'), ('게', 'EC'), ('여기', 'VV'), ('어', 'EC'), ('새로', 'MAG'), ('스물', 'NR'), ('여덟', 'NR'), ('자', 'NNB'), ('를', 'JKO'), ('만들', 'VV'), ('었', 'EP'), ('으니', 'EC'), (',', 'SP'), ('사람', 'NNG'), ('들', 'XSN'), ('로', 'JKB'), ('하여금', 'MAG'), ('쉬', 'MAG'), ('익히', 'VV'), ('어', 'EC'), ('날', 'NNG'), ('마다', 'JX'), ('쓰', 'VV'), ('는', 'ETM'), ('데', 'NNB'), ('편하', 'VA'), ('게', 'EC'), ('하', 'VV'), ('ㄹ', 'ETM'), ('뿐', 'NNB'), ('이', 'VCP'), ('다', 'EF'), ('.', 'SF')]
[Hannanum pos 함수]
[('나랏말', 'N'), ('이', 'J'), ('중국', 'N'), ('과', 'J'), ('다르', 'P'), ('아', 'E'), ('하', 'P'), ('ㄴ', 'E'), ('자', 'N'), ('와', 'J'), ('서로', 'M'), ('통하', 'P'), ('지', 'E'), ('아니하', 'P'), ('므로', 'E'), (',', 'S'), ('우매', 'N'), ('하', 'X'), ('ㄴ', 'E'), ('백성들', 'N'), ('이', 'J'), ('말', 'N'), ('하고', 'J'), ('싶', 'P'), ('은', 'E'), ('것', 'N'), ('이', 'J'), ('있', 'P'), ('어도', 'E'), ('마침내', 'M'), ('저', 'N'), ('의', 'J'), ('뜻', 'N'), ('을', 'J'), ('잘', 'M'), ('표현', 'N'), ('하', 'X'), ('지', 'E'), ('못하', 'P'), ('는', 'E'), ('사람', 'N'), ('이', 'J'), ('많', 'P'), ('다', 'E'), ('.', 'S'), ('내', 'N'), ('이', 'N'), ('를', 'J'), ('딱하', 'P'), ('게', 'E'), ('여기', 'N'), ('이', 'J'), ('어', 'E'), ('새로', 'M'), ('스물여덟', 'N'), ('자', 'N'), ('를', 'J'), ('만들', 'P'), ('었으니', 'E'), (',', 'S'), ('사람들', 'N'), ('로', 'J'), ('하여금', 'M'), ('쉬', 'M'), ('익히', 'P'), ('어', 'E'), ('날마다', 'M'), ('쓰', 'P'), ('는', 'E'), ('데', 'N'), ('편하', 'P'), ('게', 'E'), ('하', 'P'), ('ㄹ', 'E'), ('뿐', 'N'), ('이', 'J'), ('다', 'E'), ('.', 'S')]
품사 태깅은 분석기별로 차이가 있으니 자세한 내용은 아래의 링크를 참고해 주세요:)
전체 코드
####한국어 형태소 분석기####
from konlpy.tag import Kkma, Komoran, Okt, Hannanum #Mecab은 윈도우에서 작동 불가능
okt = Okt()
kkma = Kkma()
komoran = Komoran()
hannanum = Hannanum()
text = '나랏말이 중국과 달라 한자와 서로 통하지 아니하므로, \
우매한 백성들이 말하고 싶은 것이 있어도 마침내 제 뜻을 잘 표현하지 못하는 사람이 많다.\
내 이를 딱하게 여기어 새로 스물여덟 자를 만들었으니, \
사람들로 하여금 쉬 익히어 날마다 쓰는 데 편하게 할 뿐이다.'
#### .morphs()함수: 텍스트를 형태소 단위로 나누어준다.####
print("[Kkma morphs 함수]")
print(kkma.morphs(text))
print("[Okt 함수]")
print(okt.morphs(text))
print("[Komoran 함수]")
print(komoran.morphs(text))
print("[Hannanum 함수]")
print(hannanum.morphs(text))
##### stem: 각 단어에서 어간 추출 #####
print("[Okt 함수: stem사용하여 어간 추출]")
print(okt.morphs(text, stem= True))
#### .nouns()함수: 명사를 추출 ####
print("[Kkma nouns 함수]")
print(kkma.nouns(text))
print("[OKt nouns 함수]")
print(okt.nouns(text))
print("[Komoran nouns 함수]")
print(komoran.nouns(text))
print("[Hannanum nouns 함수]")
print(hannanum.nouns(text))
#### .phrases()함수: 어절 추출 ####
print("[Okt phrases 함수]")
print(okt.phrases(text))
#### .pos()함수: 품사 태깅 ####
print("[Kkma pos 함수]")
print(kkma.pos(text)) #join=True는 형태소와 품사를 붙여서 리스트화
print("[Okt pos 함수]")
print(okt.pos(text))
print("[Komoran pos 함수]")
print(komoran.pos(text))
print("[Hannanum pos 함수]")
print(hannanum.pos(text))
코드 파일
참고 자료
마무리
오늘 konlpy 분석기에 대해 알아보았는데요, 다음 시간에는 nltk를 자세히알아 보려고 합니다.
포스팅 관련 알고 싶은 내용이나 질문이 있다면 댓글 남겨주세요(^人^)
'NLP' 카테고리의 다른 글
[python] 자연어처리(NLP) - 텍스트 유사도 (0) | 2021.11.26 |
---|---|
[python] 자연어처리 - 영어 (nltk, spaCy) (0) | 2021.11.23 |
[python] 자연어처리(NLP)-텍스트 빈도 분석 (4) | 2021.11.19 |
[python/konlpy] SystemErrorjava.nio.file.InvalidPathException 오류해결 (1) | 2021.11.09 |
[Python/konlpy] (Jupyter notebook) import konlpy 오류해결(tweepy) (2) | 2021.09.30 |