Class MoreLikeThis
Generate "more like this" similarity queries. Based on this mail:
Lucene does let you access the document frequency of terms, with DocFreq(Term).
Term frequencies can be computed by re-tokenizing the text, which, for a single document,
is usually fast enough. But looking up the DocFreq(Term) of every term in the document is
probably too slow.
You can use some heuristics to prune the set of terms, to avoid calling DocFreq(Term) too much,
or at all. Since you're trying to maximize a tf*idf score, you're probably most interested
in terms with a high tf. Choosing a tf threshold even as low as two or three will radically
reduce the number of terms under consideration. Another heuristic is that terms with a
high idf (i.e., a low df) tend to be longer. So you could threshold the terms by the
number of characters, not selecting anything less than, e.g., six or seven characters.
With these sorts of heuristics you can usually find small set of, e.g., ten or fewer terms
that do a pretty good job of characterizing a document.
It all depends on what you're trying to do. If you're trying to eek out that last percent
of precision and recall regardless of computational difficulty so that you can win a TREC
competition, then the techniques I mention above are useless. But if you're trying to
provide a "more like this" button on a search results page that does a decent job and has
good performance, such techniques might be useful.
An efficient, effective "more-like-this" query generator would be a great contribution, if
anyone's interested. I'd imagine that it would take a Reader or a String (the document's
text), analyzer Analyzer, and return a set of representative terms using heuristics like those
above. The frequency and length thresholds could be parameters, etc.
Doug
Initial Usage
This class has lots of options to try to make it efficient and flexible. The simplest possible usage is as follows. The bold fragment is specific to this class.
IndexReader ir = ...
IndexSearcher is = ...
MoreLikeThis mlt = new MoreLikeThis(ir);
TextReader target = ... // orig source of doc you want to find similarities to
Query query = mlt.Like(target);
Hits hits = is.Search(query);
// now the usual iteration thru 'hits' - the only thing to watch for is to make sure
//you ignore the doc if it matches your 'target' document, as it should be similar to itself
Thus you:
- do your normal, Lucene setup for searching,
- create a MoreLikeThis,
- get the text of the doc you want to find similarities to
- then call one of the Like(TextReader, String) calls to generate a similarity query
- call the searcher to find the similar docs
More Advanced Usage
You may want to use the setter for FieldNames so you can examine multiple fields (e.g. body and title) for similarity.
Depending on the size of your index and the size and makeup of your documents you may want to call the other set methods to control how the similarity queries are generated:
Inheritance
Assembly: DistributedLucene.Net.Queries.dll
Syntax
public sealed class MoreLikeThis : object
Remarks
Changes: Mark Harwood 29/02/04 Some bugfixing, some refactoring, some optimisation.
- bugfix: retrieveTerms(int docNum) was not working for indexes without a termvector -added missing code
- bugfix: No significant terms being created for fields with a termvector - because was only counting one occurrence per term/field pair in calculations(ie not including frequency info from TermVector)
- refactor: moved common code into isNoiseWord()
- optimise: when no termvector support available - used maxNumTermsParsed to limit amount of tokenization
Constructors
Name | Description |
---|---|
MoreLikeThis(IndexReader) | Constructor requiring an IndexReader. |
MoreLikeThis(IndexReader, TFIDFSimilarity) |
Fields
Name | Description |
---|---|
DEFAULT_BOOST | Boost terms in query based on score. |
DEFAULT_FIELD_NAMES | Default field names. Null is used to specify that the field names should be looked up at runtime from the provided reader. |
DEFAULT_MAX_DOC_FREQ | Ignore words which occur in more than this many docs. |
DEFAULT_MAX_NUM_TOKENS_PARSED | Default maximum number of tokens to parse in each example doc field that is not stored with TermVector support. |
DEFAULT_MAX_QUERY_TERMS | Return a Query with no more than this many terms. |
DEFAULT_MAX_WORD_LENGTH | Ignore words greater than this length or if 0 then this has no effect. |
DEFAULT_MIN_DOC_FREQ | Ignore words which do not occur in at least this many docs. |
DEFAULT_MIN_TERM_FREQ | Ignore terms with less than this frequency in the source doc. |
DEFAULT_MIN_WORD_LENGTH | Ignore words less than this length or if 0 then this has no effect. |
DEFAULT_STOP_WORDS | Default set of stopwords. If null means to allow stop words. |
Properties
Name | Description |
---|---|
Analyzer | Gets or Sets an analyzer that will be used to parse source doc with. The default analyzer is not set. An analyzer is not required for generating a query with the Like(Int32) method, all other 'like' methods require an analyzer. |
ApplyBoost | Gets or Sets whether to boost terms in query based on "score" or not. The default is DEFAULT_BOOST. |
BoostFactor | Gets or Sets the boost factor used when boosting terms |
FieldNames | Gets or Sets the field names that will be used when generating the 'More Like This' query. The default field names that will be used is DEFAULT_FIELD_NAMES. Set this to null for the field names to be determined at runtime from the IndexReader provided in the constructor. |
MaxDocFreq | Gets or Sets the maximum frequency in which words may still appear. Words that appear in more than this many docs will be ignored. The default frequency is DEFAULT_MAX_DOC_FREQ. |
MaxNumTokensParsed | |
MaxQueryTerms | Gets or Sets the maximum number of query terms that will be included in any generated query. The default is DEFAULT_MAX_QUERY_TERMS. |
MaxWordLen | Gets or Sets the maximum word length above which words will be ignored. Set this to 0 for no maximum word length. The default is DEFAULT_MAX_WORD_LENGTH. |
MinDocFreq | Gets or Sets the frequency at which words will be ignored which do not occur in at least this many docs. The default frequency is DEFAULT_MIN_DOC_FREQ. |
MinTermFreq | Gets or Sets the frequency below which terms will be ignored in the source doc. The default frequency is the DEFAULT_MIN_TERM_FREQ. |
MinWordLen | Gets or Sets the minimum word length below which words will be ignored. Set this to 0 for no minimum word length. The default is DEFAULT_MIN_WORD_LENGTH. |
Similarity | For idf() calculations. |
StopWords | Gets or Sets the set of stopwords. Any word in this set is considered "uninteresting" and ignored. Even if your Analyzer allows stopwords, you might want to tell the MoreLikeThis code to ignore them, as for the purposes of document similarity it seems reasonable to assume that "a stop word is never interesting". |
Methods
Name | Description |
---|---|
DescribeParams() | Describe the parameters that control how the "more like this" query is formed. |
Like(Int32) | Return a query that will return docs like the passed lucene document ID. |
Like(TextReader, String) | Return a query that will return docs like the passed |
RetrieveInterestingTerms(Int32) | |
RetrieveInterestingTerms(TextReader, String) | Convenience routine to make it easy to return the most interesting words in a document. More advanced users will call RetrieveTerms(TextReader, String) directly. |
RetrieveTerms(Int32) | Find words for a more-like-this query former. |
RetrieveTerms(TextReader, String) | Find words for a more-like-this query former. The result is a priority queue of arrays with one entry for every word in the document. Each array has 6 elements. The elements are:
|
SetMaxDocFreqPct(Int32) | Set the maximum percentage in which words may still appear. Words that appear in more than this many percent of all docs will be ignored. |