Я пытаюсь изменить показатель сходства Lucene по умолчанию следующим образом. Предположим, что каждый документ, а также запрос состоят из уникальных слов. Наша пользовательская оценка сходства для запроса q и документа d должна быть com(d,q)/(size(d)+size(q))
. Где com(d,q)
— это количество терминов, которые появляются в обоих случаях (обратите внимание, что в запросе и в документе нет повторяющихся терминов). size(d)
и size(q)
— количество терминов в каждом из них. Мы используем WhiteSpaceAnalyzer
. Мы предполагаем, что частота терминов и документов равна 1, а термины не усиливаются.
Пользовательская оценка Apache Lucene
comment
А ваш вопрос?
- person mindas   schedule 24.04.2013
Ответы (1)
Чтобы применить собственную оценку, необходимо установить Similarity
вашей собственной реализации. Вы захотите обработать sive в методе calculateNorm, который сохраняется во время индексации. Остальное должен сделать coord
. Вы можете расширить TFIDFSimilarity
и получить множество вещей бесплатно, освободив вас от необходимости беспокоиться о настройке собственных SimScorer
и т.п. Вам просто нужно заглушить большую часть функциональности. Имейте в виду, что это будет дополнительный бит информации, хранящийся с каждым документом.
Итак, что-то вроде:
class MySimilarity extends TFIDFSimilarity {
// 1/size(d) where size(d) is the number of terms in the Field,
// rather than the Document (which doesn't really make sense)
computeNorm(FieldInvertState state, Norm norm) {
norm.setByte(encodeNorm(1 / state.getLength())); // encodeNorm loses a great deal of precision, FYI.
}
// 1/size(q)
float coord(int overlap, int maxOverlap) {
return 1 / maxOverlap;
}
float idf(long docFreq, long numDocs) {
return 1
}
float queryNorm(float sumOfSquaredWeights) {
return 1;
}
float scorePayload(int doc, int start, int end, BytesRef payload) {
return 1;
}
float sloppyFreq(int distance) {
return 1;
}
float tf(float freq) {
return 1;
}
float tf(int freq) {
return 1;
}
}
Который, я считаю, должен рассчитывать баллы в соответствии с:
(1 / size(q)) * ∑ (1 / size(d))
Который должен работать на то, что вы ищете.
У меня очень сильное ощущение, что вы выплескиваете ребенка вместе с водой из ванны.
person
femtoRgon
schedule
24.04.2013
Спасибо. Но это дает 1/(размер(q).размер(d))... Что, если мне нужно (размер(q)+размер(d))?
- person shahab_kamali; 24.04.2013
Другими словами, как я могу получить длину поля во время поиска?
- person shahab_kamali; 24.04.2013
Нет, вы правильно поняли фразу с первого раза. Мне уже кажется, что это проблема XY, давайте не будем сейчас переходить к Z. Вы сохраняете длину поля в норме, делая ее легко доступной в подобиях. Чтобы счетчик не умножал баллы по каждому совпадающему термину, вам может потребоваться реализовать сходство с нуля и реализовать подходящие SimScorers. ExactSimScorer — это, вероятно, то, что вам будет интересно изучить в первую очередь.
- person femtoRgon; 24.04.2013
Кажется, я понял, как хранить длину в норме, и при этом следить, чтобы она не влияла на счет. Но вот вопрос. ComputeNorm вызывается во время индексации с аргументом, являющимся экземпляром FieldInvertState. Как я могу прочитать норму во время поиска (скажем, в функции Coord)? Спасибо за помощь!
- person shahab_kamali; 25.04.2013
Вы можете получить нормы с помощью AtomicReader.normValues
- person femtoRgon; 25.04.2013
Любые предложения о том, как получить доступ к AtomicReader.normValues из координаты (int перекрытие, int maxOverlap)? ТИА
- person leoh; 10.07.2013