2010-03-14 23 views
12

Estoy intentando para desarrollar un sitio que recomiende elementos (libros de texto) a los usuarios según sus preferencias. Hasta ahora, he leído la "Inteligencia Colectiva" de O'Reilly y muchos otros artículos en línea. Sin embargo, todos parecen tratar con instancias únicas de recomendación; por ejemplo, si te gusta el libro A, te puede interesar el libro B.¿Filtrado colaborativo en MySQL?

Lo que intento hacer es crear un conjunto de 'nodos de preferencia' para cada usuario en mi sitio. Digamos que a un usuario le gustan los libros A, B y C. Luego, cuando agreguen el libro D, no quiero que el sistema recomiende otros libros basados ​​únicamente en la experiencia de otros usuarios con el libro D. Quiero que el sistema busque un libro similar. 'preferencia-nodos' y recomendar libros basados ​​en eso.

He aquí un ejemplo de 4 nodos:

User1: 'book A'->'book B'->'book C' 
User2: 'book A'->'book B'->'book C'->'book D' 
user3: 'book X'->'book Y'->'book C'->'book Z' 
user4: 'book W'->'book Q'->'book C'->'book Z' 

lo tanto, un sistema de recomendación, tal como se describe en el material que he leído, lo recomiendo el libro de Z a Usuario 1, porque hay dos personas que se recomienda Z en conjunción con gusto C (es decir, Z pesa más que D), aunque un usuario con un 'nodo de preferencia' similar, Usuario2, estaría más capacitado para recomendar el libro D porque tiene un patrón de interés más similar.

¿Alguno de ustedes tiene alguna experiencia con este tipo de cosas? ¿Hay algunas cosas que debería intentar leer o existe algún sistema de código abierto para esto?

¡Gracias por su tiempo!

Pequeña edición: Creo que el algoritmo de last.fm está haciendo exactamente lo que mi sistema hace. Usar los árboles preferidos de las personas para recomendar música más personalmente a las personas. En lugar de decir "te pueden gustar B porque te gustó A"

Respuesta

32

Crear una tabla e insertar los datos de prueba:

CREATE TABLE `ub` (
    `user_id` int(11) NOT NULL, 
    `book_id` varchar(10) NOT NULL, 
    PRIMARY KEY (`user_id`,`book_id`), 
    UNIQUE KEY `book_id` (`book_id`,`user_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

insert into ub values (1, 'A'), (1, 'B'), (1, 'C'); 
insert into ub values (2, 'A'), (2, 'B'), (2, 'C'), (2,'D'); 
insert into ub values (3, 'X'), (3, 'Y'), (3, 'C'), (3,'Z'); 
insert into ub values (4, 'W'), (4, 'Q'), (4, 'C'), (4,'Z'); 

Una los datos de prueba sobre sí mismo por book_id, y crear una tabla temporal para contener cada user_id y el número de libros que tiene en común con el objetivo user_id:

create temporary table ub_rank as 
select similar.user_id,count(*) rank 
from ub target 
join ub similar on target.book_id= similar.book_id and target.user_id != similar.user_id 
where target.user_id = 1 
group by similar.user_id; 

select * from ub_rank; 
+---------+------+ 
| user_id | rank | 
+---------+------+ 
|  2 | 3 | 
|  3 | 1 | 
|  4 | 1 | 
+---------+------+ 
3 rows in set (0.00 sec) 

podemos ver que user_id tiene en común con 3 user_id 1, pero uSER_ID 3 y 4 user_id sólo tienen 1 cada uno.

A continuación, seleccione todos los libros que tengan los usuarios de la tabla temporal que no coincidan con los libros de ID del usuario de destino, y organícelos por rango. Tenga en cuenta que el mismo libro puede aparecer en diferentes listas de usuarios, por lo que sumamos las clasificaciones de cada libro para que los libros comunes obtengan una clasificación más alta.

select similar.book_id, sum(ub_rank.rank) total_rank 
from ub_rank 
join ub similar on ub_rank.user_id = similar.user_id 
left join ub target on target.user_id = 1 and target.book_id = similar.book_id 
where target.book_id is null 
group by similar.book_id 
order by total_rank desc; 

+---------+------------+ 
| book_id | total_rank | 
+---------+------------+ 
| D  |   3 | 
| Z  |   2 | 
| X  |   1 | 
| Y  |   1 | 
| Q  |   1 | 
| W  |   1 | 
+---------+------------+ 
6 rows in set (0.00 sec) 

libro Z apareció en dos listas de usuarios, y así se clasificó por encima de X, Y, Q, W, que sólo apareció en la lista de un usuario. El libro D fue mejor porque apareció en la lista de user_id 2, que tenía 3 elementos en común con el objetivo user_id 1.

+1

Guau, esta es una respuesta muy completa. ¡Muchas gracias! –

+0

esta es una respuesta increíble, he estado usando una versión modificada de esto para mi sitio y su funcionamiento tan bien. – Franco