본문 바로가기

Java

자바 텍스트마이닝을 위한 형태소분석-꼬꼬마분석기(Kkma) 설치와 사용

자바 형태소 분석기 - 꼬꼬마분석기 설치와 사용

1. 설치

링크(다운로드)에서 꼬꼬마 형태소분석기 jar파일을 다운로드 할 수 있다.

jar 파일을 다운받고 사용할 자바 프로젝트에서 우클릭 한 후, 
Build Path-Configure Build Path에 들어간다. (단축키 alt+enter)


Libraries에 들어가 add External JARs...를 클릭하고 다운받아놓은 .jar 파일을 추가한다.



프로젝트에 Referenced Libraies 아래 org.snu.ids.ha.jar가 추가되면 성공.

2. 사용

사용하기 위해 src아래 main을 포함한 클래스파일을 만들고 
테스트를 위해 main() 아래 메소드 maTest()를 추가한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void maTest()
      {
            String string = "아버지가방에들어가셨다.";
            try {
                  MorphemeAnalyzer ma = new MorphemeAnalyzer();
                  ma.createLogger(null);
                  Timer timer = new Timer();
                  timer.start();
                  List<MExpression> ret = ma.analyze(string);
                  timer.stop();
                  timer.printMsg("Time");
                  ret = ma.postProcess(ret);
                  ret = ma.leaveJustBest(ret);
                  List<Sentence> stl = ma.divideToSentences(ret);
                  forint i = 0; i < stl.size(); i++ ) {
                        Sentence st = stl.get(i);
                        System.out.println("=============================================  " + st.getSentence());
                        forint j = 0; j < st.size(); j++ ) {
                              System.out.println(st.get(j));
                        }
                  }
                  ma.closeLogger();
            } catch (Exception e) {
                  e.printStackTrace();
            }
      }
cs

메인에서 메소드를 호출한다.
1
2
3
4
5
public class KkmaExam {
      public static void main(String[] args)
      {
            maTest();
      }
cs

실행결과:
=============================================  아버지가방에 들어가셨다.
아버지가방에     => [0/아버지/NNG+3/가방/NNG+5/에/JKM]
들어가셨다.      => [6/들어가/VV+9/시/EPH+10/었/EPT+10/다/EFN+11/./SF]

옆의 영어는 품사 태그표로 각 형태소마다 이름을 붙여준 것이다. (포스팅 하단참고)
띄어쓰기가 없지만 보통명사인 아버지, 가방을 잘 구별해내고 
어간과 조사, 높임선어말어미와 과거시제선어말어미까지 완벽하게 구별해냈다.
참고로 R의 KoNLP에서는 위 문장을 넣으면 '아버지가방에들어가셨'를 명사로, '다'를 조사로 구분한다.

String string = "그가방은제것입니다. 손대지마시죠. 라고말하였다"; 를 넣어봤다.

=============================================  그 가방은 제 것입니다.
그                      => [0/그/MDT]
가방은                  => [1/가방/NNG+3/은/JX]
제                      => [4/저/NP+5/의/JKG]
것입니다.         => [5/것/NNB+6/이/VCP+7/ㅂ니다/EFN+9/./SF]
=============================================  손대지 마시죠.
손대지                  => [11/손대지/NNG]
마시죠.                 => [14/마시/VV+16/죠/EFN+17/./SF]
=============================================  라고 말하였다
라고              => [19/라고/JX]
말하였다          => [22/말하/VV+24/였/EPT+25/다/EFN]

띄어쓰기를 알아서 해줌은 물론이고 
'제'를 대명사 '저'와 조사로 나눠준 것. '입니다'를 이- ㅂ니다로 구별하는 것까지
'손대지' 말고는 거의 완벽하게 분석해냈음을 볼 수 있다.

String string = "이것도분석하는게가능한부분인가요오지고지리고돌리고인정?어인정";

=============================================  이것도 분석하는 게 가능한 부분인가요 오지고 지리고 돌리고 인정? 어 인정
이것도                  => [0/이것/NP+2/도/JX]
분석하는          => [3/분석/NNG+5/하/XSV+6/는/ETD]
게                      => [0/것/NNB+1/이/JKS]
가능한                  => [2/가능/NNG+4/하/XSV+5/ㄴ/ETD]
부분인가요       => [0/부분/NNG+2/이/VCP+3/ㄴ가요/ECS]
오지고                  => [0/오지/VV+2/고/ECE]
지리고                  => [0/지리/VV+2/고/ECE]
돌리고                  => [22/돌리/VV+24/고/ECE]
인정?             => [25/인정/NNG+27/?/SF]
어                      => [28/어/VV+29/어/ECS]
인정              => [29/인정/NNG]

ㅇㅈ? 어 ㅇㅈ

3. 추출

이걸 추출해내는 방법은 공식홈페이지에 잘 나와있는데
1
2
3
4
5
6
7
8
9
10
11
// string to extract keywords
String strToExtrtKwrd = "이것도분석하는게가능한부분인가요오지고지리고돌리고인정?어인정";
// init KeywordExtractor
KeywordExtractor ke = new KeywordExtractor();
// extract keywords
KeywordList kl = ke.extractKeyword(strToExtrtKwrd, true);
// print result
forint i = 0; i < kl.size(); i++ ) {
    Keyword kwrd = kl.get(i);
    System.out.println(kwrd.getString() + "\t" + kwrd.getCnt());
}
cs

위 코드를 넣으면 

이것  1
부분  1
가능  1
분석  1
인정  2

이렇게 명사만 추출해준다. 
참고: 꼬꼬마 공식 홈페이지 (http://kkma.snu.ac.kr/)

한글 형태소 품사 (Part Of Speech, POS) 태그표

한글 형태소의 품사를 '체언, 용언, 관형사, 부사, 감탄사, 조사, 어미, 접사, 어근, 부호, 한글 이외'와 같이 나누고 각 세부 품사를 구분한다.
대분류
세종 품사 태그
심광섭 품사 태그
KKMA 단일 태그 V 1.0
태그
설명
Class
설명
묶음1
묶음2
태그
설명
확률태그
저장사전
체언
NNG
일반 명사
NN
명사
N
NN
NNG
보통 명사
NNA
noun.dic
NNP
고유 명사
NNP
고유 명사
NNB
의존 명사
NX
의존 명사
NNB
일반 의존 명사
NNB
simple.dic
UM
단위 명사
NNM
단위 의존 명사
NR
수사
NU
수사
NR
NR
수사
NR
NP
대명사
NP
대명사
NP
NP
대명사
NP
용언
VV
동사
VV
동사
V
VV
VV
동사
VV
verb.dic
VA
형용사
AJ
형용사
VA
VA
형용사
VA
VX
보조 용언
VX
보조 동사
VX
VXV
보조 동사
VX
AX
보조 형용사
VXA
보조 형용사
VCP
긍정 지정사
CP
서술격 조사 '이다'
VC
VCP
긍정 지정사, 서술격 조사 '이다'
VCP
raw.dic
VCN
부정 지정사
VCN
부정 지정사, 형용사 '아니다'
VCN
관형사
MM
관형사
DT
일반 관형사
M
MD
MDT
일반 관형사
MD
simple.dic
DN
수 관형사
MDN
수 관형사
부사
MAG
일반 부사
AD
부사
MA
MAG
일반 부사
MAG
MAJ
접속 부사
MAC
접속 부사
MAC
감탄사
IC
감탄사
EX
감탄사
I
IC
IC
감탄사
IC
조사
JKS
주격 조사
JO
조사
J
JK
JKS
주격 조사
JKS
raw.dic
JKC
보격 조사
JKC
보격 조사
JKC
JKG
관형격 조사
JKG
관형격 조사
JKG
JKO
목적격 조사
JKO
목적격 조사
JKO
JKB
부사격 조사
JKM
부사격 조사
JKM
JKV
호격 조사
JKI
호격 조사
JKI
JKQ
인용격 조사
JKQ
인용격 조사
JKQ
JX
보조사
JX
JX
보조사
JX
JC
접속 조사
JC
JC
접속 조사
JC
선어말 어미
EP
선어말 어미
EP
선어말 어미
E
EP
EPH
존칭 선어말 어미
EP
EPT
시제 선어말 어미
EPP
공손 선어말 어미
어말 어미
EF
종결 어미
EM
어말 어미
EF
EFN
평서형 종결 어미
EF
EFQ
의문형 종결 어미
EFO
명령형 종결 어미
EFA
청유형 종결 어미
EFI
감탄형 종결 어미
EFR
존칭형 종결 어미
EC
연결 어미
EC
ECE
대등 연결 어미
EC
ECD
의존적 연결 어미
ECS
보조적 연결 어미
ETN
명사형 전성 어미
ET
ETN
명사형 전성 어미
ETN
ETM
관형형 전성 어미
ETD
관형형 전성 어미
ETD
접두사
XPN
체언 접두사
PF
접두사
X
XP
XPN
체언 접두사
XPN
simple.dic
XPV
용언 접두사
XPV
접미사
XSN
명사 파생 접미사
SN
명사화 접미사
XS
XSN
명사 파생 접미사
XSN
XSV
동사 파생 접미사
SV
동사화 접미사
XSV
동사 파생 접미사
XSV
XSA
형용사 파생 접미사
SJ
형용사화 접미사
XSA
형용사 파생 접미사
XSA
SA
부사화 접미사
XSM
부사 파생 접미사
XSM
SF
기타 접미사
XSO
기타 접미사
XSO
어근
XR
어근
XR
XR
XR
어근
XR
부호
SF
마침표물음표,느낌표
SY
부호 외래어
S
SF
SF
마침표물음표,느낌표
SF
Symbol class
SP
쉼표,가운뎃점,콜론,빗금
SP
SP
쉼표,가운뎃점,콜론,빗금
SP
SS
따옴표,괄호표,줄표
SS
SS
따옴표,괄호표,줄표
SS
SE
줄임표
SE
SE
줄임표
SE
SO
붙임표(물결,숨김,빠짐)
SO
SO
붙임표(물결,숨김,빠짐)
SO
SW
기타기호 (논리수학기호,화폐기호)
SW
SW
기타기호 (논리수학기호,화폐기호)
SW
분석 불능
NF
명사추정범주
NR
미등록어
U
UN
UN
명사추정범주
NNA
N/A
NV
용언추정범주
UV
UV
용언추정범주
N/A
NA
분석불능범주
UE
UE
분석불능범주
N/A
한글 이외
SL
외국어
O
OL
OL
외국어
NNA
SH
한자
OH
OH
한자
NNA
SN
숫자
ON
ON
숫자
NR

포스팅에 사용한 전체 코드:

KkmaExam.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package Kkma;
import java.util.List;
import org.snu.ids.ha.index.Keyword;
import org.snu.ids.ha.index.KeywordExtractor;
import org.snu.ids.ha.index.KeywordList;
import org.snu.ids.ha.ma.MExpression;
import org.snu.ids.ha.ma.MorphemeAnalyzer;
import org.snu.ids.ha.ma.Sentence;
import org.snu.ids.ha.util.Timer;
public class KkmaExam {
      public static void main(String[] args)
      {
            maTest();
            // string to extract keywords
            String strToExtrtKwrd = "이것도분석하는게가능한부분인가요오지고지리고돌리고인정?어인정";
            // init KeywordExtractor
            KeywordExtractor ke = new KeywordExtractor();
            // extract keywords
            KeywordList kl = ke.extractKeyword(strToExtrtKwrd, true);
            // print result
            forint i = 0; i < kl.size(); i++ ) {
                  Keyword kwrd = kl.get(i);
                  System.out.println(kwrd.getString() + "\t" + kwrd.getCnt());
            }
      }
      public static void maTest()
      {
            String string = "이것도분석하는게가능한부분인가요오지고지리고돌리고인정?어인정";
            try {
                  MorphemeAnalyzer ma = new MorphemeAnalyzer();
                  ma.createLogger(null);
                  Timer timer = new Timer();
                  timer.start();
                  List<MExpression> ret = ma.analyze(string);
                  timer.stop();
                  timer.printMsg("Time");
                  ret = ma.postProcess(ret);
                  ret = ma.leaveJustBest(ret);
                  List<Sentence> stl = ma.divideToSentences(ret);
                  forint i = 0; i < stl.size(); i++ ) {
                        Sentence st = stl.get(i);
                        System.out.println("=============================================  " + st.getSentence());
                        forint j = 0; j < st.size(); j++ ) {
                              System.out.println(st.get(j));
                        }
                        
                  }
                  ma.closeLogger();
            } catch (Exception e) {
                  e.printStackTrace();
            }
      }
}
cs