我对使用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知道如何建模,或者即使它可以,但我想我会把它扔出去。
答案 0 :(得分:1)
Lucene已经使用了余弦相似度模型,所以真正的问题是:你能将你的矢量映射到Lucene的矢量吗?你可以删除Lucene做的那些你不想要的规范等吗?
你总是可以编写自己的评分和分析功能,所以如果你愿意做一些编码,那么答案就是明确的"是"。这可能需要比你想要的更多的工作。
对于可能让您参与其中但不需要任何编码的选项:将每个维度转换为单词" dim_n"并重复它(或提升它),但是很多次是该维度中向量的大小。例如:
[1,2,0,1] ==> "dim_1 dim_2 dim_2 dim_4"
如果你的矢量大小大致相同且均匀分布在维度上,这可能是一个很好的近似值。
如果你告诉我们更多关于这个问题的信息(例如,你真的需要将Lucene向量作为输入,还是可以给它提供文本?)我们可以找到更好的解决方案。