Расчет TFIDF в Lucene при ограничении временного диапазона

У меня есть много документов в разное время. Теперь мне нужно рассчитать tfidf для документов за один период времени. Вот что я собираюсь сделать, например:

У меня есть миллион текстовых документов на один год, я возьму документы за один месяц как корпус. Я хочу рассчитать tfidf для каждого месяца, т. е. вычислить частоту термина за один месяц и умножить обратную частоту документа в оставшемся месяце.

Данные (текст, время и т. д.) индексируются с использованием lucene, мне просто интересно, может ли lucene облегчить расчет такого сценария. Я знаю, что Lucene может помочь мне получить частоту термина и документировать частоту, но есть ли какой-либо API для ограничения временного диапазона для расчета?

Большое спасибо.


person GodoorSun    schedule 02.12.2013    source источник


Ответы (1)


У меня есть решение для этого с использованием Lucene.Net 3.0.3 и полезной нагрузки. Я не уверен, что это лучший способ сделать это, используя java-версию, которая в настоящее время немного опережает порт .net.

Он работает путем назначения полезной нагрузки, пользовательского массива байтов терминам, которые должны быть оценены пользователем, и пользовательского сходства, которое переопределяет ScorePayload для анализа массива байтов для выполнения пользовательской фильтрации. (для этого потребуется запрос, вызывающий этот метод, например PayloadTermQuery).

Этот чрезвычайно надуманный пример кода будет оценивать термин на основе (id % 3). (Число, кратное трем, оценивается как ноль). Вы можете использовать это в сочетании с PositiveScoresOnlyCollector, чтобы игнорировать совпадения, получившие нулевой балл.

using System;
using System.IO;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Tokenattributes;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Search.Payloads;
using Lucene.Net.Store;

public static class Program {
    public static void Main() {
        var directory = new RAMDirectory();

        // Initialization; create 50 documents with payload
        var writer = new IndexWriter(directory, new KeywordAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED);
        for (var i = 0; i < 50; ++i) {
            AddDocument(writer, i, "lorem ipsum etc blah blah");
        }
        writer.Commit();

        var searcher = new IndexSearcher(directory, readOnly: true);
        searcher.Similarity = new ShazaamPayloadSimilarity();

        // The term we'll be looking for. This should match all documents.
        var term = new Term("Data", "lorem");
        var query = new PayloadTermQuery(term, new MaxPayloadFunction());
        var topDocs = searcher.Search(query, 40);

        // This is a bad example of a FieldCache usage.
        var iValues = FieldCache_Fields.DEFAULT.GetStrings(searcher.IndexReader, "Id");
        foreach (var scoreDoc in topDocs.ScoreDocs) {
            Console.WriteLine("Score: {0:0.0000}  i={1}", scoreDoc.Score, iValues[scoreDoc.Doc]);
        }

        Console.ReadLine();
    }

    public static void AddDocument(IndexWriter writer, Int32 id, String data) {
        var payload = BitConverter.GetBytes(id);
        var analyzer = new ShazaamPayloadAnalyzer(payload);
        var textReader = new StringReader(data);

        var document = new Document();
        document.Add(new Field("Id", id.ToString(), Field.Store.NO, Field.Index.NOT_ANALYZED));
        document.Add(new Field("Data", analyzer.TokenStream(null, textReader)));

        writer.AddDocument(document);
    }
}

public class ShazaamPayloadAnalyzer : Analyzer {
    private readonly Byte[] _value;

    public ShazaamPayloadAnalyzer(Byte[] value) {
        _value = value;
    }

    public override TokenStream TokenStream(String fieldName, TextReader reader) {
        TokenStream result = new WhitespaceTokenizer(reader);
        result = new ShazaamPayloadFilter(result, _value);
        return result;
    }
}

public class ShazaamPayloadFilter : TokenFilter {
    private readonly byte[] _payload;
    private readonly IPayloadAttribute _payloadAttr;

    public ShazaamPayloadFilter(TokenStream input, Byte[] payload)
        : base(input) {
        _payload = payload;
        _payloadAttr = AddAttribute<IPayloadAttribute>();
    }

    public override Boolean IncrementToken() {
        if (input.IncrementToken()) {
            _payloadAttr.Payload = new Payload(_payload);
            return true;
        }

        return false;
    }
}

public class ShazaamPayloadSimilarity : DefaultSimilarity {
    public override Single ScorePayload(Int32 docId, String fieldName, Int32 start, Int32 end, Byte[] payload, Int32 offset, Int32 length) {
        var originalValue = BitConverter.ToInt32(payload, startIndex: 0);

        // Advanced logic ahead!
        return (originalValue % 3);
    }
}
person sisve    schedule 02.12.2013