형태소 분석의 개념과 konlpy로 사용 하기

    자연어처리(NLP)에서 토크나이징(Tokenizing)이란 데이터를 처리하기 위해서 최소한의 의미를 기반으로 토큰(Token)을 뽑는 것을 말한다. 형태소(Morpheme)는 언어에서 의미를 가지는 가장 작은 단위이기 때문에 토크나이징을 한다는 것은 사실 형태소를 기반으로 쪼개는 경우가 가장 많고, 결국 필드에서 형태소 분석는 토크나이징(자연어처리에 한함)과 유사한 의미로 사용된다.

     

    그리고 형태소 분석(Morphological analysis)은 품사 기준으로 데이터를 분석하기 때문에 품사 태깅(part-of-speech tagging, POS tagging)과 거의 동의어(토크나이징 = 품사태깅 = 형태소 분석)로 사용한다. 실제로 필드에서 형태소 분석이란 대부분 단어를 품사 기준으로 분리하고 품사로 태깅해달라는 의미로 사용한다. (실제로 형태소 분석은 품사 태깅 뿐만 아니라 다양한 분석을 수행한다)

     

    형태소 분석 개념과 konlpy 사용하기

     

    지랄 맞은 한국어

    "내 꿈은 자연어 처리를 하는 딥러닝 전문가야!"라는 꿈을 가지고 있는 학생이거나 신입이라면 일단 애도를 표하고 싶다. 왜냐하면 한글이라는 언어가 디지털에 최적화 되어 있다고 하지만 딥러닝에 최악의 궁합을 자랑하기 때문이다. 정확히 말해서 한글이 지랄이라기 보다 사용하는 국민들로 인해서 지랄맞다가 좀 더 적합한 표현일 것이다.

     

    가뜩이나 자연어처리 전문가 자체가 다른 딥러닝 영역인 이미지, 영상, 소리와 같이 상당히 고도화된 딥러닝에 비해서 지랄 맞는데 한글 자체는 지랄 중에 최고 지랄이기 때문에 애도를 표하는 것이다. 

     

    한국어 자연어처리 전문가들을 눈물나게 하는...

     

    영어같은 경우 공백(space) 기준으로 단어를 구분한다. 예를 들어 자바를 기반으로 하는 어플리케이션 개발자라고 해보자 이 사람이 자기를 "저는 자바어플리케이션개발자입니다." 라고 글로 소개를 한다 하더라도 이상하지 않다. 심지어 "자바어플리케이션개발자"를 한단어처럼 인식을 하기도 한다.

     

    이렇게 한글은 복합명사등과 같이 다양한 단어들을 결합, 분리하는 식으로 자유자재로 활용하여 형태소가 공백 기준으로 분리되지 않고, 어떻게 쓰더라도 형태소를 분석해야 하는 미션 임파서블과 같은 난이도를 자랑한다.

     

    대표적인 극악의 난이도

    아버지가방에들어가신다

    아버지(명사)
    가(조사)
    방(명사)
    에(조사)
    들어가(동사)
    신다(어미)

    엑소브레인으로 형태소 분석을 수행했을 때의 결과

     

    영어로 "javaapplicationdeveloper"라고 쓴 사람을 본적이 없을테고 이런 단어를 분석하지도 않는다. 참으로 영어기반 자연어처리 전문가는 날로먹는 셈이다.

     

    이처럼 형태소 분석이 워낙 어렵기 때문에 형태소 분석을 가장 잘 하는 국내 검색엔진 업체들이 이 정보를 쉽게 공개하지 못하고, 일반인들은 성능이 한참 떨어지는 오픈소스로 되어 있는 형태소 분석기를 사용할 수 밖에 없다.

     

     

    형태소 분석 패키지 (Konlpy)

    형태소 분석기는 다양한 언어로 공개되어 있지만 파이썬에서는 Konlpy로 다양한 형태소 분석기를 한번에 사용해 볼 수 있다. konlpy에 사용되는 형태소 분석기의 상당수가 자바 기반이지만 Konlpy는 사용도 쉽고 형태소 분석기마다 장단점이 명확하기 때문에 때에 따라 다른 형태소 분석기를 쉽게 호출 할 수 있는 장점이 있다(문제는 속도가 느리다)

     

    우선 Kkma(꼬꼬마)를 사용할 예정인데 꼬꼬마가 다양한 기능을 제공하지만 속도가 다른 형태소 분석기에 비해 압도적으로 느리기 때문에(어떻게 개발했는지 궁금할 정도) 속도에 민감한 곳에서는 사용이 힘들다. 

     

    pip install konlpy

    (saibog) C:\Project\saibog\python\saibog>pip install konlpy
    ...
    Installing collected packages: PySocks, tweepy, lxml, JPype1, colorama, beautifulsoup4, konlpy
    Successfully installed JPype1-1.2.1 PySocks-1.7.1 beautifulsoup4-4.6.0 colorama-0.4.4 konlpy-0.5.2 lxml-4.6.2 tweepy-3.10.0
    

     

    꼬꼬마(kkma) 형태소 분석기

    설치를 완료 했다면 아래의 소스를 실행해본다.

    from konlpy.tag import Kkma
    
    # 꼬꼬마 형태소 분석기
    kkma = Kkma()
    
    print(kkma.morphs('아버지가방에들어가신다'))

    konlpy install을 성공하더라도 위 코드가 제대로 실행이 안될 수 있는데 아래와 같이 에러가 발생하였다면, 추가로 설치를 해야 되는 것이 있다.

     

    Java 관련 에러

    Traceback (most recent call last):
      File "C:/Project/saibog/python/saibog/nlp.py", line 4, in <module>
        kkma = Kkma()
      File "C:\Anaconda3\envs\saibog\lib\site-packages\konlpy\tag\_kkma.py", line 95, in __init__
        jvm.init_jvm(jvmpath, max_heap_size)
      File "C:\Anaconda3\envs\saibog\lib\site-packages\konlpy\jvm.py", line 64, in init_jvm
        jpype.startJVM(jvmpath, '-Djava.class.path=%s' % classpath,
      File "C:\Anaconda3\envs\saibog\lib\site-packages\jpype\_core.py", line 221, in startJVM
        _jpype.startup(jvmpath, tuple(args),
    SystemError: java.nio.file.InvalidPathException: Illegal char <*> at index 55: C:\Anaconda3\envs\saibog\Lib\site-packages\konlpy\java\*

    kkma 위 내용을 보면 자바 에러가 발생하였는데 kkma 역시 자바 기반 프로그램이기 때문인데 보통 JPype 버전과 파이썬버전이 맞지 않는 경우이다. 

     

    http://kkma.snu.ac.kr/documents/, 꼬꼬마는 자바 기반의 형태소 분석기이다

     

    Jpype 다운로드

    www.lfd.uci.edu/~gohlke/pythonlibs/#jpype

     

    Python Extension Packages for Windows - Christoph Gohlke

    by Christoph Gohlke, Laboratory for Fluorescence Dynamics, University of California, Irvine. Updated on 9 January 2021 at 17:25 UTC. This page provides 32- and 64-bit Windows binaries of many scientific open-source extension packages for the official CPyth

    www.lfd.uci.edu

    JPype 설치 페이지

     

    필자의 가상환경은 현재 파이썬 3.8을 설치하였기 때문에 JPype1-1.2.0-cp38-cp38-win_amd64.whl을 다운로드 하였고, 

    (saibog) C:\Project\saibog>pip install JPype1-1.2.0-cp38-cp38-win_amd64.whl
    Processing c:\project\saibog\jpype1-1.2.0-cp38-cp38-win_amd64.whl
    Installing collected packages: JPype1
      Attempting uninstall: JPype1
        Found existing installation: JPype1 1.2.1
        Uninstalling JPype1-1.2.1:
          Successfully uninstalled JPype1-1.2.1
    Successfully installed JPype1-1.2.0

     이와 같이 다운로드 받은 JPype를 설치하였다. 

     

    형태소 분석 예제

    from konlpy.tag import Kkma
    
    kkma = Kkma()   # 꼬꼬마 형태소 분석기
    
    
    def morph(text):
        sentences = kkma.sentences(text)	# 텍스트를 문장으로 분리
        for sentence in sentences:
            print('=' * 50)
            print(sentence)
            print('morphs : ', kkma.morphs(sentence))	# 형태소 분석
            print('pos : ', kkma.pos(sentence))			# 태깅
            print('nouns : ', kkma.nouns(sentence))		# 명사 추출
    
    
    while True:
        text = input('문장을 입력하세요 : ')
        if text == 'exit':
            break
        else:
            morph(text)
    

     

    실행결과

    문장을 입력하세요 : 안녕하세요. 저는 자비스 입니다. 만나서 반가워요 다음에 또 만나요
    ==================================================
    안녕하세요.
    morphs :  ['안녕', '하', '세요', '.']
    pos :  [('안녕', 'NNG'), ('하', 'XSV'), ('세요', 'EFN'), ('.', 'SF')]
    nouns :  ['안녕']
    ==================================================
    저는 자비스 입니다.
    morphs :  ['저', '는', '자비스', '이', 'ㅂ니다', '.']
    pos :  [('저', 'NP'), ('는', 'JX'), ('자비스', 'NNG'), ('이', 'VCP'), ('ㅂ니다', 'EFN'), ('.', 'SF')]
    nouns :  ['저', '자비스']
    ==================================================
    만나서 반가워요
    morphs :  ['만나', '서', '반갑', '어요']
    pos :  [('만나', 'VV'), ('서', 'ECD'), ('반갑', 'VA'), ('어요', 'EFN')]
    nouns :  []
    ==================================================
    다음에 또 만 나요
    morphs :  ['다음', '에', '또', '만', '나요']
    pos :  [('다음', 'NNG'), ('에', 'JKM'), ('또', 'MAG'), ('만', 'NR'), ('나요', 'EFQ')]
    nouns :  ['다음', '만']
    문장을 입력하세요 : exit
    
    Process finished with exit code 0
    

     

    Kkma를 다시 써보면서 이제는 이 형태소 분석기를 곱게 보내줘야 할 것 같다. 위에 소스를 실행하는데도 몇초가 걸릴 정도면 사망선고 하는게 맞을 듯, 서울대에서 만든 프로젝트인데 왜 이렇게 속도 튜닝이 안됐는지 이해가 안될 정도이다. 압도적으로 좋은 기능이 있으면 써야겠지만 비슷한 성능에 몇십배 더 빠른 분석기가 많다보니 도저히 트레이드 오프가 힘들 지경인 것 같다.

     

     

    코모란(Komoran) 형태소 분석기

    코모란은 자바 기반 형태소 분석기로 이미 많은 사람들이 사용하고 있으며 속도도 괜찮고 형태소 품질도 우수한 것으로 정평이 나 있다. shineware에서 제작하였으며 코모란에 대해서 자세히 알고 싶은 분들은 아래 링크를 확인하면 된다.

     

    www.shineware.co.kr/products/komoran/

     

    KOMORAN @ Shineware

    소개 KOMORAN은 Shineware의 기술로만 연구 및 개발된 한국어 형태소 분석기로서 Java Library 형태(jar)로 제공됩니다. KOMORAN 3.0은 기존 KOMORAN 2.0 대비 속도, 정확도가 개선되었으며 타 형태소 분석기와

    www.shineware.co.kr

     

    형태소 분석 예제

    from konlpy.tag import Komoran
    
    komoran = Komoran()   # 꼬꼬마 형태소 분석기
    
    
    def morph(text):
        sentences = text.split('.')
        for sentence in sentences:
            print('=' * 50)
            print(sentence)
            print('morphs : ', komoran.morphs(sentence))
            print('pos : ', komoran.pos(sentence))
            print('nouns : ', komoran.nouns(sentence))
    
    
    while True:
        text = input('문장을 입력하세요 : ')
        if text == 'exit':
            break
        else:
            morph(text)
    

    코모란은 문장을 분리해주는 기능이 없기 때문에 위 예제에서는 마침표(.) 단위로 split 하여 분리하였다

     

    실행결과

    문장을 입력하세요 : 안녕하세요. 저는 자비스 입니다. 만나서 반가워요 다음에 또 만나요
    ==================================================
    안녕하세요
    morphs :  ['안녕하세요']
    pos :  [('안녕하세요', 'NNP')]
    nouns :  ['안녕하세요']
    ==================================================
     저는 자비스 입니다
    morphs :  ['저', '는', '자비스', '이', 'ㅂ니다']
    pos :  [('저', 'NP'), ('는', 'JX'), ('자비스', 'NNP'), ('이', 'VV'), ('ㅂ니다', 'EC')]
    nouns :  ['자비스']
    ==================================================
     만나서 반가워요 다음에 또 만나요
    morphs :  ['만나', '아서', '반갑', '어요', '다음', '에', '또', '만나', '요']
    pos :  [('만나', 'VV'), ('아서', 'EC'), ('반갑', 'VA'), ('어요', 'EC'), ('다음', 'NNG'), ('에', 'JKB'), ('또', 'MAJ'), ('만나', 'VV'), ('요', 'EC')]
    nouns :  ['다음']
    문장을 입력하세요 : exit
    
    Process finished with exit code 0
    

     

    코모란을 사용하면 일단 답답한 마음이 싹 사라진다. 더럽게 느린 kkma와 다르게 코모란은 속도가 어느정도 나오기에 현업에서도 상당히 많이 사용이 된다. Kkma 같은 경우 챗봇과 같은 실시간 분석은 불가능하고, 배치성 작업에 대상 문서가 작을 경우 사용할 순 있을 것이다.

     

    다만 위 예시에서 안녕하세요를 명사로 추출해버렸는데 이런 간단한 문장을 아직 제대로 분석하지 못하는 것은 상당한 문제가 있다고 판단이 된다. 다만 코모란의 경우 사용자 사전을 쉽게 추가할 수 있어서 오분석이 날 경우 사전을 제어하여 쉽게 형태소 품질을 올릴 수 있다. 

     

    연관포스팅

    형태소 분석기, Okt(Open Korean Text)

    [챗봇] Python으로 Rule-Based(규칙 기반) 챗봇 만들기

    [Java] 자바 아스키코드및 유니코드로 문자 변환

    [Java] 자바로 한글 자모(초성,중성,종성) 분리(추출)하기 (+개념)

    댓글

    Designed by JB FACTORY