【问题标题】:Collaborative filtering in MySQL?MySQL中的协同过滤?
【发布时间】:2011-01-27 07:17:00
【问题描述】:

我正在尝试开发一个网站,根据用户的喜好向他们推荐物品(外汇书籍)。到目前为止,我已经阅读了 O'Reilly 的“集体智慧”和许多其他在线文章。但是,它们似乎都处理单个推荐实例,例如,如果您喜欢 A 书,那么您可能会喜欢 B 书。

我要做的是为我网站上的每个用户创建一组“偏好节点”。假设用户喜欢书 A、B 和 C。然后,当他们添加书 D 时,我不希望系统仅根据其他用户对书 D 的体验来推荐其他书。我不希望系统查找类似的书'preference-nodes' 并以此为基础推荐书籍。

以下是 4 个节点的示例:

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'

因此,如我阅读过的材料中所述,推荐系统会向用户 1 推荐图书 Z,因为有两个人推荐 Z 与喜欢 C(即 Z 比 D 重),甚至尽管具有相似“偏好节点”的用户 User2 更有资格推荐书籍 D,因为他的兴趣模式更相似。

那么你们中有人有过这种事情的经验吗?是否有一些我应该尝试阅读的东西,或者是否存在任何开源系统?

感谢您的宝贵时间!

小编辑: 我认为 last.fm 的算法正在做我的系统要做的事情。使用人们的偏好树更个性化地向人们推荐音乐。而不是仅仅说“你可能喜欢 B,因为你喜欢 A”

【问题讨论】:

    标签: mysql collaborative-filtering


    【解决方案1】:

    创建表并插入测试数据:

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

    通过 book_id 将测试数据加入自身,并创建一个临时表来保存每个 user_id 以及它与目标 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)
    

    我们可以看到 user_id 和 user_id 1 共有 3 个,但是 user_id 3 和 user_id 4 各只有 1 个。

    接下来,选择临时表中用户拥有的所有与目标user_id的书籍不匹配的书籍,并按排名排列。请注意,同一本书可能会出现在不同用户的列表中,因此我们将每本书的排名求和,以便普通书获得更高的排名。

    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)
    

    图书 Z 出现在两个用户列表中,因此排名高于仅出现在一个用户列表中的 X、Y、Q、W。 Book D 表现最好,因为它出现在 user_id 2 的列表中,该列表与目标 user_id 1 有 3 个共同点。

    【讨论】:

    • 哇,这是一个非常全面的回应。非常感谢!
    • 这是一个令人难以置信的答案,我的网站一直在使用它的修改版本,并且运行良好。
    • 这对大型数据集的表现如何?
    猜你喜欢
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多