是否可以在Solr/Lucene中模拟余弦相似度?

JC *_*bbs 5 ruby lucene solr cosine-similarity

我对使用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] }
]
Run Code Online (Sandbox Code Playgroud)

以及其他人需要排名的搜索向量.

目前,我通过遍历所有项目并在输入向量上为它们分配排名来在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
Run Code Online (Sandbox Code Playgroud)

然后,为了获得排名列表,我将执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)

我不太了解Solr知道如何建模,或者即使它可以,但我想我会把它扔出去.

Xod*_*rap 1

Lucene 已经使用了余弦相似度模型,所以真正的问题是:你能将你的向量映射到 Lucene 的向量中吗?你能删除 Lucene 所做的你不想要的规范等吗?

您始终可以编写自己的评分和分析函数,因此如果您愿意进行一些编码,答案是明确的“是”。但这可能需要比您想要的更多的工作。

对于可能会帮助您完成但不需要任何编码的选项:将每个维度翻译为单词“dim_n”并重复它(或增强它),无论向量在该维度中的大小多少次。例如:

[1,2,0,1] ==> "dim_1 dim_2 dim_2 dim_4"
Run Code Online (Sandbox Code Playgroud)

如果您的向量大小大致相同并且在维度上均匀分布,那么这可能是一个非常好的近似值。

如果您告诉我们有关该问题的更多信息(例如,您是否真的需要提供 Lucene 向量作为输入,或者您可以为其提供文本吗?),我们也许能够找到更好的解决方案。