基于Mahout实现协同过滤推荐算法的电影推荐系统

article/2025/10/9 22:04:48

1 Mahout介绍

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

2 环境部署

  • JDK1.8.0_111
  • MySQL
  • apache-tomcat-8.5.31
  • mahout-0.3
  • Eclipse 8.0

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,它可以计算出对不同用户的推荐内容。Recommender是Taste中的核心组件,它可以根据提供的数据模型计算出对不同用户的推荐结果。其中包含的子类可以从内存中缓存其他的推荐结果,因此在低内存情况下可以通过让Java虚拟机取回推荐的结果再输出。在Recommender组件里包含的推荐方法一般会将结果储存在List中,另外estimatePreference()方法还能预估用户对物品的评分。


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

3.4.1 数据下载

本工程所用到的数据来源于此处:Datasets | GroupLens,下载数据“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语句如下:

CREATE DATABASE movie;USE movie;CREATE TABLE movies (  // 保存电影相关的信息。id INTEGER NOT NULL AUTO_INCREMENT,name varchar(100) NOT NULL,published_year varchar(4) default NULL,type varchar(100) default NULL,PRIMARY KEY (id));CREATE TABLE movie_preferences (  // 保存用户对电影的评分,即喜好程度userID INTEGER NOT NULL,movieID INTEGER NOT NULL,preference INTEGER NOT NULL DEFAULT 0,timestamp INTEGER not null default 0,FOREIGN KEY (movieID) REFERENCES movies(id) ON DELETE CASCADE);

•Movie:表示电影,包含电影的基本信息:编号、名称、发布时间、类型等等。
•Movie Reference:表示某个用户对某个电影的喜好程度,包含用户编号、电影编号、用户的评分以及评分的时间。
至于如何将dat文件中的内容导入到MySQL数据库中,分别由本工程目录文件下的ImportMovies.java和ImportRatings.java文件实现。

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


3.4.3 推荐引擎实现

在本推荐系统中,我实现了三种方式的推荐引擎:基于用户相似度的推荐引擎,基于内容相似度的推荐引擎,以及基于Slope One 的推荐引擎。在这些推荐引擎中,我分别使用了三种DataModel,即Database-based DataModel,File-based DataModel和In-memory DataModel。

1.基于用户相似度的推荐引擎

public class MyUserBasedRecommender {public List<RecommendedItem> userBasedRecommender(long userID,int size) {// step:1 构建模型 2 计算相似度 3 查找k紧邻 4 构造推荐引擎List<RecommendedItem> recommendations = null;try {DataModel model = MyDataModel.myDataModel();//构造数据模型UserSimilarity similarity=new PearsonCorrelationSimilarity(model,Weighting.WEIGHTED);//用PearsonCorrelation 算法计算用户相似度UserNeighborhood neighborhood = new NearestNUserNeighborhood(3, similarity, model);//计算用户的“邻居”,这里将与该用户最近距离为 3 的用户设置为该用户的“邻居”。Recommender recommender = new CachingRecommender(new GenericUserBasedRecommender(model, neighborhood, similarity));//采用 CachingRecommender 为 RecommendationItem 进行缓存recommendations = recommender.recommend(userID, size);//得到推荐的结果,size是推荐结果的数目
//			
//			List<RecommendedItem>recommendedItemList =recommender.recommend(5,10);
//			for(RecommendedItem recommendedItem:recommendedItemList){
//				System.out.println(recommendedItem);
//			}//			DataModel model = MyDataModel.myDataModel();//构造数据模型
//			UserSimilarity similarity=new EuclideanDistanceSimilarity(model);//用PearsonCorrelation 算法计算用户相似度
//			UserNeighborhood neighborhood = new NearestNUserNeighborhood(3, similarity, model);//计算用户的“邻居”,这里将与该用户最近距离为 3 的用户设置为该用户的“邻居”。
//			Recommender recommender = new CachingRecommender(new GenericUserBasedRecommender(model, neighborhood, similarity));//采用 CachingRecommender 为 RecommendationItem 进行缓存
//			recommendations = recommender.recommend(userID, size);//得到推荐的结果,size是推荐结果的数目} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}return recommendations;}

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


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


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

2.基于内容相似度的推荐引擎

public class MyItemBasedRecommender {public List<RecommendedItem> myItemBasedRecommender(long userID,int size){List<RecommendedItem> recommendations = null;try {DataModel model = new FileDataModel(new File("D:/ml-1m/movie_preferences.txt"));//构造数据模型ItemSimilarity similarity = new PearsonCorrelationSimilarity(model);//计算内容相似度  Recommender recommender = new GenericItemBasedRecommender(model, similarity);//构造推荐引擎  recommendations = recommender.recommend(userID, size);//得到推荐结果,size是推荐结果的数目} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}return recommendations;}}

3.基于Slope 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,也就是我们刚刚展示的例子。

public class MySlopeOneRecommender {public List<RecommendedItem> mySlopeOneRecommender(long userID,int size){List<RecommendedItem> recommendations = null;try {DataModel model = new FileDataModel(new File("D:/ml-1m/movie_preferences.txt"));//构造数据模型Recommender recommender = new CachingRecommender(new SlopeOneRecommender(model));//构造推荐引擎  recommendations = recommender.recommend(userID, size);//得到推荐的结果,size是推荐结果的数目} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}return recommendations;}}

4.对数据模型的优化处理

上面所叙述的三种推荐引擎,输入的都是用户的历史偏好信息,在 Mahout 里它被建模为 Preference(接口),一个 Preference 就是一个简单的三元组 < 用户 ID, 物品 ID, 用户偏好 >,它的实现类是 GenericPreference,可以通过以下语句创建一个 GenericPreference:

GenericPreference preference = new GenericPreference(1, 101, 4.0f);

这其中, 1是用户 ID,long 型;101是物品 ID,long 型;4.0f 是用户偏好,float 型。从这个例子可以看出,一个 GenericPreference 的数据就占用8+8+4=20 字节,所以如果只简单实用数组 Array 加载用户偏好数据,必然占用大量的内存,Mahout 在这方面做了一些优化,它创建了 PreferenceArray(接口)保存一组用户偏好数据,为了优化性能,Mahout 给出了两个实现类,GenericUserPreferenceArray 和 GenericItemPreferenceArray,分别按照用户和物品本身对用户偏好进行组装,这样就可以压缩用户 ID 或者物品 ID 的空间。
 

		FastByIDMap<PreferenceArray> preferences = new FastByIDMap<PreferenceArray>();PreferenceArray prefsForUser1 = new GenericUserPreferenceArray(3);// 注意这里的数字// 这里是用来存储一个用户的元数据,这些元数据通常来自日志文件,比如浏览历史等。在不同的业务场合下它的业务语义是不一样的。prefsForUser1.setUserID(0, 1);prefsForUser1.setItemID(0, 101);prefsForUser1.setValue(0, 5.0f);//<1, 101, 5.0f> < 用户 ID, 物品 ID, 用户偏好 >prefsForUser1.setItemID(1, 102);prefsForUser1.setValue(1, 3.0f);//<1, 102, 3.0f>prefsForUser1.setItemID(2, 103);prefsForUser1.setValue(2, 2.5f);//<1, 103, 2.5f>preferences.put(1l, prefsForUser1);// 在这里添加数据,userID作为key

4 程序演示

这个项目工程是B/S模式的,基于MVC开发模式开发的,开发环境是Windows10,IDE是Eclipse,工程文件目录如下图:

启动Tomcat服务器后,在浏览器地址栏里输入http://localhost:8080/MovieRecommender 即可进入本推荐系统。在初始界面选择想要测试的用户编号ID,输入电影数量,选择想要使用的一个推荐引擎就可以进入电影推荐页面。下图为用户初始登录界面,可供选择的推荐引擎有基于用户、基于物品和基于Slope One的协同过滤推荐算法。

推荐结果显示

当选择使用本项目的基于用户的协同过滤推荐策略时,推荐结果显示时间较为缓慢,大约为80秒才能得到推荐结果。总结原因是因为要从数据库获取大量数据并进行实时计算相似度。另外,基于用户相似度得到的推荐电影有很多都是评分较高的广为人知的好电影,这类电影知名度太高,所以并没有太大的必要来推荐给用户。还有一点值得注意的地方是,例如选择了对《星球大战》评分较高的用户,得到的推荐电影存在有《星球大战》续集的情况,这样的推荐结果并没有太大的意义。推荐结果意义不大是很多推荐系统的通病,也是现在研究的一个重要方向。虽然看似推荐的精确度很高,但是站在用户的角度考虑,无论是否有这样的推荐,用户都存在很大的概率会去观看这部电影的续集。

当修改推荐引擎中计算相似度的方法后,推荐结果的质量有所好转,类似上述的出现推荐续集的次数下降。但是所花费的时间比原来增加了。 

当选择使用基于物品的协同过滤推荐引擎时,结果的显示速度明显上升,而且可以很直观地看出所推荐的电影质量比基于用户的协同过滤要高一些。例如看过了星际穿越的用户会得到银翼杀手、2001太空漫游等类似科幻电影推荐。根据基于用户和基于物品的两种推荐引擎所得到的不同推荐质量可以观察出,基于用户的推荐算法的重心是放在多个用户所形成的的集合里,没有突出用户的个性,当用户数量较多时,算法的计算效率不够高。而基于物品的推荐算法更加地侧重于用户的历史爱好,突出用户的个性,但是如果物品的数量过多,那么也会影响到计算效率。 

项目源代码来源:GitHub - bystc/MovieRecommender: 基于Mahout实现协同过滤推荐算法的电影推荐系统


http://chatgpt.dhexx.cn/article/OOtuKxXb.shtml

相关文章

Mahout简介

Mahout简介 一、mahout是什么 Apache Mahout是ApacheSoftware Foundation &#xff08;ASF&#xff09;旗下的一个开源项目&#xff0c;提供了一些经典的机器学习的算法&#xff0c;皆在帮助开发人员更加方便快捷地创建智能应用程序。目前已经有了三个公共发型版本&#xff0…

推荐系统 Mahout入门之简单使用

Mahout&#xff1a; Apache Mahout 是 Apache Software Foundation&#xff08;ASF&#xff09;旗下的一个开源项目&#xff0c;提供一些可扩展的机器学习领域经典算法的实现&#xff0c;旨在帮助开发人员更加方便快捷地创建智能应用程序。Mahout项目目前已经有了多个公共发行…

Mahout介绍和简单应用

Mahout学习&#xff08;主要学习内容是Mahout中推荐部分的ItemCF、UserCF、Hadoop集群部署运行&#xff09; 1.Mahout是什么&#xff1f; Mahout是一个算法库,集成了很多算法。 Apache Mahout 是 Apache Software Foundation&#xff08;ASF&#xff09;旗下的一个开源项目&…

脚手架开发流程

先把原理讲通&#xff0c;方便后续的开发。 后续都拿vue-cli举例 脚手架实现原理 为什么全局安装vue/cli后会添加的命令为vue&#xff1f;全局安装vue/cli时发生了什么&#xff1f;执行vue命令时发生了什么&#xff1f;为什么vue指向一个js文件&#xff0c;我们却可以直接通过…

ns2模拟仿真实验

内容&#xff1a; 编写TCL脚本&#xff0c;搭建如下图所示的一个网络&#xff0c;共6个节点&#xff0c;其中2、3节点用做ftp服务器和客户端&#xff0c;4、5节点用做cbr流量的源和目的&#xff0c;而0、1节点用做转发设备。各节点间的链路属性见图。 模拟时间设为13秒钟&#…

NS2网络仿真环境的搭建和使用

一实验概述: 1学会安装和使用NS2&#xff1b;熟悉NS2的文档结构&#xff1b;掌握NS2的仿真环境、使用界面和操作方法。 2学会安装NS2仿真环境和配置。 3了解NS2的工作原理和程序组成。 4熟悉NS2中的脚本语言Tcl和Otcl 5学习分裂对象模型和TclCL 6NS的时间调度机制学习。 …

NS2的NODE类——node

本文转自&#xff1a;http://hi.baidu.com/wirelesscat/blog/item/67c6db4633f71e016b63e59b.html 同时推荐一个很好的博客&#xff0c;这里有连载的 ns2 仿真问题&#xff0c;感谢大牛&#xff5e;&#xff5e;&#xff5e; 博客地址&#xff1a;http://hi.baidu.com/wirele…

NS2问题解决

问题一&#xff1a; When configured, ns found the right version of tclsh in /usr/bin/tclsh8.6 but it doesnt seem to be there anymore, so ns will fall back on running the first tclsh in your path. The wrong version of tclsh may break the test suites. Reconfi…

NS2简单介绍

NS是一种针对网络技术的源代码公开的、免费的软件模拟平台&#xff0c;研究人员使用它可以很容易的进行网络技术的开发&#xff0c;而且发展到今天&#xff0c;它所包含的模块已经非常丰富&#xff0c;几乎涉及到了网络技术的所有方面。所以&#xff0c;NS成了目前学术界广泛使…

NS2网络仿真

NS2安装与配置TCP/UDP比较仿真静态/动态路由仿真 1.安装与配置 1.1更新系统 sudo apt-get update #更新源列表 sudo apt-get upgrade #更新已经安装的包 sudo apt-get dist-upgrade #更新软件&#xff0c;升级系统 1.2安装ns2需要的几个包 sudo apt-get install build-ess…

ns2安装详细过程与网络仿真

ns2安装详细过程与网络仿真 博客分类&#xff1a; Networks TclLinuxUnixGCCVC 简单的说&#xff0c;NS&#xff0d;2是一个网络模拟器&#xff0c;所以经常被用到网络课的教学中。 NS-2是OpenSource的&#xff0c;最早的版本是在linux/unix下运行的&#xff0c;后来有了wi…

NS2教程

柯老师的NS2新网址 Due to some reasons, my NS2 website is sometimes donw and unavailable for many users. Therefore, I provide another backup website. 1. NS2 http://csie.nqu.edu.tw/smallko/ns2/ns2.htm 2. old_NS2 (backup of NS2 Learning Guide) http://csie.n…

ns2安装和若干问题的解决方法

文章目录 1. 安装与配置2. 安装nam3. 配置环境变量4. 检查是否能够成功运行参考资料 在安装ns2的过程中遇到了很多问题&#xff0c;为了记录这些问题和为同样遇到这些问题的朋友提供思路&#xff0c;写下这篇博文。 安装ns2和nam主要分为如下几个步骤&#xff1a; 安装与配置…

Linux下安装ns2

最近为了项目需要用到NS2软件用于网络仿真实验&#xff0c;从Windows到Linux折腾了我将近一周的时间。在Windows装了卸、卸了装十几遍还是不成功&#xff0c;最后放弃了&#xff0c;回到了Linux系统&#xff0c;又折腾了两天终于安装测试成功&#xff01;&#xff08;安装其实蛮…

企业微信第三方扫码登录

为什么写这个文章 公司后台突然需要扫码登录&#xff0c;网上的企业微信扫码都是基于自建应用的扫码登录&#xff0c;对第三方的扫码并没有多加介绍 概述 企业微信的管理员和成员&#xff0c;可通过单点登录机制&#xff0c;登录到第三方网站。第三方可通过接口&#xff0c;…

微信第三方登录有两种登录方式, 1. 微信开放平台登录 2. 微信公众平台授权登录?

https://www.v2ex.com/amp/t/390333 微信开放平台登录与微信公众平台授权登录区别在哪? 2017-09-13 12:05:41 08:00 xoxo419 微信第三方登录有两种登录方式, 1. 微信开放平台登录 2. 微信公众平台授权登录? 问: 两者区别在哪? 壹号店 http://m.yhd.com 微信第三方登录属…

Android APP微信第三方登录踩坑 - 微信开放平台修改应用包名后微信第三方登录失败

在微信开放平台注册移动应用&#xff0c;才能在APP里实现「微信登录」和「微信支付」。 近期因为业务需要&#xff0c;需要修改应用的包名&#xff0c;因此在微信开发平台重新提交了应用「基本信息」修改申请&#xff0c;顺便吐槽下&#xff0c;现在微信开发平台对应用审核真是…

微信第三方登录redirect_uri 参数错误

微信第三方登录 先说解决方案&#xff1a;redirect_uri 参数错误 在开放平台设置好回调地址&#xff0c;例如地址是 www.niezhiliang.com 那么在生成二维码的时候回调只能写该域名下的地址 在申请二维码页面回调地址(你的redirect_uri) 还必须加上http或者https&#xff0c;…

微信第三方登录接口

随着手机微信的崛起&#xff0c;腾讯发布的微信联登确实很诱惑pc端的伙伴们&#xff0c;现在就说说在pc端用微信扫一扫实现微信第三方登陆的方式。 第一步&#xff1a;获取AppID AppSecret(不做解释&#xff0c;自己去微信公众平台申请) 第二步&#xff1a;生成扫描二维码&…

微信 第三方登录

转自&#xff1a;http://www.cnblogs.com/linjunjie/p/6378166.html#3902595 从http://www.cnblogs.com/v-weiwang/p/5732423.html 申请开发者账号之内的就不累赘了&#xff0c;网上一大堆&#xff1a; 说下需求&#xff0c;一个网页要在三类容器运行&#xff0c;公司app&#…