该系统利用基于密度的新型聚类算法,对给定用户基于好友推荐。本系统的开发IDE采用eclipse,使用maven构建项目,数据库选用Mysql,后台技术采用Struts2+Hibernate+Spring的架构,前端使用Easyui+Ajax的技术实现前后端的数据交互,算法的主要计算任务用Hadoop Mapreduce来完成。综合来说,本系统面临的主要挑战如下:
本此项目的用户数据源样例如下:
<row Id="-1" Reputation="9" CreationDate="2010-07-28T16:38:27.683" DisplayName="Community" EmailHash="a007be5a61f6aa8f3e85ae2fc18dd66e" LastAccessDate="2010-07-28T16:38:27.683" Location="on the server farm" AboutMe="<p>Hi, I'm not really a person.</p>
<p>I'm a background process that helps keep this site clean!</p>
<p>I do things like</p>
<ul>
<li>Randomly poke old unanswered questions every hour so they get some attention</li>
<li>Own community questions and answers so nobody gets unnecessary reputation from them</li>
<li>Own downvotes on spam/evil posts that get permanently deleted
</ul>" Views="0" UpVotes="142" DownVotes="119" />
<row Id="2" Reputation="101" CreationDate="2010-07-28T17:09:21.300" DisplayName="Geoff Dalgas" EmailHash="b437f461b3fd27387c5d8ab47a293d35" LastAccessDate="2011-09-01T23:16:56.353" WebsiteUrl="http://stackoverflow.com" Location="Corvallis, OR" Age="34" AboutMe="<p>Developer on the StackOverflow team. Find me on</p>
<p><a href="http://www.twitter.com/SuperDalgas" rel="nofollow">Twitter</a>
<br><br>
<a href="http://blog.stackoverflow.com/2009/05/welcome-stack-overflow-valued-associate-00003/" rel="nofollow">Stack Overflow Valued Associate #00003</a> </p>
" Views="25" UpVotes="7" DownVotes="0" />
该数据源是http://stackoverflow.com/ 网站上的用户数据。该网站我就不做介绍了,程序员收藏夹必备网站之一。该网站的网页截图如下:
本次好友推荐系统建立在如下假设上:
针对以上假设,对原始用户数据进行分析,挑选的代表属性如下:
其中我们实现用户聚类基于如下四个属性:reputation,upVotes,downVotes,views。
core-site.xml
<configuration>
<property>
<name>fs.defaultFSname>
<value>hdfs://sparkproject1:9000value>
property>
configuration>
hdfs-site.xml
<configuration>
<property>
<name>dfs.name.dirname>
<value>/usr/local/data/namenodevalue>
property>
<property>
<name>dfs.data.dirname>
<value>/usr/local/data/datanodevalue>
property>
<property>
<name>dfs.tmp.dirname>
<value>/usr/local/data/tmpvalue>
property>
<property>
<name>dfs.replicationname>
<value>2value>
property>
<property>
<name>dfs.namenode.secondary.http-addressname>
<value>sparkproject1:9001value>
property>
<property>
<name>dfs.webhdfs.enabledname>
<value>truevalue>
property>
configuration>
mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.namename>
<value>yarnvalue>
property>
<property>
<name>mapreduce.jobhistory.addressname>
<value>sparkproject1:10020value>
property>
<property>
<name>mapreduce.jobhistory.webapp.addressname>
<value>sparkproject1:19888value>
property>
configuration>
yarn-site.xml
<configuration>
<property>
<name>yarn.resourcemanager.hostnamename>
<value>sparkproject1value>
property>
<property>
<name>yarn.nodemanager.aux-servicesname>
<value>mapreduce_shufflevalue>
property>
<property>
<name>yarn.resourcemanager.addressname>
<value>sparkproject1:8032value>
property>
<property>
<name>yarn.resourcemanager.scheduler.addressname>
<value>sparkproject1:8030value>
property>
<property>
<name>yarn.resourcemanager.resource-tracker.addressname>
<value>sparkproject1:8031value>
property>
<property>
<name>yarn.resourcemanager.admin.addressname>
<value>sparkproject1:8033value>
property>
<property>
<name>yarn.resourcemanager.webapp.addressname>
<value>sparkproject1:8088value>
property>
configuration>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<configuration>
<port>80port>
<path>/friend_findpath>
configuration>
plugin>
点击左侧”数据表的初始化“选项卡,选择对应的表,点击初始化按钮,可完成初始化。
如果需要修改初始化信息,点击某一行数据,在toolbar里即可选择修改或保存等即可。
项目实现的流程按照系统首页左边导航栏的顺序从上到下运行,完成聚类算法的各个步骤。
查看原始数据ask_ubuntu_users.xml 文件,原始数据一共有19550条记录,去除第1、2、最后一行外其他都是用户数据(第3行不是用户数据,是该网站的描述);
用户数据需要使用一个主键来唯一标示该用户,这里不是选择Id,而是使用EmailHash。假设每个EmailHash相同的账号其是同一个人,使用上面的假设后,对原始数据进行分析,发现EmailHash是有重复记录的,所以这里需要对数据进行预处理-数据去重。
根据新型聚类算法的基本原理,可以分为如下步骤:
1. 计算用户向量两两之间的距离;
2. 根据距离求解每个用户向量的局部密度;
3. 根据步骤1和步骤2的结果求解每个用户向量的最小距离;
4. 根据步骤2,3的结果画出决策图,并判断聚类中心的局部密度和最小距离的阈值;
5. 根据局部密度和最小距离阈值来寻找聚类中心向量;
6. 根据聚类中心向量来进行分类;
执行分类算法后的结果即可以得到聚类中心向量以及每个分群的百分比,同时根据分类的结果来对用户进行组内推荐。
该项目基本完成了文章开头提出的三个挑战:算法的Mapreduce实现、MapReduce任务的远程提交、MapReduce任务的实时监控。但是在开发实践过程中仍然暴露出一些问题:
1、通过基于密度的新型聚类算法计算得到的最佳DC进行聚类,并不能得到理想的聚类效果。这个问题目前有待研究,事实上在该算法的原文章中作者也只是给出一个参考方法:选取一个Dc,使得每个数据点的平均邻居个数约为数据点总数的1%-2%。从某种程度上来讲,Dc的选取决定着这个聚类算法的成败,取得太大和太小都不行。如果Dc去的太大,将使得每个数据点的局部密度值都很大,导致区分度不高。极端情况是Dc的值大于所有点的最大距离值,这样算法的最终结果就是所有点都属于同一个聚类中心。如果Dc取值太小,那么同一个分组有可能被拆分为多个。极端情况是Dc比所有点的距离值都要小,这样将导致每一个点都是一个聚类中心。
2、在最后的根据分组推荐朋友阶段,并没有考虑分组内部的成员与当前用户的相关程度,仅仅是把该用户所在分组的所有成员列举出来。事实上应该按照与当前用户的相关程度进行排序,这里并未实现这个功能。
3、因为本人测试环境的限制(一台电脑上运行三个虚拟机),原数据量的大小远远不能发挥Hadoop大数据处理的特色。事实上,我的个人理解是,当我们的数据量非常非常大的时候并不是说一定要使用Hadoop来进行处理或者说Hadoop处理比单机处理要有多么好,而是此时单机系统因为磁盘和内存的限制已经无法处理这么大的文件了。如果是超级计算机,那么它的处理效率应该比Hadoop集群要快很多。这样来看,Hadoop集群相当于廉价的超级计算机。还是那句话,如果没有足够大的数据量,使用Hadoop完全就是“自讨苦吃”,它的资源消耗远比单机处理大的多。
4、本项目采用完全手动编程实现聚类算法,事实上,Hadoop生态系统早就提供了数据挖掘的相关框架:Mahout。Mahout提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序。Mahout包含许多实现,包括聚类、分类、推荐过滤、频繁子项挖掘。此外,通过使用 Apache Hadoop 库,Mahout 可以有效地扩展到云中。未来或可考虑将Mahout扩展到该项目中。
本项目完整源码以上传至github,链接在这里。点我