我在不同的时间里收到了很多文件。 现在我需要在一段时间内计算文档的tfidf。 以下是我要做的事情,例如:
我有一百万份文本文件一年,我将在一个月内将这些文件作为语料库。 我想计算每个月的tfidf,即计算一个月内的术语频率,并将剩余月份的逆文档频率乘以。
使用 lucene 索引数据(文本,时间等),我只是想知道lucene是否可以促进这种情况的计算 我知道Lucene可以帮助我获得术语频率和文档频率,但是有没有用于限制计算的时间范围的API?
非常感谢。
答案 0 :(得分:1)
我已经使用Lucene.Net 3.0.3和有效负载获得了解决方案。我不确定这是否是使用java-version实现此目的的最佳方法,该版本目前比.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);
}
}