2012년 3월 4일 일요일

한국어로 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모듈과 관련된 블로그 페이지 




댓글 15개:

  1. 작성자님. 안녕하세요.
    위의 형식으로 작성된 입력데이터 sample 파일과 결과는 아래의 파일로 첨부한다.
    - 첨부1: mallet site어딘가에서 얻는 2번째 파일 형식의 데이터, 정확한 소스가 기억안남.
    - 첨부2: 첨부 1을 넣어서 돌린 LDA의 결과, 꽤 나이스 하다.

    =============================================
    라고 글을 남겨주셨는데. 첨부1과 첨부2의 Link를 따라 들어가니 구글 홈페이지가 나오네요... 수정부탁드려요ㅜㅜ

    답글삭제
  2. 흠.. 아무래도 blogspot 서버가 잠시 문제가 있었던것 같습니다.
    좀전에 확인해본 결과 첨부1과 첨부2 파일을 다운하는데 문제가 없네요.
    혹시 계속 다운이 안되시면 제가 다시 받아서 이메일로 보내드리겠습니다.

    답글삭제
    답글
    1. 아. 작성자님.! 안녕하세요. LDA를 공부하고 있는 학생입니다.
      여전히 다운은 안되지만.. 하나 질문드릴게 있습니다!
      제가 한글을 형태소 분석을 통해서 명사로만, input에 넣어서 LDA를 돌려보았습니다. 작성자님이 사례를 든 것처럼.
      AP881218-1 X 거침 사마귀유치원 도지사 음성 기억 좌천
      AP881218-2 X 시원한프로 뉴스 거침 사마귀유치원 도지사 음성 기억 좌천
      AP881218-3 X 사마귀유치원 도지사 음성 기억 좌천 시청자 통쾌
      위의 예시를 돌려보았습니다. 그런데 결과값을 이해를 할 수가 없네요...
      어떠한 형식으로 주제를 도출하게 되는 것인가요..
      dezember-23 weilburg-68 beerdigt-80 fulda-44 war-68 seit-14 herzog-6 von-44 franken-23 und-44 von-44 bis-80 k?nig-44 des-68 ostfrankenreichs-49 와 같은 형식은 무엇을 의미하는 건지.. 혹시 제가 이해를 할 수 있을까요.?^^

      삭제
    2. 작성자가 댓글을 삭제했습니다.

      삭제
    3. 작성자가 댓글을 삭제했습니다.

      삭제
  3. 블로거님.. 무언가 문제가 있어 메일을 보냈습니다..
    시간나시면 확인 해주시면 감사하겠습니다!^^

    답글삭제
    답글
    1. 휴..해결되었습니다. 감사합니다.!

      삭제
  4. 네. 아직 메일 답변을 못드렸는데, 해결되셨다니 다행이네요. ^^

    답글삭제
  5. 첨부 파일 받아 볼수있을까요?

    wonmj3@gmail.com

    답글삭제
  6. 작성자님 안녕하세요
    저도 혹시 첨부파일 받아 볼 수 있을까요?
    부탁드리겠습니다.
    jwlghks90@naver.com

    답글삭제
  7. 작성자가 댓글을 삭제했습니다.

    답글삭제
  8. 안녕하세요. 전 command line으로 먼저 테스트 해보려고 했는데요 먼저 한글 형태소 분석기(hannanum)으로 단어 추출하고 띄어쓰기 구분으로 "word1 word2 word3" 이런 형식으로 파일 저장해놓고 import하고 train했습니다. 그런데 한글 인식을 못하더라구요 아웃풋에 아무것도 안뜨던데... (님께서 하신 TopicModel.java의 input으로 넣어도 같은 문제가.. 그리고 A3948 X word1 word2 ... 로 파일 만들어도 안나오더라구요 ..) 어떻게 하신건지 여쭤봐도 될까요..? 메일로 샘플이라도...ㅠ

    답글삭제
    답글
    1. 한글 인식이 안되는 문제라면 해당 txt파일이 UTF-8인코딩을 따르고 있는지 확인이 필요해 보입니다. 메모장에서 저장할때 UTF-8로 지정가능하니, 인코딩 바꿔서 한번 돌려보시는게..

      삭제
    2. 아......... notepad로 옮기고 저장했는데.. ANSI로 되있었어요.. ㅠㅠ 감사합니다.. 이런 멍충이 ㅠㅠ 창피해서 글을 삭제하고 싶지만 혹시 모를 저같은 분들을 위해.. ㅋㅋ

      삭제
  9. 작성자가 댓글을 삭제했습니다.

    답글삭제