分享

用Maven构建Mahout项目

本帖最后由 52Pig 于 2014-10-25 11:54 编辑
阅读导读:
1.Mahout0.7版本和其他Mahout版本的有什么区别?
2.简述Mahout方法中算法实现过程?
3.R语言和Mahout生成的点,并不是重合的,原因有哪些?




1.开发环境

开发环境
Win7 64bit
Java 1.6.0_45
Maven 3
Eclipse Juno Service Release 2
Mahout 0.6
这里要说明一下mahout的运行版本。
mahout-0.5, mahout-0.6, mahout-0.7,是基于hadoop-0.20.2x的。
mahout-0.8, mahout-0.9,是基于hadoop-1.1.x的。
mahout-0.7,有一次重大升级,去掉了多个算法的单机内存运行,并且了部分API不向前兼容。
注:本文关注于“用Maven构建Mahout的开发环境”,文中的 2个例子都是基于单机的内存实现,因此选择0.6版本。
2. Mahout单机开发环境介绍
hadoop-mahout-dev.png
如上图所示,我们可以选择在win中开发,也可以在linux中开发,开发过程我们可以在本地环境进行调试,标配的工具都是Maven和Eclipse。
3. 用Maven构建Mahout开发环境
  • 用Maven创建一个标准化的Java项目
  • 导入项目到eclipse
  • 增加mahout依赖,修改pom.xml
  • 下载依赖
1).用Maven创建一个标准化的Java项目
  1. ~ D:\workspace\java>mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes
  2. -DgroupId=org.conan.mymahout -DartifactId=myMahout -DpackageName=org.conan.mymahout -Dversion=1.0-SNAPSHOT -DinteractiveMode=false
复制代码
进入项目,执行mvn命令
  1. ~ D:\workspace\java>cd myMahout
  2. ~ D:\workspace\java\myMahout>mvn clean install
复制代码
2). 导入项目到eclipse
我们创建好了一个基本的maven项目,然后导入到eclipse中。 这里我们最好已安装好了Maven的插件。
mahout-eclipse-folder.png
3). 增加mahout依赖,修改pom.xml
这里我使用hadoop-0.6版本,同时去掉对junit的依赖,修改文件:pom.xml
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>org.conan.mymahout</groupId>
  5. <artifactId>myMahout</artifactId>
  6. <packaging>jar</packaging>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>myMahout</name>
  9. <url>http://maven.apache.org</url>
  10. <properties>
  11. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  12. <mahout.version>0.6</mahout.version>
  13. </properties>
  14. <dependencies>
  15. <dependency>
  16. <groupId>org.apache.mahout</groupId>
  17. <artifactId>mahout-core</artifactId>
  18. <version>${mahout.version}</version>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.apache.mahout</groupId>
  22. <artifactId>mahout-integration</artifactId>
  23. <version>${mahout.version}</version>
  24. <exclusions>
  25. <exclusion>
  26. <groupId>org.mortbay.jetty</groupId>
  27. <artifactId>jetty</artifactId>
  28. </exclusion>
  29. <exclusion>
  30. <groupId>org.apache.cassandra</groupId>
  31. <artifactId>cassandra-all</artifactId>
  32. </exclusion>
  33. <exclusion>
  34. <groupId>me.prettyprint</groupId>
  35. <artifactId>hector-core</artifactId>
  36. </exclusion>
  37. </exclusions>
  38. </dependency>
  39. </dependencies>
  40. </project>
复制代码
4). 下载依赖
  1. ~ mvn clean install
复制代码
在eclipse中刷新项目:
mahout-eclipse-package.png

项目的依赖程序,被自动加载的库路径下面。
4. 用Mahout实现协同过滤userCF
Mahout协同过滤UserCF深度算法剖析,请参考文章:用R解析Mahout用户推荐协同过滤算法(UserCF)
实现步骤:
  • 准备数据文件: item.csv
  • Java程序:UserCF.java
  • 运行程序
  • 推荐结果解读
1). 新建数据文件: item.csv
  1. ~ mkdir datafile
  2. ~ vi datafile/item.csv
  3. 1,101,5.0
  4. 1,102,3.0
  5. 1,103,2.5
  6. 2,101,2.0
  7. 2,102,2.5
  8. 2,103,5.0
  9. 2,104,2.0
  10. 3,101,2.5
  11. 3,104,4.0
  12. 3,105,4.5
  13. 3,107,5.0
  14. 4,101,5.0
  15. 4,103,3.0
  16. 4,104,4.5
  17. 4,106,4.0
  18. 5,101,4.0
  19. 5,102,3.0
  20. 5,103,2.0
  21. 5,104,4.0
  22. 5,105,3.5
  23. 5,106,4.0
复制代码
数据解释:每一行有三列,第一列是用户ID,第二列是物品ID,第三列是用户对物品的打分。
2). Java程序:UserCF.java
Mahout协同过滤的数据流,调用过程。
mahout-recommendation-process.png
新建JAVA类:org.conan.mymahout.recommendation.UserCF.java
  1. package org.conan.mymahout.recommendation;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.util.List;
  5. import org.apache.mahout.cf.taste.common.TasteException;
  6. import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
  7. import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
  8. import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
  9. import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
  10. import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
  11. import org.apache.mahout.cf.taste.model.DataModel;
  12. import org.apache.mahout.cf.taste.recommender.RecommendedItem;
  13. import org.apache.mahout.cf.taste.recommender.Recommender;
  14. import org.apache.mahout.cf.taste.similarity.UserSimilarity;
  15. public class UserCF {
  16.     final static int NEIGHBORHOOD_NUM = 2;
  17.     final static int RECOMMENDER_NUM = 3;
  18.     public static void main(String[] args) throws IOException, TasteException {
  19.         String file = "datafile/item.csv";
  20.         DataModel model = new FileDataModel(new File(file));
  21.         UserSimilarity user = new EuclideanDistanceSimilarity(model);
  22.         NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, user, model);
  23.         Recommender r = new GenericUserBasedRecommender(model, neighbor, user);
  24.         LongPrimitiveIterator iter = model.getUserIDs();
  25.         while (iter.hasNext()) {
  26.             long uid = iter.nextLong();
  27.             List list = r.recommend(uid, RECOMMENDER_NUM);
  28.             System.out.printf("uid:%s", uid);
  29.             for (RecommendedItem ritem : list) {
  30.                 System.out.printf("(%s,%f)", ritem.getItemID(), ritem.getValue());
  31.             }
  32.             System.out.println();
  33.         }
  34.     }
  35. }
复制代码
3). 运行程序
控制台输出:
  1. SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
  2. SLF4J: Defaulting to no-operation (NOP) logger implementation
  3. SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
  4. uid:1(104,4.274336)(106,4.000000)
  5. uid:2(105,4.055916)
  6. uid:3(103,3.360987)(102,2.773169)
  7. uid:4(102,3.000000)
  8. uid:5
复制代码
4). 推荐结果解读
向用户ID1,推荐前二个最相关的物品, 104和106
向用户ID2,推荐前二个最相关的物品, 但只有一个105
向用户ID3,推荐前二个最相关的物品, 103和102
向用户ID4,推荐前二个最相关的物品, 但只有一个102
向用户ID5,推荐前二个最相关的物品, 没有符合的
5. 用Mahout实现kmeans
  • 准备数据文件: randomData.csv
  • Java程序:Kmeans.java
  • 运行Java程序
  • mahout结果解读
  • 用R语言实现Kmeans算法
  • 比较Mahout和R的结果
1). 准备数据文件: randomData.csv
  1. ~ vi datafile/randomData.csv
  2. -0.883033363823402,-3.31967192630249
  3. -2.39312626419456,3.34726861118871
  4. 2.66976353341256,1.85144276077058
  5. -1.09922906899594,-6.06261735207489
  6. -4.36361936997216,1.90509905380532
  7. -0.00351835125495037,-0.610105996559153
  8. -2.9962958796338,-3.60959839525735
  9. -3.27529418132066,0.0230099799641799
  10. 2.17665594420569,6.77290756817957
  11. -2.47862038335637,2.53431833167278
  12. 5.53654901906814,2.65089785582474
  13. 5.66257474538338,6.86783609641077
  14. -0.558946883114376,1.22332819416237
  15. 5.11728525486132,3.74663871584768
  16. 1.91240516693351,2.95874731384062
  17. -2.49747101306535,2.05006504756875
  18. 3.98781883213459,1.00780938946366
复制代码
这里只截取了一部分,更多的数据请查看源代码。
注:我是通过R语言生成的randomData.csv
  1. x1<-cbind(x=rnorm(400,1,3),y=rnorm(400,1,3))
  2. x2<-cbind(x=rnorm(300,1,0.5),y=rnorm(300,0,0.5))
  3. x3<-cbind(x=rnorm(300,0,0.1),y=rnorm(300,2,0.2))
  4. x<-rbind(x1,x2,x3)
  5. write.table(x,file="randomData.csv",sep=",",row.names=FALSE,col.names=FALSE)
复制代码
2). Java程序:Kmeans.java
Mahout中kmeans方法的算法实现过程。
mahout-kmeans-process.png
新建JAVA类:org.conan.mymahout.cluster06.Kmeans.java
  1. package org.conan.mymahout.cluster06;
  2. import java.io.IOException;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import org.apache.mahout.clustering.kmeans.Cluster;
  6. import org.apache.mahout.clustering.kmeans.KMeansClusterer;
  7. import org.apache.mahout.common.distance.EuclideanDistanceMeasure;
  8. import org.apache.mahout.math.Vector;
  9. public class Kmeans {
  10.     public static void main(String[] args) throws IOException {
  11.         List sampleData = MathUtil.readFileToVector("datafile/randomData.csv");
  12.         int k = 3;
  13.         double threshold = 0.01;
  14.         List randomPoints = MathUtil.chooseRandomPoints(sampleData, k);
  15.         for (Vector vector : randomPoints) {
  16.             System.out.println("Init Point center: " + vector);
  17.         }
  18.         List clusters = new ArrayList();
  19.         for (int i = 0; i < k; i++) {
  20.             clusters.add(new Cluster(randomPoints.get(i), i, new EuclideanDistanceMeasure()));
  21.         }
  22.         List<List> finalClusters = KMeansClusterer.clusterPoints(sampleData, clusters, new EuclideanDistanceMeasure(), k, threshold);
  23.         for (Cluster cluster : finalClusters.get(finalClusters.size() - 1)) {
  24.             System.out.println("Cluster id: " + cluster.getId() + " center: " + cluster.getCenter().asFormatString());
  25.         }
  26.     }
  27. }
复制代码
3). 运行Java程序
控制台输出:
  1. Init Point center: {0:-0.162693685149196,1:2.19951550286862}
  2. Init Point center: {0:-0.0409782183083317,1:2.09376666042057}
  3. Init Point center: {0:0.158401778474687,1:2.37208412905273}
  4. SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
  5. SLF4J: Defaulting to no-operation (NOP) logger implementation
  6. SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
  7. Cluster id: 0 center: {0:-2.686856800552941,1:1.8939462954763795}
  8. Cluster id: 1 center: {0:0.6334255423230666,1:0.49472852972602105}
  9. Cluster id: 2 center: {0:3.334520309711998,1:3.2758355898247653}
复制代码
4). mahout结果解读
1. Init Point center表示,kmeans算法初始时的设置的3个中心点
2. Cluster center表示,聚类后找到3个中心点
5). 用R语言实现Kmeans算法
接下来为了让结果更直观,我们再用R语言,进行kmeans实验,操作相同的数据。
R语言代码:
  1. > y<-read.csv(file="randomData.csv",sep=",",header=FALSE)
  2. > cl<-kmeans(y,3,iter.max = 10, nstart = 25)
  3. > cl$centers
  4.           V1         V2
  5. 1 -0.4323971  2.2852949
  6. 2  0.9023786 -0.7011153
  7. 3  4.3725463  2.4622609
  8. # 生成聚类中心的图形
  9. > plot(y, col=c("black","blue","green")[cl$cluster])
  10. > points(cl$centers, col="red", pch = 19)
  11. # 画出Mahout聚类的中心
  12. > mahout<-matrix(c(-2.686856800552941,1.8939462954763795,0.6334255423230666,0.49472852972602105,3.334520309711998,3.2758355898247653),ncol=2,byrow=TRUE)
  13. > points(mahout, col="violetred", pch = 19)
复制代码
聚类的效果图:
kmeans-center.png
6). 比较Mahout和R的结果
从上图中,我们看到有 黑,蓝,绿,三种颜色的空心点,这些点就是原始的数据。

3个红色实点,是R语言kmeans后生成的3个中心。
3个紫色实点,是Mahout的kmeans后生成的3个中心。

R语言和Mahout生成的点,并不是重合的,原因有几点:
  • 距离算法不一样:
  •       Mahout中,我们用的 “欧氏距离(EuclideanDistanceMeasure)”
  •       R语言中,默认是”Hartigan and Wong”
  • 初始化的中心是不一样的。
  • 最大迭代次数是不一样的。
  • 点合并时,判断的”阈值(threshold)”是不一样的。














已有(2)人评论

跳转到指定楼层
QQ_889150 发表于 2017-2-7 16:36:35
写得不错bucu
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条