Пользовательская оценка Apache Lucene

Я пытаюсь изменить показатель сходства Lucene по умолчанию следующим образом. Предположим, что каждый документ, а также запрос состоят из уникальных слов. Наша пользовательская оценка сходства для запроса q и документа d должна быть com(d,q)/(size(d)+size(q)). Где com(d,q) — это количество терминов, которые появляются в обоих случаях (обратите внимание, что в запросе и в документе нет повторяющихся терминов). size(d) и size(q) — количество терминов в каждом из них. Мы используем WhiteSpaceAnalyzer. Мы предполагаем, что частота терминов и документов равна 1, а термины не усиливаются.


person shahab_kamali    schedule 24.04.2013    source источник
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
comment
Спасибо. Но это дает 1/(размер(q).размер(d))... Что, если мне нужно (размер(q)+размер(d))? - person shahab_kamali; 24.04.2013
comment
Другими словами, как я могу получить длину поля во время поиска? - person shahab_kamali; 24.04.2013
comment
Нет, вы правильно поняли фразу с первого раза. Мне уже кажется, что это проблема XY, давайте не будем сейчас переходить к Z. Вы сохраняете длину поля в норме, делая ее легко доступной в подобиях. Чтобы счетчик не умножал баллы по каждому совпадающему термину, вам может потребоваться реализовать сходство с нуля и реализовать подходящие SimScorers. ExactSimScorer — это, вероятно, то, что вам будет интересно изучить в первую очередь. - person femtoRgon; 24.04.2013
comment
Кажется, я понял, как хранить длину в норме, и при этом следить, чтобы она не влияла на счет. Но вот вопрос. ComputeNorm вызывается во время индексации с аргументом, являющимся экземпляром FieldInvertState. Как я могу прочитать норму во время поиска (скажем, в функции Coord)? Спасибо за помощь! - person shahab_kamali; 25.04.2013
comment
Вы можете получить нормы с помощью AtomicReader.normValues - person femtoRgon; 25.04.2013
comment
Любые предложения о том, как получить доступ к AtomicReader.normValues ​​​​из координаты (int перекрытие, int maxOverlap)? ТИА - person leoh; 10.07.2013