2015-03-05 한글 텍스트 마이닝 MALLET 

The Programming Historian
 
cmd 창에서 환경변수 설정 끝내고 명령어 입력해서 텍스트 마이닝 돌리는 절차.
 
Importing data
bin\mallet import-dir --input pathway\to\the\directory\with\the\files --output tutorial.mallet --keep-sequence --remove-stopwords
 
Your first topic model
bin\mallet train-topics  --input tutorial.mallet
 
 
한국어로 LDA(Latent Dirichlet Allocation) 돌리기
 최근 데이터마이닝(data mining)분야에서 매우 핫한 키워드가 있다.
Latent Dirichlet Allocation 혹은 그냥 LDA로 불리우는 알고리즘이다.
기존의 LSI와 비슷한 용도로 사용되는 알고리즘인데, 특정 문서 혹은 문서집합들에서 주제를 추출하는데 활용된다.
 
알고리즘에 대한 개념적인 설명과 활용방법은 다른 블로거가 LDA 겉핥기LDA실습 이라는 글에 잘 정리되어 있다.
 
따라서 여기서는 어떻게 LDA를 돌려보거나, 혹은 활용할 수 있는지에 대해 설명하려한다.
물론 데이터마이닝 전공자들은 많은 시간을 들여 LDA에 대해 공부하고, 라이브러리를 찾아서 부딛혀 볼 수 있고, 정 안되면 논문을 보고 직접 알고리즘을 구현해 볼 수 있을 것이다.
하지만, 타 분야에서 이를 단지 활용해보고 싶거나, 어떤 알고리즘인지 일단 돌려보고 싶은 사람들에겐 이건 너무 가혹하다..  왜냐면 많은 텍스트 마아닝 라이브러리는 어렵고, 배워야할 것들이 매우 많다.
 
LDA에 대한 소개는 위의 링크들에서 잘 설명되고 있으니 알고리즘에 대한 설명은 건너뛰고, LDA를 블랙박스시스템으로 놓고서 설명하면
이 블랙박스 시스템의
입력은 텍스트 문서의 집합이고
출력은 모델링된 토픽들의 집합이다.
 
기존의 벡터 스페이스 모델과 달리 LSI LDA에서는 각각의 문서들이 여럿의 토픽, 즉 주제들과 연관지어질 수 있고, 문서에 등장하는 단어들은 그 토픽들을 이루기 위한 요소들로 여긴다. , 문서에 사용된 단어들이 토픽을 구성하고, 토픽이 합쳐져서 문서를 구성하는 형태로 문서를 가정, 혹은 모델링 하고 있다. LDA는 단어들간의 문서내에서의 동시등장(co-occurrence) 빈도를 확률화하여 이로부터 숨겨진 토픽들을 도출하는 역할을 한다.
LDA의 출력 값은 아래와 같은 알흠다운 그림을 그릴 수 있게 해주는데, 아래의그림은 LDA(정확히는 L-LDA)를 활용해 특정 트위터 타임라인의 주제를 도출한 그림이다.

[출처: Characterizing Microblogs with Topic Models by Daniel Ramage, Susan Dumais, and Dan Liebling, May 2010, In Proc. ICWSM 2010]
 
이제 본격적으로 LDA를 돌려보기 위해서는 블랙박스시스템역할을 해줄 LDA 라이브러리와 분석할 대상 데이터가 필요한다.
 
LDA라이브러리는 java 기반으로 만들어진 MALLET 을 썼는데,
첫째로는, 국내 연구자들이 많이 사용하는 java를 기반으로 구현되었으며,
둘째로는, Eclipse에서 라이브러리 형태로 가져다 쓰기 용이하고,
마지막으로는 텍스트 인코딩에 UTF-8을 기본으로 쓰고 있어서, 한국어 처리에 문제가 없다는 매우 큰 장점을 가진다.
 
분석대상 될 입력데이터는 MALLET역시 한글에 대한 분석을 지원하지 않으므로, 전처리를 필요로 한다. 전처리를 위해서는 국민대의 한국어 형태소 분석 라이브러리인 HAM을 활용할 수 있다.
 
생각보다 내용이 길어져 MALLET의 구동과 HAM을 통한 데이터 전처리 과정은 다음 글에서 이어가야겠다.
 
 
 
 
한국어로 LDA(Latent Dirichlet Allocation) 돌리기 2
이전 포스트에서 다루었던 LDA로 한글을 돌리는 방법에 대해 보다 상세한 사항들을 정리하려 한다. 이전 포스트라지만.. 사실 두달전에 썼던 글을 이제서야 업데이트 한다. ㅎㅎ
 
1. Mallet eclipse에서 활용하기. 
먼저 Mallet을 사용하기 위해 패키지를 다운받는다. 현재 내가 사용해본 버전은 2.0.7이고 Mallet 다운로드페이지에서 최신버전을 제공한다. 
앞에서 언급한대로 Mallet eclipse에서 활용하기 편리한데, 먼저 압축을 해제하고(해제된 folder를 앞으로는 MALLET_HOME 으로 쓰겠다.) 
eclipse에서 새로운 프로젝트를 생성한 후 Project Property 페이지에서 Mallet활용을 위한 jar 파일들을 link시켜주어야 한다. 
[Mallet관련 jar파일들을 추가한 화면]
위의 그림처럼 mallet을 쓰기위해서는 두개의 jar파일을 link시켜야 하는데, mallet.jar mallet-deps.jar 파일은 MALLET_HOME/dist에 존재한다. 
jar와 관련된 설정을 마치고, 간단한 test를 해볼 수 있는데, mallet library는 친절하게도 example파일들을 MALLET_HOME/src/cc/mallet/examples의 위치에 포함하고 있다.
 이 포스트에서는 LDA를 활용하는 방법에 대해 적고 있으므로, examples폴더에 LDA.java 라는 example파일이 있으면 좋겠지만, Mallet에서는 LDA LDI라는 명칭을 class이름으로 쓰고 있지는 않다. 하지만 TopicModel이라는 클래스가 LDA 알고리즘을 구현한 것이라는 소개를 Mallet 페이지 어딘가에서 찾을 수 있다. 따라서 TopicModel.java를 통해서 LDA를 테스트해 볼 수 있다. 
2. Example(TopicModel.java) 실행하기 
TopicModel 클래스 파일에는 text기반의 데이터 파일을 읽는 과정과 LDA를 실행시키는 과정, 그리고 LDA의 실행결과를 콘솔에 출력하는 코드가 포함되어 있다. 
따라서 LDA실행을 위해서는 TopicModel 클래스 파일만 실행시키면 되는데, 코드를 간단히 살펴보면 알 수 있듯이, 해당파일은 입력 데이터 파일의 위치를 args로 입력받는다.  eclipse에서는 Run Configurations에 들어가서 Arguments패널에서 데이터 파일의 위치를 설정해주어야 한다. 
Mallet이 받는 데이터 파일의 구조는 3가지이고데이터 import 페이지에 설명되어 있다. 
간단하게 정리하면 
1. One instance per file은 각 text파일 마다 하나의 문서의 내용이 들어있는 형태, 폴더주소를 입력데이터의 path로 받음 
2. One file, one instance per line은 하나의 text파일에 한줄당 한 문서의 내용들이 들어가 있는 형태, 하나의 파일명을 입력 데이터 path로 받음
3. SVMLight format은  SVM 형태의 데이터를 입력으로 받음. 
2번째 파일 형식은 데이터 import 페이지에 설명되어 있드시, 
[URL] [language] [text of the page...]의 형태로 작성되어야 한다. 
여기서 URL은 문서를 지칭하는 고유의 값이어야하고, language mallet자체에 내장된 stopword list를 활용한다던지 하는 이유로 설정하여 활용할 수  있겠지만, 일단은 X로 두는걸로 한다. text of the page에 문서의 텍스트가 들어가게 된다. 
위의 형식으로 작성된 입력데이터 sample 파일과 결과는 아래의 파일로 첨부한다. 
첨부1: mallet site어딘가에서 얻는 2번째 파일 형식의 데이터, 정확한 소스가 기억안남
첨부2: 첨부 1을 넣어서 돌린 LDA의 결과, 꽤 나이스 하다
3. 한국어로 Mallet실행시키기
한국어로 mallet을 실행시키는 방법은 위의 예제처럼 간단하지 않은데 그 이유는 한국어와 영어에는 중요한 차이가 있기 때문이다. 
예를 들어 문서 A I live in South Korea라는 문장을 포함하고 있을때 우리는 꽤나 간단하게 space를 separator활용해서 이 문장의 키워드를 꺼낼 수 있다. I in 을 불용어 처리하면 live, South, Korea가 키워드가 될텐데, 이 키워드들은 대소문자 문제와 단/복수 정도의 케이스만을 제외하면 다른 문장에서 얻을 수 있는 키워드들의 비교가 용이하다.
하지만 한국어 문서를 예로들어보면, '나는 남한에 산다.' 라는 문장은 '나는', '남한에', '산다'로 분리된다. 이 단어들은 다른 문장에서 나올 같은 의미의 키워드들과 비교되기 힘들기 때문에 키워드로 활용하기에 적합한 형태가 아니다. '나는' '' ''으로, '남한에' '남한' ''로 분리하고, '산다'가 동사의 원형인지를 확인한 후 '' '남한' '산다'를 키워드로서 사용할 수 있게된다. 
위의 설명은 대략적인 설명이고 보다 자세한 한국어/영어의 언어처리방법의 차이점은 다른 많은 곳에서 찾을 수 있을 것이다. 
Mallet은 당연히 이러한 한국어 처리 과정을 지원하지 않는다. Mallet을 활용한 한국어 처리를 위해서는 이러한 한국어에 대한 전처리 과정을 수행한 후에 Mallet의 입력데이터로 제공해야 한다. 
나는 잘 알려진 국민대의 한국어형태소 분석기 HAM을 활용하여 문서에서 명사만을 걸러낸후에 Mallet의 입력으로 제공하였다. 상당히 일반적이지 않은 목적으로 테스트를 해본거라서 테스트했던 입력데이터는 크게 도움이 되지 않을 것 같아서 입력파일의 샘플만을 간단히 소개하면 아래와 같다. 
AP881218-1 X  거침 사마귀유치원 도지사 음성 기억 좌천  
AP881218-2 X  시원한프로 뉴스 거침 사마귀유치원 도지사 음성 기억 좌천 
AP881218-3 X  사마귀유치원 도지사 음성 기억 좌천 시청자 통쾌 
한국어 데이터로 LDA를 실행하기 위한 입력데이터의 준비과정을 다시 한번 설명하면.. 
1) 분석 한국어 문서들을 HAM과 같은 형태소 분석기에 돌린다. 
2) 형태소 분석기에 의해 분석된 형태소 중, LDA에서 topic추출을 위해 활용한 형태소들을 선택한다. 명사들만 활용하거나, 명사+동사, 명사+동사+부사 정도의 선택이 있을듯 하다. 
3) 각 문서와 형태소 분석기의 결과를 하나의 mallet입력파일로 변환한다. 
이렇게 정리될 수 있고, 한국어 입력데이터가 준비되면 다시 2번으로 돌아가서 sample데이터 대신 새롭게 만들어진 데이터파일을 argument로 주고 실행시키면 문제없이 구동이 가능한다.  
참고. 
HAM c기반이어서 eclipse를 활용해서 쓰는건 상당히 까다로운데, 연구실 후배가 HAM을 웹서버에 올려서 restful한 형태의 request를 지원하는 형태로 만들었다. url에 분석하고 싶은 문장을 인코딩해서 보내면 형태소분석의 결과(명사들만) soap로 보내준다. 이와 유사한 PHP모듈과 관련된 블로그 페이지 
 
 
java.lang.unsatisfiedlinkerror no in java.library.path 에러 대처법
 
LDA (topic modeling) 구현들
 
Mallet 시작하기(링크)
 
강승식 교수: 한글공학, 정보검색 연구소
 
엑셀기반 스탠포드 토픽 모델링 도구
 
한글에 대한 편집 거리 문제(한글 검색에 검색어 처리 관련 논문)
 

+ Recent posts