2010-03-14 3 views
12

Je suis en train d'essayer de développer un site qui recommande des articles (fx livres) aux utilisateurs en fonction de leurs préférences. Jusqu'à présent, j'ai lu "Collective Intelligence" d'O'Reilly et de nombreux autres articles en ligne. Cependant, ils semblent tous traiter des instances uniques de recommandation, par exemple si vous aimez le livre A, alors vous pourriez aimer le livre B.Filtrage collaboratif dans MySQL?

Ce que j'essaye de faire est de créer un ensemble de 'noeuds de préférence' pour chaque utilisateur sur mon site. Disons qu'un utilisateur aime le livre A, B et C. Puis, quand ils ajoutent le livre D, je ne veux pas que le système recommande d'autres livres basés uniquement sur d'autres utilisateurs avec le livre D. Je ne voulais pas que le système recherche "préférence-noeuds" et recommander des livres basés sur cela.

Voici un exemple de 4 nœuds:

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' 

Ainsi, un système de recommandation, tel que décrit dans le matériel que je l'ai lu, recommanderaient livre Z à l'utilisateur 1, parce qu'il ya deux personnes qui recommande Z la conjonction avec l'aimant C (ie Z pèse plus que D), même si un utilisateur avec un 'node-preference' similaire, User2, serait plus qualifié pour recommander le livre D parce qu'il a un modèle d'intérêt plus similaire.

Alors, est-ce que l'un d'entre vous a de l'expérience avec ce genre de chose? Y a-t-il des choses que je devrais essayer de lire ou existe-t-il des systèmes open source pour cela?

Merci pour votre temps!

Petite modification: Je pense que l'algorithme de last.fm fait exactement ce que mon système doit faire. Utiliser les arbres préférés des gens pour recommander la musique plus personnellement aux gens. Au lieu de simplement dire « vous B parce que vous avez aimé A »

Répondre

32

Créer une table et insérer les données de test:

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'); 

Joignez-vous aux données de test sur lui-même par book_id, et créer une table temporaire pour contenir chaque user_id et le nombre de livres qu'il a en commun avec le user_id cible:

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) 

Nous pouvons voir que user_id a 3 en commun avec user_id 1, mais id_utilisateur 3 et 4 user_id seulement 1 chacun.

Ensuite, sélectionnez tous les livres dont les utilisateurs de la table temporaire ont des livres qui ne correspondent pas aux livres de l'ID utilisateur_utilisateur, et organisez-les par rang. Notez que le même livre peut apparaître dans des listes d'utilisateurs différentes, donc nous additionnons les classements pour chaque livre afin que les livres communs obtiennent un meilleur classement.

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) 

Livre Z est apparu dans deux listes d'utilisateurs, et ainsi a été classé au-dessus X, Y, Q, W, qui est seulement apparu dans la liste d'un utilisateur. Book D a fait de son mieux parce qu'il est apparu dans la liste de user_id 2, qui avait 3 éléments en commun avec la cible user_id 1.

+1

Wow, c'est une réponse vraiment complète. Merci beaucoup! –

+0

c'est une réponse incroyable, j'ai utilisé une version modifiée de ceci pour mon site et son fonctionnement si bien. – Franco