Можно ли смоделировать косинусное сходство в Solr / Lucene? - PullRequest
5 голосов
/ 03 февраля 2012

Меня интересуют возможные способы моделирования алгоритма подобия косинуса с использованием Solr. У меня есть предметы, которым присвоен вектор, например:

items = [
  { id: 1, vector: [0,0,0,2,3,0,0] },
  { id: 2, vector: [0,1,0,1,5,0,0] },
  { id: 3, vector: [2,3,0,0,0,1,0] },
  { id: 4, vector: [1,2,4,6,5,0,0] }
]

И вектор поиска, к которому нужно причислить других.

В настоящее время я моделирую это в ruby, перебирая все элементы и присваивая им ранг по отношению к входному вектору. Вот реализация косинусного сходства, которую я использую:

module SimilarityCalculator

  def self.get_similarity(vector1, vector2)
    dp = dot_product(vector1, vector2)
    nm = normalize(vector1) * normalize(vector2)
    dp / nm
  end

  private

  def self.dot_product(vector1, vector2)
    sum = 0.0
    vector1.each_with_index { |val, i| sum += val * vector2[i] }
    sum
  end

  def self.normalize(vector)
    Math.sqrt(vector.inject(0.0) { |m,o| m += o**2 })
  end

end

Затем, чтобы получить ранжированный список, я бы сделал что-то вроде следующего:

ranked = []
search_vector = [1,0,0,3,5,0,0]
items.each do |item|
  rank = SimilarityCalculator.get_similarity(search_vector, item.vector)
  { id: item.id, rank: rank }
end

Я не знаю достаточно о Solr, чтобы знать, как это будет смоделировано или даже если это возможно, но я подумал, что выкину это там.

1 Ответ

1 голос
/ 03 февраля 2012

Lucene уже использует модель сходства косинусов, поэтому реальный вопрос: вы можете отобразить свои векторы в векторы Lucene? И можете ли вы удалить нормирование и т. Д., Что делает Lucene, чего вы не хотите?

Вы всегда можете написать свои собственные функции оценки и анализа, так что, если вы хотите заняться кодированием, ответ будет ясным «да». Это может потребовать больше работы, чем вы хотите.

Для опции, которая может помочь вам в этом, но не требует никакого кодирования: переведите каждое измерение в слово «dim_n» и повторите его (или увеличьте), сколько бы раз ни было значение вектора в этом измерении. Например:

[1,2,0,1] ==> "dim_1 dim_2 dim_2 dim_4"

Если ваши векторы примерно одинакового размера и равномерно распределены по измерениям, это может быть очень хорошим приближением.

Если вы расскажете нам больше о проблеме (например, действительно ли вам нужно указывать векторы Lucene в качестве входных данных или вы можете дать им текст?), Мы сможем найти лучшие решения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...