使用Mahout搭建推荐系统之入门篇2-玩转你的数据1

4 篇文章 0 订阅
4 篇文章 0 订阅

原始地址:http://my.oschina.net/Cfreedom/blog/173635





用意: 搞推荐系统或者数据挖掘的, 对数据要绝对的敏感和熟悉, 并且热爱你的数据. 分析数据既要用统计分析那一套,又要熟悉业务发掘有趣的特征(feature). 后者有意思的多,但是因为我业务做的不多,还不太熟悉, 跪求大牛们分析业务经历. 听豆瓣上的大神"懒惰啊我"说过,有一个Nokia的比赛,有一个团队直接用陀螺仪参数就发现了性别分布,因为男生手机都放在口袋里, 而女生往往放在包里面. 不知道记错没有. 

下面主要讲些统计分析或者简单的内容分析, 说说我自己的总结, 这个话题以后可以常说. 

这部分不涉及Mahout的内容,主要是使用Python和Linux命令简单处理数据. 不感兴趣的朋友可以直接跳到最后面看看一些不错的数据集推荐. 

一. 前期数据分析的三个阶段

1. 打开你的数据,读懂每一行的含义 

2. 统计你的数据, 用python\excel pivot table\R\SPSS等都可以, 考虑到复用性建议写代码 

    数据的行数

    item和user的数量

    rate的评分方式,是boolean还是1-5分或者其它.

    数据稀疏还是稠密 sparse or dense 

3. 找到合适的存储方式存储,DenseVector还是SparseVector 

二. 数据分析实例

   现在国内的数据还比较少, 感谢下百度,提供了一些不错的数据. 

    首先来看一份国内的数据 

    百度举办的电影推荐系统算法创新大赛提供的用户数据. http://pan.baidu.com/s/1y15w4

1. 读懂你的数据, 知道每一行的含义.

一共有五个文件: 

movie_tag.txt 每行表示一个有效数据项, 下面类似. 每行由电影id以及tag的id, 用"\t"隔开; tag用","隔开. 

training_set.txt  每行表示用户id, 电影id, 评分, 用"\t"隔开. 

user_social.txt  每行表示用户id和用户关注的好友id集合; 好友id集合用","隔开. 

predict.txt 每行表示用户id和电影id 

user_history.txt 每行表示用户id和用户看过的电影id.  

数据如下图所示: head -n 2 *.txt


2. 数据统计 
主要参数: 
    用户个数\电影个数 
    每个用户平均电影个数,平均值,标准差\每个电影平均用户个数,平均值,标准差 
    评分的范围 

行数分析: wc -l *.txt


traning_set.txt数量为1262741行,predict.txt数量为314679行, 电影和用户数量未知,大概在万的级别,所以写些 
python代码简单分析一下. 100万用户级别的数据项使用python dict数据结构消耗内存在MByte级别且由于Python使用共享池共享int类,对象的冗余开销也不会暴涨, 普通PC既可以计算. 

Python数据分析

Python代码输出如下:

     用户(总数,平均值,标准差)=( 9722 129.884900226 223.778624272 )
     电影(总数,平均值,标准差)=( 7889 160.063506148 360.171047305 )
     评分范围=( 1.0 5.0 )

简要分析: 

    由数据可见,用户数量和电影数量在10000左右级别, 由于电影更少一些,使用item-based较合适;当然,由于用户和电影数量差距不大,最终还是要用实验来证明一下两者的性能优异. 

    另外:两者标准差分别为223与336可见, 基本可以判定数据为稀疏矩阵. 

[比较: 我使用了movieLens上的1M数据集进行对比, 运行结果如下]

http://www.grouplens.org/datasets/movielens/

用户(总数,平均值,标准差)=( 6040 165.597516556 192.731072529 )
电影(总数,平均值,标准差)=( 3706 269.889098759 383.996019743 )
评分范围=( 1.0 5.0 )

    评价: 平均值更大, 数据更加致密一些. 每个用户和电影的数据推荐效果应该也会更好一些. 

[吐槽点: 你给了id不给电影和标签的真实名称,看着一堆id, 推荐一大堆数字有个毛兴趣啊.  但是movieLens给出了电影名称,以后还是使用movieLens来作为预测数据更加有兴趣一些.]

Python代码如下:

?
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<strong> # -*- coding: utf-8 -*-
'''
Created on 2 Nov, 2013
 
@author: cool
'''
import math
 
#return user_num, movie_num, movie_mean, movie_variant
def countData(filename):
     user_count = {} #the number of movie about every user
     movie_count = {} #the number of user about every movie
     max = - 100
     min = 100
     
     #Assuming no duplicate data
     for line in open (filename):
         (user, movie, rating) = line.split( "\t" )
         #(user, movie, rating, xx) = line.split("::")
         rating = float (rating.replace(r "\r\r\n" , ""))
         #print rating
         
         user_count.setdefault(user, 0 )
         user_count[user] + = 1
         
         movie_count.setdefault(movie, 0 )
         movie_count[movie] + = 1
         
         if ( max < rating): max = rating
         if ( min > rating): min = rating
         
     uSum = sum ([user_count[user] for user in user_count])
     uSqSum = sum ([user_count[user] * * 2 for user in user_count])
     user_mean = float (uSum) / len (user_count)
     user_variant = math.sqrt( float (uSqSum) / len (user_count) - user_mean * * 2 )
     
     
     mSum = sum ([movie_count[movie] for movie in movie_count])
     mSqSum = sum ([movie_count[movie] * * 2 for movie in movie_count])
     movie_mean = float (mSum) / len (movie_count)
     movie_variant = math.sqrt( float (mSqSum) / len (movie_count) - movie_mean * * 2 )
     
     return len (user_count), len (movie_count), user_mean, user_variant, movie_mean, movie_variant, min , max
 
if __name__ = = '__main__' :
     (user_count, movie_count, user_mean, user_variant, movie_mean, movie_variant, min , max ) \
      = countData( "../data/baidu/training_set.txt" )
     
     #(user_count, movie_count, user_mean, user_variant, movie_mean, movie_variant, min, max) \
     # = countData("../data/baidu/ratings.dat")
      
     print "用户(总数,平均值,标准差)=(" , user_count, user_mean, user_variant, ")"
     print "电影(总数,平均值,标准差)=(" , movie_count, movie_mean, movie_variant, ")"
     print "评分范围=(" , min , max , ")" < / strong>

三. 不错的数据来源 

[1] GroupLens数据集(推荐相关:电影数据\书\笑话等):  http://grouplens.org/datasets/
[2] UCI数据集(数据丰富,无所不包)  http://archive.ics.uci.edu/ml/index.html
[3] Kaggle数据(数据丰富,规范,KDD2012是腾讯提供的微博数据)  http://www.kddcup2012.org/c/kddcup2012-track1
[4] Scikit-learn 提供的一些Python数据库,可以教你怎么玩转数据,我自己只玩过一点,以后得深挖一下. 此外这个Python机器学习库的文档堪称天人所写   http://scikit-learn.org/stable/datasets/


用意: 搞推荐系统或者数据挖掘的, 对数据要绝对的敏感和熟悉, 并且热爱你的数据. 分析数据既要用统计分析那一套,又要熟悉业务发掘有趣的特征(feature). 后者有意思的多,但是因为我业务做的不多,还不太熟悉, 跪求大牛们分析业务经历. 听豆瓣上的大神"懒惰啊我"说过,有一个Nokia的比赛,有一个团队直接用陀螺仪参数就发现了性别分布,因为男生手机都放在口袋里, 而女生往往放在包里面. 不知道记错没有. 

下面主要讲些统计分析或者简单的内容分析, 说说我自己的总结, 这个话题以后可以常说. 

这部分不涉及Mahout的内容,主要是使用Python和Linux命令简单处理数据. 不感兴趣的朋友可以直接跳到最后面看看一些不错的数据集推荐. 

一. 前期数据分析的三个阶段

1. 打开你的数据,读懂每一行的含义 

2. 统计你的数据, 用python\excel pivot table\R\SPSS等都可以, 考虑到复用性建议写代码 

    数据的行数

    item和user的数量

    rate的评分方式,是boolean还是1-5分或者其它.

    数据稀疏还是稠密 sparse or dense 

3. 找到合适的存储方式存储,DenseVector还是SparseVector 

二. 数据分析实例

   现在国内的数据还比较少, 感谢下百度,提供了一些不错的数据. 

    首先来看一份国内的数据 

    百度举办的电影推荐系统算法创新大赛提供的用户数据. http://pan.baidu.com/s/1y15w4

1. 读懂你的数据, 知道每一行的含义.

一共有五个文件: 

movie_tag.txt 每行表示一个有效数据项, 下面类似. 每行由电影id以及tag的id, 用"\t"隔开; tag用","隔开. 

training_set.txt  每行表示用户id, 电影id, 评分, 用"\t"隔开. 

user_social.txt  每行表示用户id和用户关注的好友id集合; 好友id集合用","隔开. 

predict.txt 每行表示用户id和电影id 

user_history.txt 每行表示用户id和用户看过的电影id.  

数据如下图所示: head -n 2 *.txt


2. 数据统计 
主要参数: 
    用户个数\电影个数 
    每个用户平均电影个数,平均值,标准差\每个电影平均用户个数,平均值,标准差 
    评分的范围 

行数分析: wc -l *.txt


traning_set.txt数量为1262741行,predict.txt数量为314679行, 电影和用户数量未知,大概在万的级别,所以写些 
python代码简单分析一下. 100万用户级别的数据项使用python dict数据结构消耗内存在MByte级别且由于Python使用共享池共享int类,对象的冗余开销也不会暴涨, 普通PC既可以计算. 

Python数据分析

Python代码输出如下:

     用户(总数,平均值,标准差)=( 9722 129.884900226 223.778624272 )
     电影(总数,平均值,标准差)=( 7889 160.063506148 360.171047305 )
     评分范围=( 1.0 5.0 )

简要分析: 

    由数据可见,用户数量和电影数量在10000左右级别, 由于电影更少一些,使用item-based较合适;当然,由于用户和电影数量差距不大,最终还是要用实验来证明一下两者的性能优异. 

    另外:两者标准差分别为223与336可见, 基本可以判定数据为稀疏矩阵. 

[比较: 我使用了movieLens上的1M数据集进行对比, 运行结果如下]

http://www.grouplens.org/datasets/movielens/

用户(总数,平均值,标准差)=( 6040 165.597516556 192.731072529 )
电影(总数,平均值,标准差)=( 3706 269.889098759 383.996019743 )
评分范围=( 1.0 5.0 )

    评价: 平均值更大, 数据更加致密一些. 每个用户和电影的数据推荐效果应该也会更好一些. 

[吐槽点: 你给了id不给电影和标签的真实名称,看着一堆id, 推荐一大堆数字有个毛兴趣啊.  但是movieLens给出了电影名称,以后还是使用movieLens来作为预测数据更加有兴趣一些.]

Python代码如下:

?
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<strong> # -*- coding: utf-8 -*-
'''
Created on 2 Nov, 2013
 
@author: cool
'''
import math
 
#return user_num, movie_num, movie_mean, movie_variant
def countData(filename):
     user_count = {} #the number of movie about every user
     movie_count = {} #the number of user about every movie
     max = - 100
     min = 100
     
     #Assuming no duplicate data
     for line in open (filename):
         (user, movie, rating) = line.split( "\t" )
         #(user, movie, rating, xx) = line.split("::")
         rating = float (rating.replace(r "\r\r\n" , ""))
         #print rating
         
         user_count.setdefault(user, 0 )
         user_count[user] + = 1
         
         movie_count.setdefault(movie, 0 )
         movie_count[movie] + = 1
         
         if ( max < rating): max = rating
         if ( min > rating): min = rating
         
     uSum = sum ([user_count[user] for user in user_count])
     uSqSum = sum ([user_count[user] * * 2 for user in user_count])
     user_mean = float (uSum) / len (user_count)
     user_variant = math.sqrt( float (uSqSum) / len (user_count) - user_mean * * 2 )
     
     
     mSum = sum ([movie_count[movie] for movie in movie_count])
     mSqSum = sum ([movie_count[movie] * * 2 for movie in movie_count])
     movie_mean = float (mSum) / len (movie_count)
     movie_variant = math.sqrt( float (mSqSum) / len (movie_count) - movie_mean * * 2 )
     
     return len (user_count), len (movie_count), user_mean, user_variant, movie_mean, movie_variant, min , max
 
if __name__ = = '__main__' :
     (user_count, movie_count, user_mean, user_variant, movie_mean, movie_variant, min , max ) \
      = countData( "../data/baidu/training_set.txt" )
     
     #(user_count, movie_count, user_mean, user_variant, movie_mean, movie_variant, min, max) \
     # = countData("../data/baidu/ratings.dat")
      
     print "用户(总数,平均值,标准差)=(" , user_count, user_mean, user_variant, ")"
     print "电影(总数,平均值,标准差)=(" , movie_count, movie_mean, movie_variant, ")"
     print "评分范围=(" , min , max , ")" < / strong>

三. 不错的数据来源 

[1] GroupLens数据集(推荐相关:电影数据\书\笑话等):  http://grouplens.org/datasets/
[2] UCI数据集(数据丰富,无所不包)  http://archive.ics.uci.edu/ml/index.html
[3] Kaggle数据(数据丰富,规范,KDD2012是腾讯提供的微博数据)  http://www.kddcup2012.org/c/kddcup2012-track1
[4] Scikit-learn 提供的一些Python数据库,可以教你怎么玩转数据,我自己只玩过一点,以后得深挖一下. 此外这个Python机器学习库的文档堪称天人所写   http://scikit-learn.org/stable/datasets/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值