当前位置: 首页 > 推荐系统 > 正文

推荐系统实例(二)

1 星2 星3 星4 星5 星 (1 次投票, 评分: 5.00, 总分: 5)
Loading ... Loading ...
baidu_share

接上一篇文章推荐系统实例(一)

4.为了加深理解,看下面的sql语句
对上述3中的sql语句作了一下改进,select改成了a.*,b.*,去掉了group by a.item_id,b.item_id,其它的是一样的。

看了下面sql语句的输出结果以后,相信对协同过滤算法的理解又加深了一步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
a.select a.*,b.* from oso_user_ratings a,oso_user_ratings b where a.item_id = '1' and b.item_id != a.item_id and a.user_id=b.user_id
 
user_id item_id rating user_id item_id rating
111    1    1.0000    111    2    0.2000(用户111听了歌曲12)
112    1    1.0000    112    2    0.5000(用户112听了歌曲12)
113    1    0.3300    113    2    0.6600(用户113听了歌曲12)
113    1    0.3300    113    3    1.0000(用户113听了歌曲13)
 
b.SELECT a.*,b.* FROM oso_user_ratings a,oso_user_ratings b WHERE a.item_id = '2' AND b.item_id != a.item_id AND a.user_id=b.user_id
 
user_id    item_id    rating    user_id    item_id    rating
111    2    0.2000    111    1    1.0000(用户111听了歌曲21)
113    2    0.6600    113    1    0.3300(用户113听了歌曲21)
113    2    0.6600    113    3    1.0000(用户113听了歌曲23)
112    2    0.5000    112    1    1.0000(用户112听了歌曲21)
 
c.SELECT a.*,b.* FROM oso_user_ratings a,oso_user_ratings b WHERE a.item_id = '3' AND b.item_id != a.item_id AND a.user_id=b.user_id
 
user_id    item_id    rating    user_id    item_id    rating
113    3    1.0000    113    1    0.3300(用户113听了歌曲31)
113    3    1.0000    113    2    0.6600(用户111听了歌曲32)

有了上面的数据,实现电子商务中的买了商品xxx的用户也买了商品xxx,浏览了商品xxx的用户也浏览了商品xxx的功能就比较容易了,此时我们可以把item_id理解为商品的id:

1.当用户购买了商品1时,可以向他(她)提示,买了商品1的用户也买了商品3,2。
2.当用户在浏览商品2时,可以向他(她)提示,浏览了商品2的用户也浏览了商品3,1

5.根据item id给用户推荐指定的信息(基于item_id的协同过滤)
按照item_id2分组,按sum(rating/times)进行顺排,取前面的几个值。

根据插入到表oso_slope_one中时的sql语句,因为已经按照两个item_id进行分组了(group by a.item_id,b.item_id),item_id1与item_id2相同时在表oso_slope_one中只可能存在一条记录的,item_id1相同的行中应该是不可能出现item_id2相同的,所以下面的sql语句加不加group by item_id2结果都是一样的。

2010-2-26 下面是我的测试,下面两个sql语句返回的结果是完全一样的。

1
2
3
select item_id2 from oso_slope_one where item_id1 = '272987' group by item_id2 order by sum(rating/times) limit 10;
 
select item_id2 from oso_slope_one where item_id1 = '272987' order by rating/times limit 10;

将item_id1换为264315后就不一样了(主要是当item_id1为264315时,有两行rating/times的值均为-0.97140000),奇怪,最后知道为什么了,原因如下:

1.select中如果有两列(item_id2,rating/times),则结果及排序完全一样(有group by及没有group by的情况)。
2.select中如果只有一列item_id2,则结果一样,排序有两个不一样(有group by及没有group by的情况
主要就是rating/times相同的两条记录排序不一样,其它的均一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
select item_id2,sum(rating/times) from oso_slope_one where item_id1 = '264315' group by item_id2 order by sum(rating/times) limit 10;
 
7698    -0.99390000
37836    -0.98680000
5156    -0.97830000
3791    -0.97140000
6195    -0.97140000
43160    -0.96970000
19803    -0.96870000
16356    -0.96380000
133117    -0.96380000
60923    -0.95660000
 
select item_id2,rating/times from oso_slope_one where item_id1 = '264315' order by rating/times limit 10;
 
7698    -0.99390000
37836    -0.98680000
5156    -0.97830000
3791    -0.97140000
6195    -0.97140000
43160    -0.96970000
19803    -0.96870000
16356    -0.96380000
133117    -0.96380000
60923    -0.95660000
 
public function getRecommendedItemsById($itemId, $limit = 20)
    {
        $sql = 'select item_id2 from oso_slope_one where item_id1 = '
             . $itemId
             . ' group by item_id2 order by sum(rating/times) limit '
             . $limit;
        return  $this->_db->fetchCol($sql);
    }

分别根据item_id为1,2,3时的推荐结果,sum(raging/times)的值越小的越排在前面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT item_id2 FROM oso_slope_one WHERE item_id1 = '1' GROUP BY item_id2 ORDER BY SUM(rating/times) LIMIT 10;
 
item_id2
3
2
 
SELECT item_id2 FROM oso_slope_one WHERE item_id1 = '2' GROUP BY item_id2 ORDER BY SUM(rating/times) LIMIT 10;
item_id2
3
1
 
SELECT item_id2 FROM oso_slope_one WHERE item_id1 = '3' GROUP BY item_id2 ORDER BY SUM(rating/times) LIMIT 10;
item_id2
2
1

6.基于用户的协同过滤
基于用户的协同过滤算法如下,经过项目中实际应用,发现按照基于用户的协同过滤得出来的结果不太准确,而且当用户数增多,用户听的歌曲越来越多的时候,直接读取数据库的效率非常低下,性能是一个非常大的问题。

比如有315813个音乐用户,表oso_user_ratings中的记录数为2316730,表oso_slope_one中的记录数为 58846482,二百多万条记录的表与五千多万条记录的表联合查询你想想效率能高吗?即使把这些数据库查询改成缓存来处理,代价也是非常高的,最重要的是推荐结果也不是很准,所以基于用户的协同不推荐使用。

本文固定链接: http://www.chepoo.com/recommendation-system-demo-two.html | IT技术精华网

推荐系统实例(二):等您坐沙发呢!

发表评论