본문 바로가기

Lucene

Terms.getSumTotalTermFreq() in Lucene 4.0

소스의 중복도를 체크하는 프로그램의 파일럿을 만들어보려고 새벽 출근한김에 뚝딱거려보았다.


뭐 기본적으로는 루씬으로 색인 후 루씬의 TermFreqVector를 이용해서 코사인유사도를 사용해서 일단 뽑아보는거였는데.. lucene 3.6까지는 TermFreqVector가 있었는데 4.0에서는 그것이 Terms, TermEnum, DocEnum등으로 대체가 된듯 하였다.


그래서 관련한 자료들을 찾아보고

테스트 코드를 만들어가면서 이것저것 실행을 해보고 있었는데

Terms.getSumTotalTermFreq()의 결과가 영~~ 이상하게 나온다. 계속 -1이 나오는것..


IndexReader로부터 하나의 Document에 대한 Terms 인스턴스를 얻어내면

그 Terms의 인스턴스는 딱 하나의 Document가 색인되어있는 역인덱스 파일의 데이터와 같은

형태를 가진다.


예를 들어서,

> Document 1 : "learning perl learning java learning ruby"
> Document 2 : "perl test"


이 두개의 Document가 있을 경우 IndexReader로부터

아래와 같은 코드로 Terms 인스턴스를 얻어낸다..


> IndexReader ir = IndexReader.open(dir);
> Terms terms = ir.getTermVector(0, "f");
>
> System.out.println(terms.getDocCount()); -> 1
> System.out.println(terms.getSumDocFreq()); -> 4
> System.out.println(terms.getSumTotalTermFreq()); -> -1


 옆에 화살표에 표시된 숫자가 결과값인데.. 앞에 이야기하였듯이 terms 인스턴스는 단일 Document가 색인된 역인덱스 파일의 데이터와 같다. 따라서 term이 위와 같이 데이터가 나타나는듯하다.

terms로부터 TermsEnum을 얻고, 이 enum으로부터 각 term에 대한 통계정보를 받을 수 있는 구조이며

위 나열되어있는 terms의 메서드들은 대부분 TermsEnum으로 얻어지는 각 term들의 통계정보에 대한 합이다.


예를들어 getSumDocFreq는 TermsEnum.docFreq()의 합인데, TermsEnum.docFreq()는 

"How many documents contain at least one occurrence of the term in the field" 이다.

즉, 각 term을 가진 Document의 수인데, 단일 Document가 색인된 역인덱스파일에 대한 형태이므로 learning - 1, perl - 1, java - 1, ruby - 1이 되고 이 합인 4가 나오는 형태이다.


물론 이것을 전체 색인 파일을 대상으로 Terms 인스턴스를 뽑아내면 결과는 달라질것이다.

일단 perl에 대한 docFreq()가 1이 아니라 2가 될테니..


아무튼.. -1이 나오는 것이 이상하여..

루씬 메일링 그룹에 질문을 올렸다.. 아 근데 역시 영어가 문제야..ㅠㅠ 

영어로 메일쓰기가 너무 어렵고 보내기 버튼을 누르는 순간까지도 이걸 이 사람들이 질문을 이해할까? 이런 고민만..-.-;;


근데 이 궁금증을 해결할 방법이 없어서 질문을 보냈는데, 루씬 메인 커미터중 한사람인 Michael McCandless로 부터 답을 받았다. 결론은....  현재 색인 포맷이 각 Document별로 저 데이터를 가지고 

있지 않아서 그런것이며 원칙적으로는 수정을 하려고 하고있다.

현재 상태로 -1은 맞는 값이다. 라는 것..


이게 javadoc에 codec이 통계 데이터를 가지고 있지 않으면 -1이 나온다라고 되어있었던것 같은데..

그게 이런 의미로 연결되는 줄은 전혀 몰랐다.. 역시 일단 막 던지고 봐야돼 -_-;


급한거면 지라 이슈를 열어서 패치를 해주겠다고 다시 물어봐오는데..

그럴필요 없다라고.. 다시 메일을 써야하는건 함정 --;


결국 새벽에 만들던 파일럿 프로그램은 3.6을 사용해서 원래 알던 방법으로 구현을 해봤는데..

결과가 영 이상하다..ㅎㅎ 생각해보니 중복 소스를 체크하는 것은 TF-IDF를 이용한 유사도 점수와는 좀 다른 문제인듯하다.