2017-09-03 1 views
1

Lucene을 통해 발견되는 다양한 문서의 COMBINED_FIELD 필드에있는 각 용어에 대해 필드 표준으로 정규화 된 TF-IDF 점수를 계산하려고합니다. 아래 코드에서 볼 수 있듯이 문서 필드에서 각 용어의 빈도를 구할 수 있으며 문서 빈도를 얻을 수도 있지만이 필드의 표준을 구할 수있는 방법을 찾을 수 없습니다. 질의 시간. 필자가 지금까지 발견 한 모든 접근법은 오래된 Lucene 버전에만 존재하지만 Lucene 6에는 존재하지 않는 방법에 의존합니다. 이동 방법은 LeafReader의 사용 일지 모르지만 그 인스턴스를 얻는 방법을 찾지 못했습니다.Lucene 6에서 문서의 필드 표준을 얻는 방법은 무엇입니까?

각 문서에 대해 COMBINED_FIELD 필드의 표준을 어떻게 얻을 수 있는지 알고 있습니까?

필드 길이 대신 termVector.size()를 사용할 수 있습니까? size()는 각 용어의 숫자가 건이라고 간주합니까? 아니면 모든 용어가 한 번만 계산됩니까?

미리 감사드립니다.

IndexSearcher iSearcher = null; 
ScoreDoc[] docs = null; 
try { 
    iSearcher = this.searchManager.acquire(); 
    IndexReader reader = iSearcher.getIndexReader(); 

    MultiFieldQueryParser parser = new MultiFieldQueryParser(this.getSearchFields(), this.queryAnalyzer); 

    parser.setDefaultOperator(QueryParser.Operator.OR); 

    Query query = parser.parse(QueryParser.escape(searchString));    

    docs = iSearcher.search(query, maxSearchResultNumber).scoreDocs;  

    for(int i=0; i < docs.length; i++) { 
     Terms termVector = reader.getTermVector(docs[i].doc, COMBINED_FIELD); 

     TermsEnum itr = termVector.iterator(); 
     BytesRef term = null; 
     PostingsEnum postings = null; 

     while((term = itr.next()) != null){ 
     String termText = term.utf8ToString(); 
     postings = itr.postings(postings, PostingsEnum.FREQS); 
     postings.nextDoc(); 

     int tf = postings.freq(); 
     int docFreq = reader.docFreq(new Term(COMBINED_FIELD, term)); 
     //HERE I WANT TO GET THE FIELD LENGTH OF THE CURRENT DOCUMENT 
     } 
    } 
} catch (Exception e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace();   
} finally { 
    try { 
     this.searchManager.release(iSearcher); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

Alternively, 루씬에서 직접 필드의 각 용어에 대한 TF-IDF 또는 BM25 값을 얻을 수있는 방법이 있나요?

+0

그래서 표준을 구하거나 길이를 구합니다. – Mysterion

+0

사실 Lucene이 색인 생성 중에 계산하는 표준을 알고 싶습니다. 그러나 가능하지 않으면 프록시로 길이를 사용하고 1/sqrt (길이)로 내 표준을 사용합니다. –

답변

0

루씬 내부적 후, 방법 org.apache.lucene.search.similarities.Similarity#computeNorm 인덱싱 동안 기준을 계산하는 .nvm 파일의 디스크에 저장을 인코딩한다. 나중에 쿼리/점수 계산 과정에서 해독 된 것입니다.

Lucene에서 프로그래밍 방식으로 프로그래밍 할 수있는 한 가지 가능한 방법은 Similarity 클래스를 확장하고 인덱싱 및 저장 중이 정보를 얻는 것입니다. 나에게 가장 좋은 방법은 있지만 적어도 뭔가는 좋아하지 않습니다. getLength() 당신은 당신이 당신의 예에서와 같이 while의 반복에 의해 계산할 수있는 분야에서 용어의 수입니다

discountOverlaps ? state.getLength() - state.getNumOverlap() : state.getLength(); 

: 한편

, BM25Similarity는 길이 이런 식으로 계산한다.

+0

답장을 보내 주셔서 감사합니다. 흠, 방법 일 수 있고 이미 이것에 대해 생각했지만 뭔가를 놓친 것일 수도 있다고 생각했습니다. Lucene은 실제로 안정적인 API를 가지고 있지 않으며, 거의 모든 것을 지속적으로 변화시키고 있지만 이전에 제공했던 기능을 왜 제거해야하는지에 대한 질문에 당황 스럽습니다. 조건을 반복하고 빈도를 곱하면 z가 될 수 있지만 확실히 그렇게하는 방법입니다. 그러나 Lucene이 내가 액세스 할 수있는이 값을 저장할 수 있다고 생각합니다. –

+0

그들은 그것을 많이 바꾸고 있습니다. 네, 제가 말했듯이, Lucene은 .nvm 파일의 규범을 디스크에 저장합니다. 아마도 수동으로 읽고 해독 할 수는 있지만 Lucene API 방법은 그렇지 않습니다. – Mysterion

+0

사실입니다! 내 말은, Lucene에서 nvm 파일을 읽고 다시 수동으로 코드를 찾을 수도 있지만 정말 이상 할 것입니다. 두 번째 방법은이 정보를 얻는 방법이 더 쉽고 (더 쉽고 빠를 가능성이 높을 것 같습니다.) 그런데 size()는 모든 토큰을 한 번만 계산하므로이 필드의 전체 길이를 반환하지 않습니다. –

관련 문제