通过引用Collaborative filtering in MySQL?,我创建了以下内容:
CREATE TABLE `ub` (
`user_id` int(11) NOT NULL,
`book_id` varchar(10) NOT NULL,
`rate` int(11) 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', '8'), (1, 'B', '7'), (1, 'C', '10');
insert into ub values (2, 'A', '8'), (2, 'B', '7'), (2, 'C', '10'), (2,'D', '8'), (2,'X', '7');
insert into ub values (3, 'X', '10'), (3, 'Y', '8'), (3, 'C', '10'), (3,'Z', '10');
insert into ub values (4, 'W', '8'), (4, 'Q', '8'), (4, 'C', '10'), (4,'Z', '8');
然后,我可以得到下表并了解它是如何工作的。
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 and target.rate= similar.rate
where target.user_id = 1
group by similar.user_id;
select * from ub_rank;
+---------+------+
| user_id | rank |
+---------+------+
| 2 | 3 |
| 3 | 1 |
| 4 | 1 |
+---------+------+
但是,在下面的代码之后我开始感到困惑。
select similar.rate, 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 and target.Rate= similar.Rate
where target.book_id is null
group by similar.book_id
order by total_rank desc, rate desc;
+---------+------------+
| book_id | total_rank |
+---------+------------+
| X | 4 |
| D | 3 |
| Z | 2 |
| Y | 1 |
| Q | 1 |
| W | 1 |
+---------+------------+
(1, 'A', '8'), (1, 'B', '7'), (1, 'C', '10');
(2, 'A', '8'), (2, 'B', '7'), (2, 'C', '10'), (2,'D', '8'), (2,'X', '7');
我想做的是,假设用户1和2具有相似的行为(在匹配评级之前选择A,B,C),因此我会向用户A推荐D,因为它具有更高的速率。
上面的代码似乎不这样做?因为,第一个排名是X.如何更改代码以实现上述目标?
或者,实际上现有方法对推荐更好/更准确吗?
答案 0 :(得分:2)
现有查询根据每本书的排名总值对结果进行排名,然后使用费率作为具有相同总排名的书籍的平局。 (此外,速率基本上是随机的,因为similar.rate不会聚合,分组或在功能上依赖于查询中的分组项。)
因此,X将排名高于D,因为它已被一个等级3的用户和一个等级1的用户选择,总排名为4,而D仅由一个等级3的用户选择
您可以更改查询以包含按排名加权的评级元素 - 例如:
select similar.book_id,
sum(ub_rank.rank) total_rank,
sum(ub_rank.rank*similar.rate) wtd_rate
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 and target.Rate= similar.Rate
where target.book_id is null
group by similar.book_id
order by wtd_rate desc, total_rank desc
- 虽然在这种情况下,这仍然会将X排名更高,因为它从等级3的用户得到7的评级加上等级1的用户的等级10,总得分为31,与D'相比总排名为24。
如果你希望X排名高于D,你需要决定你将使用哪个标准将X排在D之上。