posted by dalnimbest 2017. 1. 8. 13:12


영어문장에서 단어를 찾아내는 솔루션이 필요하여 알아보니 아파치재단에 openNLP라는것이 있다는것을 알게 되었다. 혹시 참고 될 사람이 있을까 싶어서 openNLP사용법을 간단히 적어본다.


홈페이지 : https://opennlp.apache.org/

아파치 설명서 : https://opennlp.apache.org/documentation/1.7.0/manual/opennlp.html

참고한곳 (영어) : http://www.programcreek.com/2012/05/opennlp-tutorial/


관련 라이브러리는 Maven으로 설치하였다. 현재기준으로 1.7이 최신버전이다.

pom.xml에 아래와 같이 적어주면 된다.

<dependency>

<groupId>org.apache.opennlp</groupId>

<artifactId>opennlp-tools</artifactId>

  <version>1.7.0</version>

</dependency>


openNLP는 영어뿐만 아니라 스페인어등 다른 언어도 지원하기 때문에 각 언어별로 단어를 추출하는 로직이 다르므로 각 언어별로 필요한 모델을 다운받아서 사용한다. 모델에는 문장 추출, token(단어, 구둣점등) 추출, 고유명사 추출, POS태깅등이 각각 따로 존재한다.)

openNLP 1.7은 model 1.5를 사용하면 된다. 

다운받는 경로 : http://opennlp.sourceforge.net/models-1.5/



다운 받은 모델을 프로젝트의 리소스에 추가해준다.(아래는 필자의 경로입다.)



String strOri = "Hi. How're you? This is Mike.";

System.out.println("\nSentences : " + strOri);

try {

//Resource 있는 Model 파일을 읽기 위한 설정

ClassLoader loader = Thread.currentThread().getContextClassLoader();

//문장으로 분리하기

InputStream is_sentence = loader.getResourceAsStream("en-sent.bin");

SentenceModel modelSentence = new SentenceModel(is_sentence);

SentenceDetectorME sdetector = new SentenceDetectorME(modelSentence);  

String sentences[] = sdetector.sentDetect(strOri);

//POS(Part of Speech) 찾아내기...

InputStream is_POS = loader.getResourceAsStream("en-pos-maxent.bin");

POSModel modelPOS = new POSModel(is_POS);

POSTaggerME tagger = new POSTaggerME(modelPOS);


//token(단어)으로 분리하기 (How're 하나의 token 본다.) 

InputStream is_token = loader.getResourceAsStream("en-token.bin");

TokenizerModel modelToekn = new TokenizerModel(is_token);

TokenizerME tokenizer = new TokenizerME(modelToekn);

//고유명사들 찾기...

//사람 이름 찾아내기

InputStream is_NameOfPeople = loader.getResourceAsStream("en-ner-person.bin");  

TokenNameFinderModel model_NameOfPeople  = new TokenNameFinderModel(is_NameOfPeople);

NameFinderME peopleNameFinder = new NameFinderME(model_NameOfPeople);

//지명 이름 찾아내기 

InputStream is_NameOfLocation = loader.getResourceAsStream("en-ner-location.bin");  

TokenNameFinderModel model_NameOfLocation = new TokenNameFinderModel(is_NameOfLocation);

NameFinderME locationNameFinder = new NameFinderME(model_NameOfLocation);

//조직 이름 찾아내기 

InputStream is_NameOfOrgan = loader.getResourceAsStream("en-ner-organization.bin");  

TokenNameFinderModel model_NameOfOrgan= new TokenNameFinderModel(is_NameOfOrgan);

NameFinderME organNameFinder = new NameFinderME(model_NameOfOrgan);

//날짜 찾아내기 

InputStream is_NameOfDate = loader.getResourceAsStream("en-ner-date.bin");  

TokenNameFinderModel model_NameOfDate= new TokenNameFinderModel(is_NameOfDate);

NameFinderME dateNameFinder = new NameFinderME(model_NameOfDate);

//화폐 이름 찾아내기 

InputStream is_NameOfMoney= loader.getResourceAsStream("en-ner-money.bin");  

TokenNameFinderModel model_NameOfMoney= new TokenNameFinderModel(is_NameOfMoney);

NameFinderME moneyNameFinder = new NameFinderME(model_NameOfMoney);

//입력문장 전체를 문장으로 나눈다.

System.out.println("count of senctences : " + sentences.length);

for(String sentence : sentences){

System.out.println("sentence : " + sentence);

// 문장에서 token단위(단어, 구둣점등) 나눈다.

String[] tokens = tokenizer.tokenize(sentence);

//tokens으로 분리한 토큰들에 대한 POS 가져온다.

String tag[] = tagger.tag(tokens);

System.out.println("\ncount of tokens : " + tokens.length);

for (int i = 0; i < tokens.length; i++) {

String strWord = tokens[i];

String pos = tag[i];

System.out.println(i + " : " + strWord);//+ "  , POS[" + pos + "]");

}

//whitespaceTokens으로 분리한 토큰들에 대한 POS 가져온다.

String whitespaceTokens[] = WhitespaceTokenizer.INSTANCE.tokenize(sentence);

String tagOfWhitespaceTokens[] = tagger.tag(whitespaceTokens);

System.out.println("\ncount of whitespaceTokens : " + whitespaceTokens.length);

for (int i = 0; i < whitespaceTokens.length; i++) {

String strWord = whitespaceTokens[i];

String pos = tagOfWhitespaceTokens[i];

System.out.println(i + " : " + strWord);//+ "  , POS[" + pos + "]");

}


//simpleTokens으로 분리한 토큰들에 대한 POS 가져온다.

String simpleTokens[] = SimpleTokenizer.INSTANCE.tokenize(sentence);

String tagOfSimpleTokens[] = tagger.tag(simpleTokens);

System.out.println("\ncount of simpleTokens : " + simpleTokens.length);

for (int i = 0; i < simpleTokens.length; i++) {

String strWord = simpleTokens[i];

String pos = tagOfSimpleTokens[i];

System.out.println(i + " : " + strWord);//+ "  , POS[" + pos + "]");

}

Span peopleNameSpans[] = peopleNameFinder.find(simpleTokens);  

for(Span name: peopleNameSpans) {

logger.info("people Name : " + name.toString());

}

Span locationNameSpans[] = locationNameFinder.find(simpleTokens);  

for(Span name: locationNameSpans) {

logger.info("location Name : " + name.toString());

}

Span organNameSpans[] = organNameFinder.find(simpleTokens);  

for(Span name: organNameSpans) {

logger.info("organ Name : " + name.toString());

}

Span dateNameSpans[] = dateNameFinder.find(simpleTokens);  

for(Span name: dateNameSpans) {

logger.info("date Name : " + name.toString());

}

Span moneyNameSpans[] = moneyNameFinder.find(simpleTokens);  

for(Span name: moneyNameSpans) {

logger.info("money Name : " + name.toString());

}

}

is_sentence.close();

is_token.close();

is_NameOfPeople.close();

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}



위를 실행하면 나오는 결과는 아래와 같다..

Sentences : Hi. How're you? This is Mike.

count of senctences : 2

sentence : Hi. How're you?


count of tokens : 5

0 : Hi

1 : .

2 : How're

3 : you

4 : ?


count of whitespaceTokens : 3

0 : Hi.

1 : How're

2 : you?


count of simpleTokens : 7

0 : Hi

1 : .

2 : How

3 : '

4 : re

5 : you

6 : ?

sentence : This is Mike.


count of tokens : 4

0 : This

1 : is

2 : Mike

3 : .


count of whitespaceTokens : 3

0 : This

1 : is

2 : Mike.


count of simpleTokens : 4

0 : This

1 : is

2 : Mike

3 : .