设为首页 收藏本站
查看: 706|回复: 0

[经验分享] 基于 Apache Mahout 实现高效的协同过滤推荐

[复制链接]

尚未签到

发表于 2015-11-14 09:59:15 | 显示全部楼层 |阅读模式

基于 Apache Mahout 实现高效的协同过滤推荐


[size=1.166em]
Apache Mahout 是 Apache Software Foundation (ASF) 旗下的一个开源项目,提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序,并且,在 Mahout 的最近版本中还加入了对 Apache Hadoop 的支持,使这些算法可以更高效的运行在云计算环境中。

[size=1.166em]
关于 Apache Mahout 的安装和配置请参考《基于 Apache Mahout 构建社会化推荐引擎》,它是笔者 09 年发表的一篇关于基于 Mahout 实现推荐引擎的 developerWorks 文章,其中详细介绍了 Mahout 的安装步骤,并给出一个简单的电影推荐引擎的例子。

[size=1.166em]
Apache Mahout 中提供的一个协同过滤算法的高效实现,它是一个基于 Java 实现的可扩展的,高效的推荐引擎。图 4 给出了 Apache Mahout 中协同过滤推荐实现的组件图,下面我们逐步深入介绍各个部分。



图 4.组件图


http://onexin.iyunv.com/source/plugin/onexin_bigdata/https://www.ibm.com/developerworks/cn/web/1103_zhaoct_recommstudy2/image019.gif

数据表示:Data Model


[size=1.166em]
Preference

[size=1.166em]
基于协同过滤的推荐引擎的输入是用户的历史偏好信息,在 Mahout 里它被建模为 Preference(接口),一个 Preference 就是一个简单的三元组 < 用户 ID, 物品 ID, 用户偏好 >,它的实现类是 GenericPreference,可以通过以下语句创建一个 GenericPreference。

[size=1.166em]
GenericPreference preference = new GenericPreference(123, 456, 3.0f);

[size=1.166em]
这其中, 123 是用户 ID,long 型;456 是物品 ID,long 型;3.0f 是用户偏好,float 型。从这个例子我们可以看出,单单一个 GenericPreference 的数据就占用 20 bytes,所以你会发现如果只简单实用数组 Array 加载用户偏好数据,必然占用大量的内存,Mahout 在这方面做了一些优化,它创建了 PreferenceArray(接口)保存一组用户偏好数据,为了优化性能,Mahout 给出了两个实现类,GenericUserPreferenceArray 和
GenericItemPreferenceArray,分别按照用户和物品本身对用户偏好进行组装,这样就可以压缩用户 ID 或者物品 ID 的空间。下面清单 1 的代码以 GenericUserPreferenceArray 为例,展示了如何创建和使用一个 PreferenceArray。



清单 1. 创建和使用 PreferenceArray


PreferenceArray userPref = new GenericUserPreferenceArray(2); //size = 2
userPref.setUserID(0, 1L);
userPref.setItemID(0, 101L);  //<1L, 101L, 2.0f>
userPref.setValue(0, 2.0f);
userPref.setItemID(1, 102L);  //<1L, 102L, 4.0f>
userPref.setValue(1, 4.0f);
Preference pref = userPref.get(1);   //<1L, 102L, 4.0f>
[size=1.166em]
为了提高性能 Mahout 还构建了自己的 HashMap 和 Set:FastByIDMap 和 FastIDSet,有兴趣的朋友可以参考 Mahout 官方说明。

[size=1.166em]
DataModel

[size=1.166em]
Mahout 的推荐引擎实际接受的输入是 DataModel,它是对用户偏好数据的压缩表示,通过创建内存版 DataModel 的语句我们可以看出:

[size=1.166em]
DataModel model = new GenericDataModel(FastByIDMap<PreferenceArray> map);

[size=1.166em]
他保存在一个按照用户 ID 或者物品 ID 进行散列的 PreferenceArray,而 PreferenceArray 中对应保存着这个用户 ID 或者物品 ID 的所有用户偏好信息。

[size=1.166em]
DataModel 是用户喜好信息的抽象接口,它的具体实现支持从任意类型的数据源抽取用户喜好信息,具体实现包括内存版的 GenericDataModel,支持文件读取的 FileDataModel 和支持数据库读取的 JDBCDataModel,下面我们看看如何创建各种 DataModel。



清单 2. 创建各种 DataModel


//In-memory DataModel - GenericDataModel
FastByIDMap<PreferenceArray> preferences = new FastByIDMap<PreferenceArray>();
PreferenceArray prefsForUser1 = new GenericUserPreferenceArray(10);  
prefsForUser1.setUserID(0, 1L);
prefsForUser1.setItemID(0, 101L);
prefsForUser1.setValue(0, 3.0f);  
prefsForUser1.setItemID(1, 102L);
prefsForUser1.setValue(1, 4.5f);
… (8 more)
preferences.put(1L, prefsForUser1);   //use userID as the key
… (more users)
DataModel model = new GenericDataModel(preferences);
//File-based DataModel - FileDataModel
DataModel dataModel = new FileDataModel(new File(&quot;preferences.csv&quot;);
//Database-based DataModel - MySQLJDBCDataModel
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setServerName(&quot;my_user&quot;);
dataSource.setUser(&quot;my_password&quot;);
dataSource.setPassword(&quot;my_database_host&quot;);
JDBCDataModel dataModel = new MySQLJDBCDataModel(dataSource, &quot;my_prefs_table&quot;,
&quot;my_user_column&quot;, &quot;my_item_column&quot;, &quot;my_pref_value_column&quot;);
[size=1.166em]
支持文件读取的 FileDataModel,Mahout 没有对文件的&#26684;式做过多的要求,只要文件的内容满足以下&#26684;式:




  • 每一行包括用户 ID, 物品 ID, 用户偏好

  • 逗号隔开或者 Tab 隔开

  • *.zip 和 *.gz 文件会自动解压缩(Mahout 建议在数据量过大时采用压缩的数据存储)

[size=1.166em]
支持数据库读取的 JDBCDataModel,Mahout 提供一个默认的 MySQL 的支持,它对用户偏好数据的存放有以下简单的要求:




  • 用户 ID 列需要是 BIGINT 而且非空

  • 物品 ID 列需要是 BIGINT 而且非空

  • 用户偏好列需要是 FLOAT

[size=1.166em]
建议在用户 ID 和物品 ID 上建索引。



实现推荐:Recommender


[size=1.166em]
介绍完数据表示模型,下面介绍 Mahout 提供的协同过滤的推荐策略,这里我们选择其中最经典的三种,User CF, Item CF 和 Slope One。

[size=1.166em]
User CF

[size=1.166em]
前面已经详细介绍了 User CF 的原理,这里我们着重看怎么基于 Mahout 实现 User CF 的推荐策略,我们还是从一个例子入手:



清单 3. 基于 Mahout 实现 User CF


DataModel model = new FileDataModel(new File(&quot;preferences.dat&quot;));
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
UserNeighborhood neighborhood = new NearestNUserNeighborhood(100, similarity, model);
Recommender recommender = new GenericUserBasedRecommender(model,
neighborhood, similarity);


  • 从文件建立 DataModel,我们采用前面介绍的 FileDataModel,这里假设用户的喜好信息存放在 preferences.dat 文件中。

  • 基于用户偏好数据计算用户的相&#20284;度,清单中采用的是 PearsonCorrelationSimilarity,前面章节曾详细介绍了各种计算相&#20284;度的方法,Mahout 中提供了基本的相&#20284;度的计算,它们都 UserSimilarity 这个接口,实现用户相&#20284;度的计算,包括下面这些常用的:



  • PearsonCorrelationSimilarity:基于皮尔逊相关系数计算相&#20284;度

  • EuclideanDistanceSimilarity:基于欧几里德距离计算相&#20284;度

  • TanimotoCoefficientSimilarity:基于 Tanimoto 系数计算相&#20284;度

  • UncerteredCosineSimilarity:计算 Cosine 相&#20284;度

[size=1.166em]
ItemSimilarity 也是类&#20284;的:




  • 根据建立的相&#20284;度计算方法,找到邻居用户。这里找邻居用户的方法根据前面我们介绍的,也包括两种:“固定数量的邻居”和“相&#20284;度门槛邻居”计算方法,Mahout 提供对应的实现:


    • NearestNUserNeighborhood:对每个用户取固定数量 N 的最近邻居

    • ThresholdUserNeighborhood:对每个用户基于一定的限制,取落在相&#20284;度门限内的所有用户为邻居。


  • 基于 DataModel,UserNeighborhood 和 UserSimilarity 构建 GenericUserBasedRecommender,实现 User CF 推荐策略。

[size=1.166em]
Item CF

[size=1.166em]
了解了 User CF,Mahout Item CF 的实现与 User CF 类&#20284;,是基于 ItemSimilarity,下面我们看实现的代码例子,它比 User CF 更简单,因为 Item CF 中并不需要引入邻居的概念:



清单 4. 基于 Mahout 实现 Item CF


DataModel model = new FileDataModel(new File(&quot;preferences.dat&quot;));
ItemSimilarity similarity = new PearsonCorrelationSimilarity(model);
Recommender recommender = new GenericItemBasedRecommender(model, similarity);
[size=1.166em]
Slope One

[size=1.166em]
如前面介绍的,User CF 和 Item CF 是最常用最容易理解的两种 CF 的推荐策略,但在大数据量时,它们的计算量会很大,从而导致推荐效率较差。因此 Mahout 还提供了一种更加轻量级的 CF 推荐策略:Slope One。

[size=1.166em]
Slope One 是有 Daniel Lemire 和 Anna Maclachlan 在 2005 年提出的一种对基于评分的协同过滤推荐引擎的改进方法,下面简单介绍一下它的基本思想。

[size=1.166em]
图 5 给出了例子,假设系统对于物品 A,物品 B 和物品 C 的平均评分分别是 3,4 和 4。基于 Slope One 的方法会得到以下规律:




  • 用户对物品 B 的评分 = 用户对物品 A 的评分 &#43; 1

  • 用户对物品 B 的评分 = 用户对物品 C 的评分

[size=1.166em]
基于以上的规律,我们可以对用户 A 和用户 B 的打分进行预测:




  • 对用户 A,他给物品 A 打分 4,那么我们可以推测他对物品 B 的评分是 5,对物品 C 的打分也是 5。

  • 对用户 B,他给物品 A 打分 2,给物品 C 打分 4,根据第一条规律,我们可以推断他对物品 B 的评分是 3;而根据第二条规律,推断出评分是 4。当出现冲突时,我们可以对各种规则得到的推断进行就平均,所以给出的推断是 3.5。

[size=1.166em]
这就是 Slope One 推荐的基本原理,它将用户的评分之间的关系看作简单的线性关系:

[size=1.166em]
Y = mX &#43; b;

[size=1.166em]
当 m = 1 时就是 Slope One,也就是我们刚刚展示的例子。



图 5.Slope One 推荐策略示例


http://onexin.iyunv.com/source/plugin/onexin_bigdata/https://www.ibm.com/developerworks/cn/web/1103_zhaoct_recommstudy2/image021.gif
[size=1.166em]
Slope One 的核心优势是在大规模的数据上,它依然能保证良好的计算速度和推荐效果。Mahout 提供了 Slope One 推荐方法的基本实现,实现代码很简单,参考清单 5.



清单 5. 基于 Mahout 实现 Slope One


//In-Memory Recommender
DiffStorage diffStorage = new MemoryDiffStorage(model, Weighting.UNWEIGHTED, false,
Long.MAX_VALUE));
Recommender recommender = new SlopeOneRecommender(model, Weighting.UNWEIGHTED,
Weighting.UNWEIGHTED, diffStorage);  
//Database-based Recommender
AbstractJDBCDataModel model = new MySQLJDBCDataModel();
DiffStorage diffStorage = new MySQLJDBCDiffStorage(model);
Recommender recommender = new SlopeOneRecommender(model, Weighting.WEIGHTED,
Weighting.WEIGHTED, diffStorage);
[size=1.166em]
1. 根据 Data Model 创建数据之间线性关系的模型 DiffStorage。

[size=1.166em]
2. 基于 Data Model 和 DiffStorage 创建 SlopeOneRecommender,实现 Slope One 推荐策略。


[size=1.166em]
回页首



总结


[size=1.166em]
Web2.0 的一个核心思想就是“集体智慧”,基于协同过滤的推荐策略的基本思想就是基于大众行为,为每个用户提供个性化的推荐,从而使用户能更快速更准确的发现所需要的信息。从应用角度分析,现今比较成功的推荐引擎,比如 Amazon,豆瓣,当当等都采用了协同过滤的方式,它不需要对物品或者用户进行严&#26684;的建模,而且不要求物品的描述是机器可理解的,是中领域无关的推荐方法,同时这个方法计算出来的推荐是开放的,可以共用他人的经验,很好的支持用户发现潜在的兴趣偏好。基于协同过滤的推荐策略也有不同的分支,它们有不同的实用场景和推荐效果,用户可以根据自己应用的实际情况选择合适的方法,异或组合不同的方法得到更好的推荐效果。

[size=1.166em]
除此之外,本文还介绍了如何基于 Apache Mahout 高效实现协同过滤推荐算法,Apache Mahout 关注海量数据上的机器学习经典算法的高效实现,其中对基于协同过滤的推荐方法也提供了很好的支持,基于 Mahout 你可以轻松的体验高效推荐的神奇。

[size=1.166em]
作为深入推荐引擎相关算法的第一篇文章,本文深入介绍了协同过滤算法,并举例介绍了如何基于 Apache Mahout 高效实现协同过滤推荐算法,Apache Mahout 作为海量数据上的机器学习经典算法的高效实现,其中对基于协同过滤的推荐方法也提供了很好的支持,基于 Mahout 你可以轻松的体验高效推荐的神奇。但我们也发现了在海量数据上高效的运行协同过滤算法以及其他推荐策略这样高复杂的算法还是有很大的挑战的。在面对这个问题的过程中,大家提出了很多减少计算量的方法,而聚类无疑是其中最优的选择。所以本系列的下一篇文章将详细介绍各类聚类算法,它们的原理,优缺点和实用场景,并给出基于
Apache Mahout 的聚类算法的高效实现,并分析在推荐引擎的实现中,如何通过引入聚类来解决大数据量造成的海量计算,从而提供高效的推荐。

[size=1.166em]
最后,感谢大家对本系列的关注和支持。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-139041-1-1.html 上篇帖子: python apache2 Internal Server Error 下篇帖子: Apache POI如何获取Excel合并单元格的值
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表