Cálculo TFIDF en Lucene mientras se restringe el rango de tiempo

Tengo un montón de documentos en diferentes tiempos. Ahora necesito calcular el tfidf para documentos en un período de tiempo. Lo siguiente es lo que voy a hacer, por ejemplo:

Tengo un millón de documentos de texto para un año, tomaré los documentos en un mes como corpus. Quiero calcular el tfidf para cada mes, es decir, calcular la frecuencia del término en un mes, y multiplicar la frecuencia inversa del documento en el mes restante.

Los datos (texto, hora, etc.) se indexan utilizando lucena, solo me preguntaba si lucene podría facilitar el cálculo de tal escenario. Sé que Lucene puede ayudarme a obtener el término frecuencia y la frecuencia del documento, pero ¿hay alguna API para restringir el intervalo de tiempo para calculo?

Muchas gracias.

preguntado el 02 de diciembre de 13 a las 17:12

1 Respuestas

Tengo una solución para esto usando Lucene.Net 3.0.3 y payloads. No estoy seguro de si esta es la mejor manera de lograr esto utilizando la versión de Java, que actualmente está un poco por delante del puerto .net.

Funciona mediante la asignación de una carga útil, una matriz de bytes personalizada, a los términos que deben calificarse de forma personalizada y una similitud personalizada que anula ScorePayload para analizar la matriz de bytes para realizar un filtrado personalizado. (esto requeriría una consulta que llame a este método, como PayloadTermQuery).

Este código de ejemplo altamente artificial calificará el término en función de (id % 3). (Los múltiplos de tres se puntúan como cero). Puede usar esto combinado con un PositiveScoresOnlyCollector para ignorar las coincidencias que reciben una puntuación de cero.

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);
    }
}

Respondido el 02 de diciembre de 13 a las 20:12

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.