레이블이 Mecab인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Mecab인 게시물을 표시합니다. 모든 게시물 표시

2015년 8월 31일 월요일

Mac에서 MeCab Ko의 Java API 사용하기


Mac에서 Mecab Ko를 수정한 후 디버깅 환경을 구축할 때 생각보다 삽질을 많이 해서 글을 남긴다.

Mac에서 MeCab Ko의 Java API 구축 환경


MacBook Pro (Retina, 15-inch, Late 2013)
Mac OS X 10.10.5
2.3 GHz Intel Core i7
16GB 1600 MHz DDR3

GCC 컴파일러 설치 여부 확인


$gcc -v

configure: error: C compiler cannot create executables
Mac OS에서 위와 같은 메시지가 출력하면 컴파일러가 설치되지 않은 것이다.

App Store > Xcode 설치

mecab-ko 설치

    mecab-0.996-ko-0.9.2.tar.gz 다운로드

2. 압축풀기 및 컴파일
    $ tar xvfz mecab-0.996-ko-0.9.2.tar.gz
    $ cd mecab-0.996-ko-0.9.2
    $ ./configure
    $ make
    $ make check
    $ make install



mecab-ko-dic 설치

    mecab-ko-dic-2.0.1-20150825.tar.gz 다운로드

2. 압축풀기 및 컴파일
    $ tar xvfz mecab-ko-dic-2.0.1-20150825.tar.gz
    $ cd mecab-ko-dic-2.0.1-20150825
    $ ./configure
    $ sudo ./autogen.sh
    $ make
    $ make install

    # autogen.sh의 실행을 안하면 Mac에서는 make에서 AM_INIT_AUTOMAKE(mecab-ko-dic, 2.0.0)라는 컴파일 에러가 발생한다.


mecab-ko-lucene-analyzer 설치

    mecab-java-0.996.tar.gz 다운로드

2. 압축풀기 및 컴파일
    $ tar xvfz mecab-java-0.996.tar.gz
    $ cd mecab-java-0.996
     > ! Mac에서는 Makefile이 제대로 동작하지 않기 때문에 다음과 같이 변경한다.
     > 빨간색으로 표시한 영역이 수정된 설정값이다.
    $ vi Makefile

TARGET=MeCab
JAVAC=javac
JAVA=java
JAR=jar
CXX=c++
INCLUDE=/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers

PACKAGE=org/chasen/mecab

LIBS=`mecab-config --libs`
INC=`mecab-config --cflags` -I$(INCLUDE) -I$(INCLUDE)/MacOS

all:
        $(CXX) -O3 -c -fpic $(TARGET)_wrap.cxx  $(INC)
        $(CXX) -dynamiclib  $(TARGET)_wrap.o -o lib$(TARGET).dylib $(LIBS)
        $(JAVAC) $(PACKAGE)/*.java
        $(JAVAC) test.java
        $(JAR) cfv $(TARGET).jar $(PACKAGE)/*.class

test:
        env DYLD_LIBRARY_PATH=. $(JAVA) test

clean:
        rm -fr *.jar *.o *.dylib *.so *.class $(PACKAGE)/*.class

cleanall:
        rm -fr $(TARGET).java *.cxx


          > 수정이 다 되었으면 저장

      >> make 명령을 실행해서 libMeCab.dylib와 MeCab.jar가 생성되어 있어야 한다.
     
      $ make

      컴파일이 성공적으로 완료되면 디렉토리명을 수정한후 경로를 다음과 같이 변경하자.
      mv mecab-java-0.996 mecab-java    # 디렉토리 이름을 변경
      mv mecab-java /usr/local/bin/           # 디렉토리 위치 변경

      로컬 계정의 profile파일에 동적 라이브러리 경로를 추가하자
      $ cd ~/
      $ vi .bash_profile

      export DYLD_LIBRARY_PATH=/usr/local/bin/mecab-java

      # 저장 후 반영
      $ . .bash_profile


MeCab에서 형태소 분석 프로그램 작성

mecab-java-0.996 압축을 해제한 폴더에서 MeCabTest.java 파일을 만든다.

import org.chasen.mecab.Tagger;
import org.chasen.mecab.Node;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;

public class MeCabTest {
    static {
        try {
            System.loadLibrary ( "MeCab"); // MeCab을로드
        } catch (UnsatisfiedLinkError e) {
            // MeCab을로드 할 때의 처리
            System.err.println ( "Can not load the example native code \ nMake sure your LD_LIBRARY_PATH contains \ n"+ e);
            System.exit (1);
        }
    }

    public static void main (String [] args)
    {
        HashMap map = new HashMap ();

        Tagger tagger = new Tagger (); // 형태소 분석의 준비
        String aString = "자연어처리의 시작이라 할 수 있는 형태소 분석에 대해서 알아본다.";
        System.out.println ( "입력 :"+ aString);

        tagger.parse (aString); // 이것을 쓰고 두지 않으면 다음 잘 작동하지 않았다.

           Node node = tagger.parseToNode (aString); // 노드에 분해
        for (; node! = null; node = node.getNext ()) // 노드를 순차적으로 출력
        {
            String str = node.getFeature (); // 품사 등의 정보를 저장
            String [] strAry = str.split ( ""); // ","로 구분하여 배열에 저장

            String word = node.getSurface (); // 단어를 저장
            String feature = strAry [0]; // 품사를 저장

            System.out.println (word + "\ t"+ feature); // 단어와 품사를 출력

            if (map.containsKey (word)) {
                // 만약 이미 map에 등록되어있는 단어라면 카운트 플러스
                map.put (word, map.get (word) + 1); // 단어 word로 이미 저장되어있는 카운트 수에 1을 더해 등록하기
            } else {
                // 만약 아직 map에 등록되지 않은 단어라면 카운트를 1로 등록
                map.put (word, 1); // 단어 word와 횟수는 1 세트에 저장
            }
        }

        // map에서 저장되는 단어와 개수를 출력하는
        for (Iterator it = map.entrySet (). iterator (); it.hasNext ();) {
            Map.Entry entry = (Map.Entry) it.next ();
            Object key = entry.getKey ();
            Object value = entry.getValue ();
            System.out.println ( "단어 :"+ key + "\ t 출현 횟수 :"+ value);
        }
    }
}


출력결과

javac -cp MeCab.jar MeCabTest.java
java -Djava.library.path=/usr/local/bin/mecab-java -cp .:MeCab.jar MeCabTest


입력 :자연어처리의 시작이라 할 수 있는 형태소 분석에 대해서 알아본다.
B
자연어 N
처리 N
J
시작 N
V
E
V
N
V
E
형태소 N
분석 N
J
대해서 V
알아본다 V
. S
B
단어 : 출현 횟수 :2
단어 :할 출현 횟수 :1
단어 :있 출현 횟수 :1
단어 :처리 출현 횟수 :1
단어 :시작 출현 횟수 :1
단어 :분석 출현 횟수 :1
단어 :. 출현 횟수 :1
단어 :알아본다 출현 횟수 :1
단어 :에 출현 횟수 :1
단어 :자연어 출현 횟수 :1
단어 :대해서 출현 횟수 :1
단어 :이 출현 횟수 :1
단어 :는 출현 횟수 :1
단어 :의 출현 횟수 :1
단어 :수 출현 횟수 :1
단어 :형태소 출현 횟수 :1
단어 :라 출현 횟수 :1


2015년 8월 25일 화요일

Elasticsearch에서 Mecab Ko 사전경로 변경하기

Elasticsearch Settings > Analysis > Analyzer, Tokenizer를 Mecab Ko로 설정한다.

Index analysis는 Analyzer, Tokenizer, TokenFilter로 구성된다.


1. Analysis 설정 구조
index
     analysis
            analyzer
                   standard : 
                          type : standard
                          stopwords : [stop, stop2]
                   myAnalyzer  :
                           type : standard
                           stopwords : [stop1, stop2, stop3]
                           max_token_length : 500
            tokenizer :
                   myTokenizer :
                          type : standard
                          max_token_length : 900
            filter :
                  myTokenFilter :
                         type : stop
                         stopwords : [stop1, stop2, stop3, stop4]

* max_token_length의 기본값은 255이다.

2. Mecab Ko Analysis 설정

setting에서 아래와 같이 사전경로 지정을 위해 tokenizer > mecab_args를 추가한다.

PUT /shop
{
"settings" : {
    "index":{
      "analysis":{
        "analyzer":{
          "korean":{
            "type":"custom",
            "tokenizer":"mecab_ko_standard_tokenizer"
          }
        },
        "tokenizer": {
          "mecab_ko_standard_tokenizer": {
            "type": "mecab_ko_standard_tokenizer",
            "mecab_args": "-d /home/elasticsearch/knowledge/mecab/dic/mecab-ko-dic"
          }
        }
      }
    }
 }
}

[분석 결과보기]
GET /shop/_analyze?analyzer=korean&pretty=true
{
  레노버노트북
}


[참고 URL]

Elasticsearch에서 Mecab Ko 동의어사전 적용하기

Elasticsearch Settings > Analysis > Filter 설정

Index analysis는 Analyzer, Tokenizer, TokenFilter로 구성된다.


TOKEN FILTER 종류
33개 
tokenizer로 부터 token stream을 받아서 token에 대해 lower case, add, delete 등을 처리

Synonym Token Filter
동의어를 적용하는 필터. Elasticsearch에 포함되어 있다.

# 설정 예제
PUT /shop
{
"settings" : {
    "index":{
      "analysis":{
        "filter" : {
            "synonym" : {
                "type" : "synonym",
                "synonyms_path" : "analysis/synonyms.txt"
            }
        },
        "analyzer":{
          "korean":{
            "filter" : [
              "standard",
              "lowercase",
              "stop",
              "synonym"  
            ],
            "type":"custom",
            "tokenizer":"mecab_ko_standard_tokenizer"
          }
        },
        "tokenizer": {
          "mecab_ko_standard_tokenizer": {
            "type": "mecab_ko_standard_tokenizer",
            "mecab_args": "-d /home/elasticsearch/knowledge/mecab/dic/mecab-ko-dic"
          }
        }
      }
    }
 }
}

# edit : $ES_HOME/config/analysis/synonym.txt 
노트북,labtop,notebook

# 확인 명령
$ curl -XGET ‘localhost:9200/shop/_analyze?analyzer=korean&pretty=true' -d ‘노트북'

# 노트북 labtop notebook  

2015년 8월 24일 월요일

Elasticsearch에 한국어 형태소분석기 Mecab ko 적용

최근에 Elasticsearch를 정리하면서 MeCab Ko의 Elasticsearch 연동을 정리하지 않은 것 같아서 작성 해 본다.
(사실 SOLR에 MeCab Ko를 먼저 붙였지만, 최근에 Elasticsearch만 정리하고 있다. ㅡㅡ;)

참고) SOLR와 Elasticsearch에서 MeCab을 사용할 때 특수문자 허용 검색하기
http://nocode2k.blogspot.kr/2015/08/mecab-ko-solr-elasticsearch.html

CentOS 6.x 환경에서 SOLR와  Elasticsearch에서 한국어 형태소분석기인 Mecab Ko를 사용하기 위해서는 먼저 아래와 같이 설치 및 환경설정이 필요하다.
(* 8월 20일 현재 은전한닢 프로젝트에서는 mecab ko 사전을 사용하는 스칼라로 개발된 형태소분석기도 배포중이다.)

1. GCC컴파일러/JDK설치


1.1 C++ 컴파일러 설치
yum install gcc-c++

1.2 Java 다운로드 및 설치

사이트 다운로드 : http://www.oracle.com/technetwork/java/javase/downloads/index.html

리눅스 command 다운로드

32 bit linux use this:
curl -v -j -k -L -H "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u51-b16/jdk-8u51-linux-i586.rpm > jdk-8u51-linux-i586.rpm

For 64 bit:
curl -v -j -k -L -H "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u51-b16/jdk-8u51-linux-x64.rpm > jdk-8u51-linux-x64.rpm

Install the rpm:
rpm -ivh  jdk-8u51-linux-i586.rpm


2. mecab-ko 설치


mecab-ko는 한국어 특성에 맞는 기능이 추가된 MeCab의 fork 프로젝트이다.
mecab-ko 다운로드 페이지에서 mecab-ko의 소스를 다운로드 받고 설치한다.

사이트 다운로드: https://bitbucket.org/eunjeon/mecab-ko/downloads

리눅스 command 다운로드 및 설치

wget https://bitbucket.org/eunjeon/mecab-ko/downloads/mecab-0.996-ko-0.9.2.tar.gz

tar -zxvf mecab-0.996-ko-0.9.2.tar.gz

cd mecab-0.996-ko-0.9.2

./configure --with-charset=utf-8

make

make check

make install


# /usr/local/bin 아래에 실행바이너리 파일이, /usr/local/lib 아래에 라이브러리가, 그리고 /usr/local/etc 아래에 설정 파일인 mecabrc가 설치된다.


3. mecab-ko-dic 설치


mecab-ko-dic 다운로드 페이지에서 mecab-ko-dic의 최신버전을 다운로드 받는다.

사이트 다운로드: https://bitbucket.org/eunjeon/mecab-ko-dic/downloads

리눅스 command 다운로드 및 설치

wget https://bitbucket.org/eunjeon/mecab-ko-dic/downloads/mecab-ko-dic-2.0.1-20150707.tar.gz

tar zxvf mecab-ko-dic-2.0.1-20150707.tar.gz

cd mecab-ko-dic-2.0.1-20150707

./configure --with-charset=utf-8

make

make install

# /usr/local/lib/mecab/dic/mecab-ko-dic 아래에 사전이 설치된다.

4. mecab 테스트


$ /usr/local/bin/mecab -d /usr/local/lib/mecab/dic/mecab-ko-dic
mecab-ko-dic은 MeCab을 사용하여, 한국어 형태소 분석을 하기 위한 프로젝트입니다.
mecab    SL,*,*,*,*,*,*,*
-    SY,*,*,*,*,*,*,*
ko    SL,*,*,*,*,*,*,*
-    SY,*,*,*,*,*,*,*
dic    SL,*,*,*,*,*,*,*
은    JX,*,T,은,*,*,*,*
MeCab    SL,*,*,*,*,*,*,*
을    JKO,*,T,을,*,*,*,*
사용    NNG,*,T,사용,*,*,*,*
하    XSV,*,F,하,*,*,*,*
여    EC,*,F,여,*,*,*,*
,    SC,*,*,*,*,*,*,*
한국어    NNG,*,F,한국어,Compound,*,*,한국/NNG/*+어/NNG/*
형태소    NNG,*,F,형태소,Compound,*,*,형태/NNG/*+소/NNG/*
분석    NNG,*,T,분석,*,*,*,*
을    JKO,*,T,을,*,*,*,*
하    VV,*,F,하,*,*,*,*
기    ETN,*,F,기,*,*,*,*
위한    VV+ETM,*,T,위한,Inflect,VV,ETM,위하/VV/*+ᆫ/ETM/*
프로젝트    NNG,*,F,프로젝트,*,*,*,*
입니다    VCP+EF,*,F,입니다,Inflect,VCP,EF,이/VCP/*+ᄇ니다/EF/*
.    SF,*,*,*,*,*,*,*
EOS


5. mecab-java 설치


사이트 다운로드: https://bitbucket.org/eunjeon/mecab-ko-lucene-analyzer

리눅스 command 다운로드 및 설치
wget https://bitbucket.org/eunjeon/mecab-java/downloads/mecab-java-0.996.tar.gz

tar -zxvf mecab-java-0.996.tar.gz

cd mecab-java-0.996

# Makefile 수정
vi Makefile

# Makefile 에서 INCLUDE 변수에 java include directory를 설정해준다.
INCLUDE=/usr/java/jdk1.8.0_51/include

# Makefile에서 GCC optimization 옵션을 O3에서 O1으로 변경한다.
# 은전한닢에서는 OpenJDK사용시 변경하라고 되어 있으나 Oracle JDK에서도 변경해줘야 한다.
all:
        $(CXX) -O1 -c -fpic $(TARGET)_wrap.cxx  $(INC)
        $(CXX) -shared  $(TARGET)_wrap.o -o lib$(TARGET).so $(LIBS)
        $(JAVAC) $(PACKAGE)/*.java
        $(JAVAC) test.java
        $(JAR) cfv $(TARGET).jar $(PACKAGE)/*.class

# 저장
:wq

make

cp libMeCab.so /usr/local/lib


6. 환경 설정


CentOS에서 Elasticsearch를 실행하는 계정의 환경설정파일(예: .bashrc)에 라이브러리 경로를 추가한다.

LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"
export LD_LIBRARY_PATH

7. Elasticsearch MeCab 플러그인 설치


./bin/plugin --install analysis-mecab-ko-0.17.0 --url https://bitbucket.org/eunjeon/mecab-ko-lucene-analyzer/downloads/elasticsearch-analysis-mecab-ko-0.17.0.zip


8. Elasticsearch 재시작 및 analyzer 테스트


8.1 Elasticsearch 실행
bin/elasticsearch -Djava.library.path=/usr/local/lib


8.2 index 생성 
curl -XPUT ‘localhost:9200/INDEX_NAME’
예)
curl -XPUT ‘localhost:9200/eunjeon’

8.3 index close
curl -XPOST 'localhost:9200/eunjeon/_close’

8.3 analyzer 추가 
curl -XPUT 'localhost:9200/eunjeon/_settings’ -d ’{
   "index": {
      “analysis”: {
         "analyzer": {
               "korean": {
                       "type": “custom”,
                       "tokenizer": “mecab_ko_standard_tokenizer”
                }
          }
      }
   }
}’

테스트)
curl -XGET 'localhost:9200/eunjeon/_analyze?analyzer=korean\&pretty=true -d '은전한닢 프로젝트'

8.4 index open
curl -XPOST 'localhost:9200/eunjeon/_open’


8.5 type에 대한 _mapping 설정 추가

한글 형태소 분석기 적용된 mapping 추가의 예)

curl -XPUT 'localhost:9200/eunjeon/_mapping/survey’ -d ’{
     "properties":{  
           "title":{      
                  "type":"string",      
                  "analyzer":"korean"  
          }
    }
}’

설정값 확인)
curl -XGET 'localhost:9200/eunjeon/_settings?pretty=1’


[참고 사이트]

은전한닢 프로젝트: http://eunjeon.blogspot.kr
은전한닢 프로젝트 구글 포럼: https://groups.google.com/forum/#!forum/eunjeon

2015년 8월 13일 목요일

SOLR와 Elasticsearch에서 MeCab을 사용할 때 특수문자 허용 검색하기

Apache SOLR 또는 Elasticsearch에서 한글 형태소 분석기로 Mecab Ko를 사용할 때 천원 단위 구분 또는 소수점이 포함된 숫자 타입을 검색할 때 특수문자를  SY(SYMBOL)로 태깅하고 있어서 .와 ,를 숫자와 결합하여 색인 또는 검색하는 방법을 찾지 못했다. (불가능한 것일지도...)

이번 포스팅에서는 상기의 문제점을 해결하려고 시도한 첫번째 방법과 최근에 수정한 방법을 작성했다.

문제의 검색키워드 : 1.5m 케이블

mecab 분석결과 :
1    SN,*,*,*,*,*,*,*
.     SY,*,*,*,*,*,*,*
5    SN,*,*,*,*,*,*,*
m   SL,*,*,*,*,*,*,*
케   XSV+EC,*,F,케,Inflect,XSV,EC,하/XSV/*+게/EC/*
케이블   NNG,*,T,케이블,*,*,*,*

검색/색인결과 : 
1 / 5 / m / 케이블

이렇게 색인/검색이 되기 때문에 정확하게 '1.5m 케이블' 외에 원하지 않은 결과가 상당 수 포함되었으며,
또한 마침표가 포함된 동의어를 등록할 수가 없었다.
예) 21.5 => 22


[Mecab Ko를 수정하지 않고 처리하는 방법]

PatternReplaceCharFilter를 사용해서 처리한다.

1) Solr : solr.PatternReplaceCharFilterFactory
2) Elasticsearch : Pattern Replace Char Filter 

상기의 필터를 적용하면 1.5에서 .을 제거하고 분리된 음절을 결합한다.

Solr에 적용 예)
<fieldType name="text_ko" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <tokenizer class="org.bitbucket.eunjeon.mecab_ko_lucene_analyzer.StandardTokenizerFactory" compoundNounMinLength="3" />
    <charFilter class="solr.PatternReplaceCharFilterFactory" pattern="[\.]" replacement=""/>
  </analyzer>
</fieldType>
  

결과) 1.5m 케이블 -> 15 / m / 케이블

문제점) 당연한 결과지만 15m 케이블도 같이 검색 결과로 노출된다.


[Mecab Ko를 수정해서 처리하는 방법]


[STEP 1]
mecab-ko-dic-x.x.x의 char.def에서 ASCII Code 0X2E ( . ) 와 0X2C ( , )를 SYMBOL에서 제외한다.
# ASCII
# 0x0021..0x002F SYMBOL
0x0021..0x002B SYMBOL
0x002D SYMBOL
0x002F SYMBOL
0x0030..0x0039 NUMERIC
0x003A..0x0040 SYMBOL
0x0041..0x005A ALPHA
0x005B SYMBOL
0x005D..0x0060 SYMBOL
0x0061..0x007A ALPHA
0x007B..0x007E SYMBOL

[STEP 2]
$ cd mecab-ko-dic-XX
$ make clean
$ ./configure
$ make
$ su make install

[STEP 3]
$ cd /usr/local/bin
$ ./mecab

1.5m 케이블

1    SN,*,*,*,*,*,*,*
.     SF,*,*,*,*,*,*,*
5    SN,*,*,*,*,*,*,*
m   SL,*,*,*,*,*,*,*
케   XSV+EC,*,F,케,Inflect,XSV,EC,하/XSV/*+게/EC/*
케이블   NNG,*,T,케이블,*,*,*,*

1,500원

1    SN,*,*,*,*,*,*,*
,    SC,*,*,*,*,*,*,*
500    SN,*,*,*,*,*,*,*
원    NNBC,*,T,원,*,*,*,*

[STEP 4]
mecab-ko-lucene-analyzer-0.17.x의 StandardPosAppender.java에서 결합규칙 추가
// 숫자(SN), 기호(SF/SC)는 모두 연결
appendableSet.add(new Appendable(PosId.SN, PosId.SC));   
appendableSet.add(new Appendable(PosId.SC, PosId.SN));
appendableSet.add(new Appendable(PosId.SN, PosId.SF));
appendableSet.add(new Appendable(PosId.SF, PosId.SN));

[STEP 5]
Maven Build

[STEP 6]
색인/검색 분석 결과 확인

1) Elasticsearch
curl -XGET 'http://127.0.0.1:9200/eunjeon/_analyze?analyzer=korean_query&pretty=true' -d '1.5m케이블'
{
  "tokens" : [ {
    "token" : "1.5",
    "start_offset" : 0,
    "end_offset" : 3,
    "type" : "EOJEOL",
    "position" : 1
  }, {
    "token" : "m",
    "start_offset" : 3,
    "end_offset" : 4,
    "type" : "SL",
    "position" : 2
  }, {
    "token" : "케이블",
    "start_offset" : 4,
    "end_offset" : 7,
    "type" : "NNG",
    "position" : 3
  } ]
}

2) Solr