본문으로 바로가기

[Lucene] 루씬 - TermVector란?

category 개발이야기/Lucene & Solr 2019. 10. 2. 04:12
반응형

이전글에서 간단하게 무작정 따라하기로 문서의 index를 만들고 검색하는 예제를 작성했습니다.

다음 예제를 포스팅하기 전에 TermVector의 정의를 설명하려 합니다.

Apache Lucene 공식 API 문서에도 TermVector라는 단어가 계속 나오기 때문에 개념없이 다음을 이해하기엔 반쪽짜리 설명이 될것 같네요.


이 글은 하기 링크의 원문을 번역 및 의역하였습니다.

또한 불필요한 부분은 제거하고 이해를 돕기위해 추가적인 부가 설명도 추가하였습니다.

http://makble.com/what-is-term-vector-in-lucene


루씬 자바독의 문서에 따르면, term vector는 document에서 term의 list와 document 내부에서 반복되는 개수로 정의 됩니다.

따라서 Document당 하나의 term vector(list형태의)를 갖습니다.


term은 lucene에서 검색가능한 기본단위 입니다.

Text는 stream으로 분리돠고, term은 stream을 구성하는 요소가 됩니다.

query를 할때, 먼저 terms으로 parse된 이후에 lucene index에서 검색 됩니다.


term은 field name과 실제 값으로 (pair로) 존재하며, 여기서 값은 영어단어나, URL, email등이 될수 있습니다.


Term t = new Term("Field", "Term text");


Lucene의 index를 검색한다는건, 일반적으로 문자를 찾거나, 정규식 또는 작은단위의 문자를 찾는것과는 다릅니다.

Lucene의 기본적인 검색은 user가 term(field, value)의 정보를 제공하고, lucene은 키워드를 갖는 filed를 포함하는 document를 반환합니다.



Term vector의 정의에 대한 혼돈

만약 어떤 field가 document에서 term vector를 사용한다면, 이 field에 속한 모든 terms는 document의 term vector에 추가 됩니다.

Java Doc에서는 term이 document에 포함된것처럼 설명하지만, term의 집합(collection)이 document이며, term은 먼저 field로 카테고라이징 된 이후에 문서에 포함됩니다.


Term vector는 field 단위로 활성화/비활성화가 될수 있습니다.

Document는 활성화 또는 비활성화된 term vector들 동시에 가질수도 있습니다.


좀더 이해하기 쉽게 정리하자면, 각 document의 각 field에 대한 term vector는 활성화/비활성화 될 수 있습니다.

만약 term vector가 활성화 된다면 해당 field에 속한 모든 terms는 document의 term vector list에 포함됩니다.

이 list는 term 뿐만 아니라, 부가적인 정보(발생빈도, 문서내 위치, offset)도 같이 포함됩니다.



Index option과 Term vector

Lucene에서 document를 index에 등록하면, DB table의 column에 row를 추가하듯 document에 field가 추가됩니다.

document == table, field == column 이라고 생각하면 되겠네요.

또한 각 field마다 다양한 옵션을 통해 Lucene이 이 document의 index를 만들때 어떻게 다룰지를 결정할 수 있습니다.


field의 옵션에는 세가지가 있습니다.

1. indexing

2. storing

3. term vectors


Indexing

이 옵션은 field를 어떻게 index할지를 결정하고, 이에 따라 어떻게 검색할지도 결정됩니다.
tokenize의 여부 및 해당 token이 검색이 가능하게 할건지, ID값(숫자이지만 String 타입으로 저장된) 같이 전체 문자열이 동일할 때만 검색하게 할 건지를 결정합니다.

Storing

이 옵션은 index에 실제 데이터를 저장할지 말지를 결정합니다.

Index는 Map 형태이며 java로 표현하면 Map<Term, Document>형태 입니다.

Term vector 역시 storing 처럼 저장될수 있지만 indexing에 의해서 생성된 다른 정보를 저장합니다.

Term vector 역시 Map 형태이나 term을 key로 하고 값은 document 내부에서 term의 position, offset, frequency를 나타냅니다.

Map<Term, (position, offset and frequency of document)>

Document의 term vector의 각 term들은  document id, field name, text of term, frequency, position, offset으로 구성되어 있어, 이런 정보들을 활용하여 검색을 진행합니다.


Term Vectors

이런 index 옵션들은 inverted index를 생성합니다. 하지만 이 inverted index는 특정 term으로 이 term이 포함된 document나 field를 찾는 역할밖에 할 수 없습니다.

즉 term으로 document id를 찾는 작업밖에는 할 수 없습니다. 

하지만 이렇게 inverted index로 일단 document id를 찾고, term vector로 document 내부에 term이 속한 위치를 모두 찾을 수 있습니다.

Term vector는 document 내부에서 정보를 찾는 inverted index 역할을 합니다.


가장 전형적인 예로 검색 결과의 highlighting을 들 수 있습니다.

일반적으로 특정 string으로 query를 하면 Lucene은 관련 document를 찾고 찾은 내용을 보여줍니다.

이때 결과로 제목, URL 그리고 검색 키워드가 포함된 간략한 문장에 키워드를 Highlight해서 보여주는 형태로 많이 구성 됩니다.

다만, Docuement에 제목과 URL은 저장할 수 있지만 query에 따라 매번 달라지는 keyword를 포함하는 앞뒤 문장은 저장할 수 없습니다.

따라서 이때 term vector의 정보를 이용하여 키워드의 position을 찾고, 그 주위 문장들을 일부 가져와 같이 보여줍니다.

이제 terms vector의 역할이 명확해 지셨나요?


Term vector의 또다른 강점은 유사문서를 찾을수 있다는점 입니다.

Term vector의 정보를 이용하면 두 Document가 얼마나 유사한지 간단한 공식으로 계산할 수 있습니다.

예를 들어 블로그 항목에 관련 게시물 처럼 유사 게시물을 찾는데도 Term vector의 정보가 이용됩니다.

이 부분은 글 아래에서 좀더 자세히 다룹니다.


Term vector는 analyzing 단계에서 생성되며, 이때 position과 offset 정보도 제공됩니다.

또한 이런 정보의 저장여부를 옵션으로 조정할 수 있습니다.

- TermVector.YES:  반복 회수만 저장함.

- TermVector.WITH_POSITIONS: 반복횟수 & position 정보

- TermVector.WITH_OFFSETS: 반복횟수 & offset 정보

- TermVector.WITH_POSITIONS_OFFSETS: 반복횟수 & position 정보 & offset 정보

- TermVector.NO: 아무것도 저장 안함.

저장한 정보가 없더라도 검색시에 계산하도록 할 수 도 있습니다.


아래와 같이 값을 저장하면 Term vector를 활성화 시킬 수 있습니다.

Document doc = new Document();
doc.add(new Field("title", "My cat looks like tiger",
    Field.Store.YES,
    Field.Index,ANALYZED,
    Field.Store.TermVector.WITH_POSITIONS_OFFSETS));


Term vector의 동적 생성


Text 값만 저장한 경우 query 시점에 term vector를 생성할 수 있습니다.

예를 들어 text의 일부를 highlighting 하는 경우 TokenSources class의 getAnyTokenStream() 통해서 token stream을 얻을 수 있습니다.

token stream은 만약 index time에 생성된 term vector가 있으면 이걸 사용하고, 없다면 분석을 시작합니다.

text 일부 Highlighting 예제링크 -> http://makble.com/how-to-do-lucene-search-highlight-example



Term vector를 이용한 문서간 유사성 측정

Term vector의 vector의 수학에서 사용하는 vector의 개념에서 가져왔습니
만약 Document에 term1, term2 두개의 term vector만 있다고 할때 두개의 term의 발생 빈도를 아래와 같이 표시 할수 있습니다.

document에서 term1, term2의 발생빈도 (frequency)

(term1:3, term2:4) 

term1을 x축, term2를 y축이라고 한다면 x-y 평면에서 (3,4)에 위치 하며, 원점(0,0) 에서 (3,4)까지 직선을 이으면 이 document의 vector가 완성됩니다.


만약 term이 하나더 존재한다면 3차원 평면이 되며, term이 n개 있다면 n차원의 벡터값이 됩니다.

이렇게 문서간 벡터의 기울기(각도)가 적을수독 문서의 유사성이 높다고 판단할 수 있습니다.


Term vector의 생성 시점 조정

Term vector는 유용하기는 하지만 추가적인 정보의 저장으로 인하여 디스크 공간을 많이 사용합니다.

따라서 검색시 document를 다시 분석하고 term vector를 바로 얻을수 도 있습니다.

이때 걸리는 시간은 indexing process에서 진행하는것과 동일하게 걸리며, 검색성능의 overhead는 생기지만 디스크 공간은 절약할 수 있습니다.

만약 문서의 크기가 작다면 이런식으로 term vector를 적용하는게 더 나은 방법이 될수도 있습니다. 


 

반응형