Skip to content

Instantly share code, notes, and snippets.

@bakyeono
Last active February 11, 2023 01:07
Show Gist options
  • Save bakyeono/6e9320fbd026e7b0320a to your computer and use it in GitHub Desktop.
Save bakyeono/6e9320fbd026e7b0320a to your computer and use it in GitHub Desktop.
자연어 처리기

자연어 처리기

이 문서의 내용은 자연어 처리기 라이브러리 설치/설정/시험구동 결과다.

라이브러리 사용 목적은 아래와 같다.

  • 독자가 입력한 검색 문자열에서 검색어 추출
  • 기사에서 인덱스용 검색어 추출
  • 한국어를 지원
  • 쉬운 사용(개발)

KoNLPy: Korean NLP in Python

KoNLPy는 자바용으로 만들어진 여러 가지 자연어 처리기를 래핑해서 파이썬에서 편하게 쓸 수 있게 해주는 라이브러리다. 지원하는 자연어 처리기는 한나눔, 꼬꼬마, 코모란, Mecab, 트위터로 총 5가지다. 모두 자바로 만들어졌다. Mecab은 자바 아닌 듯.

설치 (for python 2.7)

$ sudo pip install konlpy # 관리자 권한으로 설치해야 됨.

jpype 오류 문제

자바 모듈을 사용하므로 자바-파이썬 연동 모듈인 jpype가 필요하다. 그런데 jpype가 JAVA_PATH 환경변수를 읽지 못하는 오류가 있어 실행이 안된다. 라즈베리 파이에서 실행했을 때 그랬다. 아마도 데비안 저장소에 등록된 jpype 버전의 문제인 듯하다. (관련 이슈: konlpy/konlpy#24)

해결: 아래 방법으로 jpype 최신버전을 수동 설치

$ git clone --recursive [email protected]:originell/jpype.git
$ cd jpype
$ sudo python setup.py build
$ sudo python setup.py install

TODO: jpype를 apt 대신 pip으로 깔면 어떻게 되는지 확인해볼 것

pip이 패키지 설치하는 위치: /usr/local/lib/python2.7/dist-packages/konlpy

설치 (for python 3.2)

python 3.2에서는 pip이 jpype 패키지를 찾지 못한다. JPype1-py3을 까니 된다.

sudo pip-3.2 install JPype1-py3
sudo pip-3.2 install konlpy

pip이 패키지 설치하는 위치: /usr/local/lib/python3.2/dist-packages/konlpy

모듈 비교 테스트

모듈 로드:

# 한나눔
from konlpy.tag import Hannanum
hannanum = Hannanum()

# 꼬꼬마
from konlpy.tag import Kkma
kkma = Kkma()

# 코모란
from konlpy.tag import Komoran
komoran = Komoran()

# 트위터
from konlpy.tag import Twitter
twitter = Twitter()

Mecab 모듈은 별도의 외부 프로그램을 설치해야 하는 모듈이다. 그래서 일단은 사용해보지 않았다.

테스트 할 문장

string1 = '시리자가 결단을 내릴 때가 다가오는가?'
string2 = '세월호 참사 진실 규명 운동이 더 정치적으로 돼선 안 되는가'

추출 결과

한나눔
hannanum.analyze(string1)
[ [ [('시리자', 'ncn'), ('가', 'jcc')],
    [('시리자', 'ncn'), ('가', 'jcs')],
    [('시리자가', 'ncn')],
    [('시리자', 'nqq'), ('가', 'jcc')],
    [('시리자', 'nqq'), ('가', 'jcs')],
    [('시리자가', 'nqq')]],
  [[('결단', 'ncpa'), ('을', 'jco')]],
  [ [('내', 'nbn'), ('이', 'jp'), ('리', 'ep'), ('ㄹ', 'etm')],
    [('내', 'ncn'), ('이', 'jp'), ('리', 'ep'), ('ㄹ', 'etm')],
    [('내', 'npp'), ('이', 'jp'), ('리', 'ep'), ('ㄹ', 'etm')],
    [('내', 'pvg'), ('리', 'ep'), ('ㄹ', 'etm')],
    [('내', 'px'), ('리', 'ep'), ('ㄹ', 'etm')],
    [('내리', 'pvg'), ('ㄹ', 'etm')],
    [('내리', 'px'), ('ㄹ', 'etm')]],
  [ [('때', 'nbn'), ('가', 'jcc')],
    [('때', 'nbn'), ('가', 'jcs')],
    [('때', 'ncn'), ('가', 'jcc')],
    [('때', 'ncn'), ('가', 'jcs')],
    [('뜨', 'paa'), ('어', 'ecx'), ('가', 'px'), ('아', 'ecs')],
    [('뜨', 'paa'), ('어', 'ecx'), ('가', 'px'), ('아', 'ecx')],
    [('뜨', 'paa'), ('어', 'ecx'), ('가', 'px'), ('아', 'ef')],
    [('뜨', 'pvg'), ('어', 'ecx'), ('가', 'px'), ('아', 'ecs')],
    [('뜨', 'pvg'), ('어', 'ecx'), ('가', 'px'), ('아', 'ecx')],
    [('뜨', 'pvg'), ('어', 'ecx'), ('가', 'px'), ('아', 'ef')],
    [('때', 'pvg'), ('어', 'ecx'), ('가', 'px'), ('아', 'ecs')],
    [('때', 'pvg'), ('어', 'ecx'), ('가', 'px'), ('아', 'ecx')],
    [('때', 'pvg'), ('어', 'ecx'), ('가', 'px'), ('아', 'ef')]],
  [[('다가오', 'pvg'), ('는가', 'ecs')], [('다가오', 'pvg'), ('는가', 'ef')]],
  [[('?', 'sf')]]]

hannanum.analyze(string2)
[[[('세월', 'ncn'), ('호', 'ncn')]],
 [[('참사', 'ncpa')]],
 [[('진실', 'ncps')], [('진', 'ncn'), ('실', 'xsncc')]],
 [[('규명', 'ncpa')]],
 [[('운동', 'ncn'), ('이', 'jcc')],
  [('운동', 'ncn'), ('이', 'jcs')],
  [('운동', 'ncn'), ('이', 'ncn')],
  [('운동', 'ncpa'), ('이', 'jcc')],
  [('운동', 'ncpa'), ('이', 'jcs')],
  [('운동', 'ncpa'), ('이', 'ncn')]],
 [[('더', 'mag')]],
 [[('정치', 'ncpa'), ('적', 'ncn'), ('으로', 'jca')],
  [('정치', 'ncpa'), ('적', 'xsncc'), ('으로', 'jca')]],
 [[('되', 'paa'), ('어선', 'ecs')],
  [('되', 'paa'), ('어', 'ecs'), ('선', 'jxc')],
  [('되', 'paa'), ('어서', 'ep'), ('ㄴ', 'etm')],
  [('되', 'pvg'), ('어선', 'ecs')],
  [('되', 'pvg'), ('어', 'ecs'), ('선', 'jxc')],
  [('되', 'pvg'), ('어서', 'ep'), ('ㄴ', 'etm')],
  [('되', 'px'), ('어선', 'ecs')],
  [('되', 'px'), ('어', 'ecs'), ('선', 'jxc')],
  [('되', 'px'), ('어서', 'ep'), ('ㄴ', 'etm')]],
 [[('안', 'mag')], [('안', 'ncn')], [('알', 'pvg'), ('ㄴ', 'etm')]],
 [[('되', 'paa'), ('는가', 'ecs')],
  [('되', 'paa'), ('는가', 'ef')],
  [('되', 'pvg'), ('는가', 'ecs')],
  [('되', 'pvg'), ('는가', 'ef')],
  [('되', 'px'), ('는가', 'ecs')],
  [('되', 'px'), ('는가', 'ef')]]]
꼬꼬마
kkma.morphs(string1)
['시리', '자', '가', '결단', '을', '내리', 'ㄹ', '때', '가', '다그', '아', '올', '는가', '?']

kkma.morphs(string2)
['세월', '호', '참사', '진실', '규명', '운동', '이', '더', '정치적', '으로', '되', '어', '선', '안', '되', '는가']
코모란
komoran.morphs(string1)
['시리자', '가', '결단', '을', '내리', 'ㄹ', '때', '가', '다가오', '는가', '?']

komoran.morphs(string2)
['세월호 참사', '진실', '규명', '운동', '이', '더', '정치', '적', '으로', '되', '어서', 'ㄴ', '안', '되', '는가']
트위터
twitter.morphs(string1)
['시리자', '가', '결단', '을', '내릴', '때', '가', '다가오는', '가', '?']

twitter.morphs(string2)
['세월호', '참사', '진실', '규명', '운동', '이', '더', '정치', '적', '으로', '돼', '선', '안', '되는', '가']

성능 비교

모듈 최초 구동(사전 로드 등) string1 string2
한나눔 12.42 0.09 0.15
꼬꼬마 128.60 0.85 0.89
코모란 47.27 27.51 32.76
트위터 25.02 0.22 0.20
  • 단위: 초
  • 시험한 기계: Raspberry Pi 2 Model B (ARM 900MHz * 4)

사전 문제

일단 한나눔 모듈의 사전만 확인했다.

가장 유명한 혁명가의 이름들은 기본 사전에 들어 있다.

$ egrep '(마르크스|맑스|레닌|트로츠키)'
dic_system.txt:니콜라이레닌     nqpc
dic_system.txt:레닌     nqq
dic_system.txt:레닌광장 ncn
dic_system.txt:레닌그라드       nqq
dic_system.txt:레닌그라드국제경영관리협회       nqq
dic_system.txt:레닌그라드소재   ncn
dic_system.txt:레닌그라드시     nqq
dic_system.txt:레닌그라드주     nqq
dic_system.txt:레닌동상 ncn
dic_system.txt:레닌동지 ncn
dic_system.txt:레닌모   ncn
dic_system.txt:레닌모자 ncn
dic_system.txt:레닌상   ncn
dic_system.txt:레닌이론 ncn
dic_system.txt:레닌이후 ncn
dic_system.txt:레닌정부 ncn
dic_system.txt:레닌제철소       ncn
dic_system.txt:레닌주의 ncn
dic_system.txt:레닌주의자       ncn
dic_system.txt:레닌초상화       ncn
dic_system.txt:레닌파   ncn
dic_system.txt:마르크스 nqq
dic_system.txt:마르크스경제학   ncn
dic_system.txt:마르크스경제학자 ncn
dic_system.txt:마르크스광장     ncn
dic_system.txt:마르크스레닌주의 ncn
dic_system.txt:마르크스시대     ncn
dic_system.txt:마르크스이론     ncn
dic_system.txt:마르크스주의     ncn
dic_system.txt:마르크스주의자   ncn
dic_system.txt:마르크스주의진영 nqq
dic_system.txt:마르크스철학     ncn
dic_system.txt:맑스     nqq
dic_system.txt:맑스주의 ncn
dic_system.txt:맑스주의이론     ncn
dic_system.txt:맑스주의자       ncn
dic_system.txt:비마르크스주의   ncn
dic_system.txt:비마르크스주의자 ncn
dic_system.txt:서구마르크스주의 ncn
dic_system.txt:서구마르크스주의자       ncn
dic_system.txt:신마르크스주의   ncn
dic_system.txt:칼마르크스       nqq
dic_system.txt:칼맑스   nqq
dic_system.txt:칼하인리히마르크스       nqpc
dic_system.txt:트로츠키 nqq
dic_system.txt:트로츠키주의자   ncn
dic_system.txt:포스트맑스주의   ncn

일반적인 용어들도 기본 사전에 있다.

egrep '(공동전선|인민전선|이윤율|변증법|유물론)' *
dic_system.txt:고대변증법       ncn
dic_system.txt:공동전선 ncn
dic_system.txt:관념변증법       ncn
dic_system.txt:변증법   ncn
dic_system.txt:변증법논리       ncn
dic_system.txt:변증법논리학     ncn
dic_system.txt:변증법론자       ncn
dic_system.txt:비변증법 ncn
dic_system.txt:상호변증법       ncn
dic_system.txt:속류유물론       ncn
dic_system.txt:실질이윤율       ncn
dic_system.txt:역사변증법       ncn
dic_system.txt:유물론   ncn
dic_system.txt:유물론자 ncn
dic_system.txt:유물변증법       ncn
dic_system.txt:이윤율   ncn
dic_system.txt:이윤율저하       ncpa
dic_system.txt:인민전선 ncn
dic_system.txt:일반이윤율       ncn
dic_system.txt:자연변증법       ncn
dic_system.txt:주객변증법       ncn
dic_system.txt:평균이윤율       ncn
dic_system.txt:헤겔변증법       ncn
dic_system.txt:현대유물론       ncn

최근의 시사 용어·인명은 사전에 없는 경우가 많다. 사전이 만들어진 시점과 관련있는 듯하다.

$ egrep '(천안함|세월호|시리자|포데모스|모기지|서브프라임)' *
(결과 없음)

$ egrep '(박근혜|이명박|김무성|윤창중|홍준표)' *
dic_system.txt:김무성   nqpc
dic_system.txt:박근혜   ncn
dic_system.txt:윤창중   nqpc
dic_system.txt:이명박   nqq
dic_system.txt:홍준표   nqpc
dic_system.txt:홍준표당선자     ncn

$ egrep '(문재인|정청래|안철수)' *
(결과 없음)

결론: 사용자 사전을 별도로 제공해야 할 듯하다.

평가

TODO

다른 라이브러리

TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment