1

現在、ルセン インデックスの用語の tf-idf マトリックスを計算しようとしています。私は次の関数でこれをやろうとします:

public Table<Integer, BytesRef, Double> tfidf(String field) throws IOException, ParseException{
    //variables in complete context
    int totalNoOfDocs = reader.numDocs();                                   //total no of docs
    HashBasedTable<Integer, BytesRef, Double> tfidfPerDocAndTerm = HashBasedTable.create(); //tfidf value for each document(integer) and term(Byteref) pair.

    //variables in loop context
    BytesRef    term;                                                       //term as BytesRef
    int         noOfDocs;                                                   //number of documents (a term occours in)
    int         tf;                                                         //term frequency (of a term in a doc)
    double      idf;                                                        //inverse document frequency (of a term in a doc)
    double      tfidf;                                                      //term frequency - inverse document frequency value (of a term in a doc)
    Terms       termVector;                                                 //all terms of current doc in current field
    TermsEnum   termsEnum;                                                  //iterator for terms
    DocsEnum    docsEnum;                                                   //iterator for documents (of current term)

    List<Integer> docIds = getDocIds(totalNoOfDocs);                        //get internal documentIds of documents

    try {
        for(int doc : docIds){
            termVector  = reader.getTermVector(doc, field);                 //get termvector for document
            termsEnum   = termVector.iterator(null);                        //get iterator of termvector to iterate over terms


            while((term = termsEnum.next()) != null){                       //iterate of terms

                    noOfDocs = termsEnum.docFreq();                         //add no of docs the term occurs in to list

                    docsEnum = termsEnum.docs(null, null);                  //get document iterator for this term (all documents the term occours in)
                    while((doc = docsEnum.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS){ //iterate over documents - computation of all tf-idf values for this term
                        tf      = docsEnum.freq();                          //get termfrequency of current term in current doc
                        idf     = Math.log((double)totalNoOfDocs / (double)noOfDocs); //calculate idf
                        tfidf   = (double) tf * idf;                        //caculate tfidf
                        tfidfPerDocAndTerm.put(doc, term, tfidf);           //add tf-idf value to matrix

                    }
            }
        }

    } catch (IOException ex) {
        Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
    }   
    return tfidfPerDocAndTerm;
}

問題は次のとおりです。 noOfDocs = termsEnum.docFreq(); 常に 1 を返します。明らかに、複数のドキュメントに出現する用語があります(「用語」を印刷して手動でチェックしました)。

また、docsEnum を次のように取得することもわかりました。 docsEnum = termsEnum.docs(null, null); には常に 1 つのドキュメント (ドキュメント 0) のみが含まれます。

インデックスを作成するときは、ストップ ワード リストを備えた標準のアナライザーを使用したため、すべての用語が小文字になっています。

だから私の問題は何ですか?:/

ご協力いただきありがとうございます!

4

2 に答える 2

0

実際には、BytesRef タイプであるタームは、タームセナムの代わりにループしていますが、残念ながら、BytesRef は freq() または docfreq() と呼ばれるメソッドをサポートしていません。

于 2013-10-30T06:19:57.067 に答える
0

確かに、列挙子は常に 1 を返します。ただし、次を使用して正しい値を取得できますCollectionStatistics

DefaultSimilarity similarity = new DefaultSimilarity();

IndexReader reader = searcher.getIndexReader();
IndexReaderContext context = searcher.getTopReaderContext();
CollectionStatistics collectionStats = searcher.collectionStatistics(FIELD);
long totalDocCount = collectionStats.docCount();

Terms termVector = reader.getTermVector(docId, FIELD);
TermsEnum iterator = termVector.iterator(null);

while (true) {
    BytesRef ref = iterator.next();
    if (ref == null) {
        break;
    }

    long termFreq = iterator.totalTermFreq();
    float tf = similarity.tf(termFreq);

    Term term = new Term(FIELD, ref);
    TermContext termContext = TermContext.build(context, term);

    TermStatistics termStats = searcher.termStatistics(term, termContext);
    long docFreq = termStats.docFreq();
    float idf = similarity.idf(docFreq, totalDocCount);

    // do something with tf and idf
}

これが機能するには、用語ベクトルをインデックスに保存する必要があることに注意してください。

于 2016-03-14T16:57:20.133 に答える