2012-02-03 18 views
5

Me interesan las posibles maneras de modelar el algoritmo de similitud del coseno utilizando Solr. Tengo elementos a los que se les asigna un vector, por ejemplo:¿Es posible modelar la similitud del coseno en Solr/Lucene?

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] } 
] 

Y un vector de búsqueda al que los demás deben clasificarse.

Actualmente estoy modelando esto en ruby ​​pasando todos los elementos y asignándoles un rango contra el vector de entrada. Aquí está la implementación de similitud del coseno que estoy usando:

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 

Entonces, para obtener una lista clasificada me gustaría hacer algo como lo siguiente:

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 

No sé lo suficiente sobre Solr para saber cómo esto sería modelado o incluso si puede, pero pensé que lo tiraría allí.

+0

http://stackoverflow.com/a/1849270/272861 – Mikos

Respuesta

1

Lucene ya usa un modelo de similitud de coseno, por lo que la verdadera pregunta es: ¿puedes mapear tus vectores en los vectores de Lucene? ¿Y puedes eliminar la norma, etc. que Lucene hace y que no quieres?

Siempre puede escribir sus propias funciones de puntuación y análisis, por lo que si está dispuesto a hacer alguna codificación, la respuesta es un claro "sí". Sin embargo, esto podría requerir más trabajo del que usted desea.

Para una opción que puede obtener parte del camino pero no requiere ninguna codificación: traducir cada dimensión en la palabra "dim_n" y repetirla (o aumentarla) cuantas veces sea la magnitud del vector en esa dimensión . Por ejemplo:

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

Si sus vectores son todas de aproximadamente el mismo tamaño y distribuido uniformemente a través de las dimensiones, esto podría ser una muy buena aproximación.

Si nos contas más sobre el problema (por ejemplo, si realmente necesitas darles vectores de Lucene como entrada o puedes darle un mensaje de texto?), Podremos encontrar mejores soluciones.

+0

Definitivamente necesito darle vectores, aunque podría ver algo como el enfoque de traducción de texto anterior. No me importa hacer una codificación, pero estoy en una plataforma de ruby ​​y realmente solo tengo Solr a mi disposición, por lo que debe ser algo que pueda expresar a través de la API de Solr. –

+0

Bueno, eche un vistazo a la [fórmula de puntuación] de Lucene (http://lucene.apache.org/java/3_0_0/api/core/org/apache/lucene/search/Similarity.html) y decida si el método de texto acércate lo suficiente. Solr te permite [escribir consultas de función] (http://wiki.apache.org/solr/FunctionQuery) sin cambiar la fuente, que es otra opción. – Xodarap

Cuestiones relacionadas