2015년 9월 4일 금요일

소셜 데이터에 대한 빅데이터 분석과 형태소 분석기의 사용..

소셜 데이터들에 대한 빅데이터(?) 혹은 나름의 분석을 하려고 할때 많은 사람들이 찾게되는 기술블록인것 같다. 사실 개발하려는 기술을 빅데이터에 분석이라는 이름으로 정의를 하던 그렇지 않던간에 자연어 텍스트에 대한 분석을 하는 상황에서 형태소 분석기를 찾는건 어찌보면 당연한것 같다.

그래서인지 최근에 쉽게 사용할 수 있는 형태소 분석기의 옵션이 꽤 많아진것 같다.

HAM으로 잘 알려진 국민대의 형태소 분석기는 국민 형태소 분석기랄까? ㅎㅎ 한번씩은 다들 써보는 형태소 분석기이다.
KOMORAN 이나 꼬꼬마 한국어 형태소 분석기는 최근에 많이 쓰이는 추세인것 같고, 은전한닢 이라는 나름 좋은 컨셉으로 새롭게 만들어지고 있는 형태소 분석기도 있다.

이런 형태소 분석기들 중 뭐가 성능이 좋은가를 논하는건 사실 꽤나 의미가 없는 일이라고 생각된다. 왜냐면, '한국어텍스트' 자체가 처리하기 까다로운 언어라서 어떤 녀석을 택해도 직관적으로 만족스러울 만큼의 성능을 보장하지는 않기 때문에... 그래서 실제 한국어 텍스트 데이터들을 처리하는 회사들은 조금더 나은 성능의 상업버전(대부분 이런 형태소 분석기들을 기반으로 만들어진거지만..)을 가져다가 사용자 사전을 충실히 보강하는 방식으로 형태소 분석기를 활용하는 것으로 알고 있다. 은전한닢이 다른 형태소 분석기들에 비해서 새롭다는건... 이런 사전관리에 'Web기반', 'Open기반' 등의 개념의 도입을 고려하고 있어 다른 형태소 분석기들에 비해 사용자 사전관리가 용이한 녀석이 될 것 같기 때문이다. (아직까지 시스템에 반영된것은 아닌것으로 알지만, 현재로서도 사용자 사전 관리는 다른 형태소 분석기에 비해 용이한것으로 판단된다)

사실 형태소분석기의 사용여부는 참 풀기힘든 문제인것 같다. 아무래도 많은 데이터를 다루게 될텐데, 형태소 분석기를 앞단에 내세워 최대한의 garbage를 걸러내고 의미있게 태깅된 데이터만을 가지고 데이터를 분석하는게 맞는 것 같기도 하고, 형태소 분석기가 가지는 오류를 안고 가느니 분석범위를 포괄하는 사전(Dictionary)를 잘 구축해서 처리하는게 나을 것 같기도 하고... 참 '계륵'같은 녀석인것 같다.

결국은 포털에서 하는것처럼 형태소 분석기와 n-gram인식기를 둘다 사용하는 쪽으로 결론내는게 자연스러운 의사결정인것 같다. 하지만 의존성이랄까? 형태소 분석기와 n-gram 인식기의 비중, 두 녀석이 담당하는 영역의 정의 문제가 남게되는데.. 몇가지 기준은 정할 수 있을 것 같다.

1. 동사, 형용사에 대한 추출이 필요한가?
2. 텍스트데이터에서 뽑을 키워드 사전을 직접 구축할 수 있는가?
   2.1 ngram사전 > 내사전이 맞는가?

1번의 질문의 답이 '필요하다' 라면 당연히 형태소 분석기에 의존할 수 밖에 없다. 만약 '전혀 필요없다' 라면 n-gram단어 인식기를 쓰고 garbage 열심히 걸러내는 형태로 사용해도 형태소 분석기를 쓸때보다 나은 결과를 얻을 수 있을 것으로 보인다.
2번에서 텍스트 데이터를 분석할때 활용할 키워드를 사전화 할 수 있다는 말은 (사전의 주기적update도 포함해서) 데이터로 부터 추출할 키워드들을 명확하게 정리해낼 수 있는냐는 질문인데... 직접 사전이 구축가능하다면 n-gram추출기를 활용하는게 더 효율적일 가능성이 높다. 키워드가 한정된다면 garbage처리도 수월하고, 데이처처리 속도도 '형태소분석' >>넘사벽>> '사전을 사용한 ngram인식' 일 확률이 높기 때문이다.
2.1번의 질문은 2번에서 구축한 사전이 n-gram사전처럼 방대한 경우는 다르게 생각해야할 수 있다는 건데, 이럴 경우, garbage 필터링에 대한 보장을 할 수 없고 n-gram인식기의 처리속도도 그닥 빨라지기 힘들어 진다. 포털은 이러한 상황에 의해 형태소 분석기와 ngram인식기를 함께 쓰는걸로 봐야할듯 하고...

형태소 분석기과 n-gram인식기를 사용한 방식에 대한 비교글은 조만간 테스트가 끝나는 대로 정리해볼 예정이다.


* ms에서 공개하는 N-gram사전 서비스가 있다. 물론 영어..
** 한국어는 오픈한글이라는 사이트에서 제한적으로(감성사전만..) api형태로 제공하고 있기는 한데.. n-gram사전이라고 하기엔 좀 민망하다.







2015년 9월 2일 수요일

한국어 ngram 생성기..

단어가 아닌 글자수로 ngram을 생성하기 위한 java 코드.
한국어라고해서 딱히 달라질건 없으나, 함수 입력값으로 gram생성을 위한 size를 받아서 해당 size의 ngram만 생성해준다. 물론 1~10크기의 ngram을 생성하기 위해서는 10번을 호출해야한다.
한국어 특성상 ngram을 생성하면 garbage가 꽤나 많아지므로 글자의 size별로 grabage 날리기 위한 처리를 하기에는 편한 코드.

public ArrayList<String> nGramAnalyzer(String sentence, int gram) {
ArrayList<String> termList = new ArrayList<String>();
for(int i = 0; i < sentence.length() - (gram - 1); i++)
        {
String term = "";
for (int j = 0; j < gram; j++) {
if (j == (gram - 1)) {
term += String.valueOf(sentence.charAt(i + j));
} else {
term += sentence.charAt(i + j) + "";
}
}
termList.add(term);
}
return termList;
}

** 대상 text는 UTF-8로 가정하고 테스트를 해본 코드
** 사전은 가능하면 Map으로 memory에 로딩해서 비교해야 처리속도를 보장할 수 있음

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




2012년 1월 5일 목요일

한국어로 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을 통한 데이터 전처리 과정은 다음 글에서 이어가야겠다.