基于Mahout的电影推荐系统

目录(?)[+] html

源代码下载地址:http://download.csdn.net/detail/huhui_bj/5248056

参考资料:

QQ:66781877

1 Mahout介绍

Apache Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地建立智能应用程序。经典算法包括聚类、分类、协同过滤、进化编程等等,而且,在 Mahout 中还加入了对Apache Hadoop的支持,使这些算法能够更高效的运行在云计算环境中。 java


2 环境部署

  • Ubuntu
  • JDK1.6.0_21
  • MySQL
  • apache-tomcat-6.0.35
  • mahout-0.3
  • MyEclipse 8.0

2.1 JDK1.6.0_21的安装

jdk的下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html我所用的版本是jdk-6u21-linux-i586.bin。
安装步骤:
1.打开终端,进入放置jdk安装文件的目录cd /home/huhui/develop


2.更改文件权限为可执行chmod +x jdk-6u21-linux-i586.bin


3.执行该文件,执行命令./jdk-6u21-linux-i586.bin


JDK自动安装到/home/huhui/develop/jdk1.6.0_21目录下。这个目录下,在终端输入java -version能够看到jdk的版本信息: node


4.安装完JDK以后,接下来须要配置环境变量,在终端中输入命令sudo gedit /etc/profile,此时会弹出以下对话框: mysql


在这个文档的末尾加入以下信息:
#set java environment
JAVA_HOME=/home/huhui/develop/jdk1.6.0_21
export JRE_HOME=/home/huhui/develop/jdk1.6.0_21/jre
export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
保存并关闭文件,至此,jdk的安装与配置就完成了。

2.2 MySQL的安装

MySQL的安装过程比较简单,在终端输入sudo apt-get install mysql-server my-client便可: linux

到这里,要求用户输入Y或者N,此时选择Y,会弹出一个界面,要求输入mysql的root的密码,这里必定输入,免得安装后再设密码了。 web


我习惯与使用可视化工具来操做MySQL数据库,因而我又安装了“MySQL Administrator”软件,这个是数据库管理软件,运行以下图所示:


2.3 Tomcat的安装

软件下载地址:http://archive.apache.org/dist/tomcat/tomcat-6/ 我下载的版本是apache-tomcat-6.0.35.tar.gz
1.解压文件
复制安装文件到hom/huhui/develop目录下,在终端输入sudo tar -zxvf apache-tomcat-6.0.35.tar.gz,将安装包解压至apache-tomcat-6.0.35目录下
2.配置startup.sh文件
在终端输入sudo gedit home/huhui/develop/apache-tomcat-6.0.35/bin/startup.sh
在startup.sh文件的末尾加入一下内容,加入的内容即为jdk的环境变量:
JAVA_HOME=/home/huhui/develop/jdk1.6.0_21
PATH=$JAVA_HOME/bin:$PATH  
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
TOMCAT_HOME=/home/huhui/develop/apache-tomcat-6.0.35
3.启动tomcat

进入/usr/local/apache-tomcat-6.0.35/bin/目录,输入sudo ./startup.sh,若出现下图信息,则说明tomcat安装成功。 算法

此时在浏览器中输入http://localhost:8080/将出现tomcat的欢迎界面。


2.4 Mahout安装

1.Mahout能够从http://mirror.bit.edu.cn/apache/mahout/下载,我下载的版本是mahout-0.3.tar.gz
2.将下载下来的压缩文件解压缩,将lib文件夹下的jar文件所有拷贝出,为之后的工做作准备。doc目录下的mahout-core文件夹下是mahout的API,供开发时查阅。

2.5 MyEclipse8.0安装

MyEclipse的安装简单,基本和windows下安装同样,此处再也不赘述。MyEclipse安装完成以后,将前面安装好的tomcat关联到MyEclipse下。

至此,已经完成了对环境的部署,下面进入开发阶段。 sql


3 工程开发

3.1 推荐引擎简介

推荐引擎利用特殊的信息过滤(IF,Information Filtering)技术,将不一样的内容(例如电影、音乐、书籍、新闻、图片、网页等)推荐给可能感兴趣的用户。一般状况下,推荐引擎的实现是经过将用户的我的喜爱与特定的参考特征进行比较,并试图预测用户对一些未评分项目的喜爱程度。参考特征的选取多是从项目自己的信息中提取的,或是基于用户所在的社会或社团环境。
根据如何抽取参考特征,咱们能够将推荐引擎分为如下四大类:
基于内容的推荐引擎:它将计算获得并推荐给用户一些与该用户已选择过的项目类似的内容。例如,当你在网上购书时,你老是购买与历史相关的书籍,那么基于内容的推荐引擎就会给你推荐一些热门的历史方面的书籍。
基于协同过滤的推荐引擎:它将推荐给用户一些与该用户品味类似的其余用户喜欢的内容。例如,当你在网上买衣服时,基于协同过滤的推荐引擎会根据你的历史购买记录或是浏览记录,分析出你的穿衣品位,并找到与你品味类似的一些用户,将他们浏览和购买的衣服推荐给你。
基于关联规则的推荐引擎:它将推荐给用户一些采用关联规则发现算法计算出的内容。关联规则的发现算法有不少,如 Apriori、AprioriTid、DHP、FP-tree 等。
混合推荐引擎:结合以上各类,获得一个更加全面的推荐效果。

3.2 Taste简介

       Taste 是 Apache Mahout 提供的一个协同过滤算法的高效实现,它是一个基于 Java 实现的可扩展的,高效的推荐引擎。Taste 既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户能够方便的定义和实现本身的推荐算法。同时,Taste 不只仅只适用于 Java 应用程序,它能够做为内部服务器的一个组件以 HTTP 和 Web Service 的形式向外界提供推荐的逻辑。 数据库


3.3 Taste工做原理

Taste 由如下五个主要的组件组成:
  • DataModel:DataModel 是用户喜爱信息的抽象接口,它的具体实现支持从任意类型的数据源抽取用户喜爱信息。Taste 默认提供 JDBCDataModel 和 FileDataModel,分别支持从数据库和文件中读取用户的喜爱信息。
  • UserSimilarity 和 ItemSimilarity:UserSimilarity 用于定义两个用户间的类似度,它是基于协同过滤的推荐引擎的核心部分,能够用来计算用户的“邻居”,这里咱们将与当前用户口味类似的用户称为他的邻居。ItemSimilarity 相似的,计算内容之间的类似度。
  • UserNeighborhood:用于基于用户类似度的推荐方法中,推荐的内容是基于找到与当前用户喜爱类似的“邻居用户”的方式产生的。UserNeighborhood 定义了肯定邻居用户的方法,具体实现通常是基于 UserSimilarity 计算获得的。
  • Recommender:Recommender 是推荐引擎的抽象接口,Taste 中的核心组件。程序中,为它提供一个 DataModel,它能够计算出对不一样用户的推荐内容。实际应用中,主要使用它的实现类 GenericUserBasedRecommender 或者 GenericItemBasedRecommender,分别实现基于用户类似度的推荐引擎或者基于内容的推荐引擎。
 

                                                                 图1 Taste的主要组件图 apache


3.4 基于Taste构建电影推荐引擎

3.4.1 数据下载

本工程所用到的数据来源于此处: http://www.grouplens.org/node/12,下载数据“MovieLens 1M - Consists of 1 million ratings from 6000 users on 4000 movies.”

这个数据文件夹下有三个文件:movies.dat,ratings.dat和users.dat,数据形式以下三个图所示:

movies.dat的文件描述是 电影编号::电影名::电影类别
ratings.dat的文件描述是 用户编号::电影编号::电影评分::时间戳
users.dat的文件描述是 用户编号::性别::年龄::职业::Zip-code

这些文件包含来自6040个MovieLens用户在2000年对约3900部电影的1000209个匿名评分信息。


3.4.2 构造数据库

构建推荐引擎,能够直接使用movie.dat文件做为数据源,也可使用数据库中的数据做为数据源,本实验中,这两种方式都实现了,因此下面介绍利用dat文件创建数据库。
构建数据库的SQL语句以下:
[sql]   view plain copy 在CODE上查看代码片 派生到个人代码片
  1. CREATE DATABASE movie;   
  2.  USE movie;   
  3.  CREATE TABLE movies (  // 保存电影相关的信息。  
  4.     id INTEGER NOT NULL AUTO_INCREMENT,   
  5.     name varchar(100) NOT NULL,   
  6.     published_year varchar(4) default NULL,   
  7.     type varchar(100) default NULL,   
  8.     PRIMARY KEY (id)   
  9.  );   
  10.  CREATE TABLE movie_preferences (  // 保存用户对电影的评分,即喜爱程度  
  11.     userID INTEGER NOT NULL,   
  12.     movieID INTEGER NOT NULL,   
  13.     preference INTEGER NOT NULL DEFAULT 0,   
  14.     timestamp INTEGER not null default 0,   
  15.     FOREIGN KEY (movieID) REFERENCES movies(id) ON DELETE CASCADE   
  16.  );   
•Movie:表示电影,包含电影的基本信息:编号、名称、发布时间、类型等等。
•Movie Reference:表示某个用户对某个电影的喜爱程度,包含用户编号、电影编号、用户的评分以及评分的时间。
至于如何将dat文件中的内容导入到MySQL数据库中,分别由本工程目录文件下的ImportMovies.java和ImportRatings.java文件实现。

MySQL数据库中的数据以下图:

                                                                                                                                                                图二 movie_preferences表记录


                                                                                                                                                                    图三 movies表记录

3.4.3 推荐引擎实现

在本工程中,我实现了三种方式的推荐引擎:基于用户类似度的推荐引擎,基于内容类似度的推荐引擎,以及基于Slope One 的推荐引擎。在这些推荐引擎中,我分别使用了三种DataModel,即Database-based DataModel,File-based DataModel和In-memory DataModel。
a) 基于用户类似度的推荐引擎
[java]   view plain copy 在CODE上查看代码片 派生到个人代码片
  1. public class MyUserBasedRecommender {  
  2.     public List<RecommendedItem> userBasedRecommender(long userID,int size) {  
  3.         // step:1 构建模型 2 计算类似度 3 查找k紧邻 4 构造推荐引擎  
  4.         List<RecommendedItem> recommendations = null;  
  5.         try {  
  6.             DataModel model = MyDataModel.myDataModel();//构造数据模型,Database-based  
  7.             UserSimilarity similarity = new PearsonCorrelationSimilarity(model);//用PearsonCorrelation 算法计算用户类似度  
  8.             UserNeighborhood neighborhood = new NearestNUserNeighborhood(3, similarity, model);//计算用户的“邻居”,这里将与该用户最近距离为 3 的用户设置为该用户的“邻居”。  
  9.             Recommender recommender = new CachingRecommender(new GenericUserBasedRecommender(model, neighborhood, similarity));//构造推荐引擎,采用 CachingRecommender 为 RecommendationItem 进行缓存  
  10.             recommendations = recommender.recommend(userID, size);//获得推荐的结果,size是推荐接过的数目  
  11.         } catch (Exception e) {  
  12.             // TODO: handle exception  
  13.             e.printStackTrace();  
  14.         }  
  15.         return recommendations;  
  16.     }  
  17.   
  18.   
  19.     public static void main(String args[]) throws Exception {  
  20.   
  21.     }  
  22. }  


在这个推荐引擎中,因为使用的是MySQLJDBCDataModel和JNDI,因此须要在tomcat的server.xml文件中添加以下信息:
[html]   view plain copy 在CODE上查看代码片 派生到个人代码片
  1. <Context path="/MyRecommender" docBase="/home/huhui/develop/apache-tomcat-6.0.35/webapps/MyRecommender" debug="0" reloadable="true">  
  2.                 <Resource name="jdbc/movie" auth="Container" type="javax.sql.DataSource"  
  3.                         username="root"  
  4.                         password="***"  
  5.                         driverClassName="com.mysql.jdbc.Driver"  
  6.                         url="jdbc:mysql://localhost:3306/movie"  
  7.                         maxActive="15"  
  8.                         maxIdle="7"  
  9.                         defaultTransactionIsolation="READ_COMMITTED"  
  10.                         validationQuery="Select 1" />  
  11. </Context>  

Mahout 中提供了基本的类似度的计算,它们都实现了 UserSimilarity 这个接口,以实现用户类似度的计算,包括下面这些经常使用的:
•PearsonCorrelationSimilarity:基于皮尔逊相关系数计算类似度   (它表示两个数列对应数字一块儿增大或一块儿减少的可能性。是两个序列协方差与两者方差乘积的比值)
•EuclideanDistanceSimilarity:基于欧几里德距离计算类似度
•TanimotoCoefficientSimilarity:基于 Tanimoto 系数计算类似度


根据创建的类似度计算方法,找到邻居用户。这里找邻居用户的方法根据前面咱们介绍的,也包括两种:“固定数量的邻居”和“类似度门槛邻居”计算方法,Mahout 提供对应的实现:
•NearestNUserNeighborhood:对每一个用户取固定数量 N 的最近邻居
•ThresholdUserNeighborhood:对每一个用户基于必定的限制,取落在类似度门限内的全部用户为邻居。


基于 DataModel,UserNeighborhood 和 UserSimilarity 构建 GenericUserBasedRecommender,从而实现基于用户的推荐策略。


b) 基于内容类似度的推荐引擎
理解了基于用户类似读的推荐引擎,基于内容类似读的推荐引擎相似,甚至更加简单。
[java]   view plain copy 在CODE上查看代码片 派生到个人代码片
  1. public class MyItemBasedRecommender {  
  2.     public List<RecommendedItem> myItemBasedRecommender(long userID,int size){  
  3.         List<RecommendedItem> recommendations = null;  
  4.         try {  
  5.             DataModel model = new FileDataModel(new File("/home/huhui/movie_preferences.txt"));//构造数据模型,File-based  
  6.             ItemSimilarity similarity = new PearsonCorrelationSimilarity(model);//计算内容类似度  
  7.             Recommender recommender = new GenericItemBasedRecommender(model, similarity);//构造推荐引擎  
  8.             recommendations = recommender.recommend(userID, size);//获得推荐接过  
  9.         } catch (Exception e) {  
  10.             // TODO: handle exception  
  11.             e.printStackTrace();  
  12.         }  
  13.         return recommendations;  
  14.     }  
  15. }  

在这个推荐引擎中,使用的是File-based Datamodel,数据文件格式以下图所示:
 

每一行都是一个简单的三元组< 用户 ID, 物品 ID, 用户偏好 >。


c) 基于Slop One的推荐引擎
基于用户和基于内容是最经常使用最容易理解的两种推荐策略,但在大数据量时,它们的计算量会很大,从而致使推荐效率较差。所以 Mahout 还提供了一种更加轻量级的 CF 推荐策略:Slope One。
Slope One 是有 Daniel Lemire 和 Anna Maclachlan 在 2005 年提出的一种对基于评分的协同过滤推荐引擎的改进方法,下面简单介绍一下它的基本思想。
假设系统对于物品 A,物品 B 和物品 C 的平均评分分别是 3,4 和 4。基于 Slope One 的方法会获得如下规律:
•用户对物品 B 的评分 = 用户对物品 A 的评分 + 1
•用户对物品 B 的评分 = 用户对物品 C 的评分
基于以上的规律,咱们能够对用户 A 和用户 B 的打分进行预测:
•对用户 A,他给物品 A 打分 4,那么咱们能够推测他对物品 B 的评分是 5,对物品 C 的打分也是 5。
•对用户 B,他给物品 A 打分 2,给物品 C 打分 4,根据第一条规律,咱们能够推断他对物品 B 的评分是 3;而根据第二条规律,推断出评分是 4。当出现冲突时,咱们能够对各类规则获得的推断进行就平均,因此给出的推断是 3.5。
这就是 Slope One 推荐的基本原理,它将用户的评分之间的关系看做简单的线性关系:
Y = mX + b;
当 m = 1 时就是 Slope One,也就是咱们刚刚展现的例子。

[java]   view plain copy 在CODE上查看代码片 派生到个人代码片
  1. public class MySlopeOneRecommender {  
  2.     public List<RecommendedItem> mySlopeOneRecommender(long userID,int size){  
  3.         List<RecommendedItem> recommendations = null;  
  4.         try {  
  5.             DataModel model = new FileDataModel(new File("/home/huhui/movie_preferences.txt"));//构造数据模型  
  6.             Recommender recommender = new CachingRecommender(new SlopeOneRecommender(model));//构造推荐引擎  
  7.             recommendations = recommender.recommend(userID, size);//获得推荐结果  
  8.         } catch (Exception e) {  
  9.             // TODO: handle exception  
  10.             e.printStackTrace();  
  11.         }  
  12.         return recommendations;  
  13.     }  
  14. }  


d) 对数据模型的优化——In-memory DataModel
上面所叙述的三种推荐引擎,输入的都是用户的历史偏好信息,在 Mahout 里它被建模为 Preference(接口),一个 Preference 就是一个简单的三元组 < 用户 ID, 物品 ID, 用户偏好 >,它的实现类是 GenericPreference,能够经过如下语句建立一个 GenericPreference:
[java]   view plain copy 在CODE上查看代码片 派生到个人代码片
  1. GenericPreference preference = new GenericPreference(11014.0f);  
这其中, 1是用户 ID,long 型;101是物品 ID,long 型;4.0f 是用户偏好,float 型。从这个例子能够看出,一个 GenericPreference 的数据就占用8+8+4=20 字节,因此若是只简单实用数组 Array 加载用户偏好数据,必然占用大量的内存,Mahout 在这方面作了一些优化,它建立了 PreferenceArray(接口)保存一组用户偏好数据,为了优化性能,Mahout 给出了两个实现类,GenericUserPreferenceArray 和 GenericItemPreferenceArray,分别按照用户和物品自己对用户偏好进行组装,这样就能够压缩用户 ID 或者物品 ID 的空间。
[java]   view plain copy 在CODE上查看代码片 派生到个人代码片
  1. FastByIDMap<PreferenceArray> preferences = new FastByIDMap<PreferenceArray>();  
  2.   
  3.   
  4. PreferenceArray prefsForUser1 = new GenericUserPreferenceArray(3);// 注意这里的数字  
  5. // 这里是用来存储一个用户的元数据,这些元数据一般来自日志文件,好比浏览历史,等等,不一样的业务场合,它的业务语义是不同  
  6.   
  7. prefsForUser1.setUserID(01);  
  8.   
  9. prefsForUser1.setItemID(0101);  
  10. prefsForUser1.setValue(05.0f);//<1, 101, 5.0f>         < 用户 ID, 物品 ID, 用户偏好 >  
  11.   
  12.   
  13. prefsForUser1.setItemID(1102);  
  14. prefsForUser1.setValue(13.0f);//<1, 102, 3.0f>  
  15.   
  16.   
  17. prefsForUser1.setItemID(2103);  
  18. prefsForUser1.setValue(22.5f);//<1, 103, 2.5f>  
  19.   
  20.   
  21. preferences.put(1l, prefsForUser1);// 在这里添加数据,userID做为key  
  22. ........  

因为代码比较长,此处就不所有贴出来,详见工程文件中的RecommenderIntro.java文件。


4 程序演示

这个项目工程是B/S模式的,基于MVC开发模式开发的,开发环境是Ubuntu,IDE是MyEclipse8.0,工程文件目录以下图:
 
                            图四 工程文件目录


                                                                                      主要类文件之间的关系


项目首页提供三个输入:用户id,推荐电影的数目(默认为25),推荐策略。

                                                                  图五 首页


                                                                                                      图六 编号为10的用户,基于用户类似度的推荐结果


 
                                                                                                              图七 编号为10的用户,基于内容类似度的推荐结果


 

                                                                                                  图八 编号为10的用户,基于SlopOne的推荐结果

相关文章
相关标签/搜索