[转载] Mahout
转载自http://hadoop.readthedocs.org/en/latest/Hadoop-Mahout.html#
Mahout
12.1 简介
可以使开发人员更为快捷的创建智能应用程序。
12.2 安装
12.2.1 要求
12.2.2 配置
tar -zxvf mahout-distribution-0.7.tar.gz -C /usr/local/cloud/src/
cd /usr/local/cloud/
ln -s -f /usr/local/cloud/src/mahout-distribution-0.7 mahout
12.3 测试
12.3.1 获取测试数据
wget http://archive.ics.uci.edu/ml/databases/synthetic_control/synthetic_control.data
12.3.2 上传到Hadoop集群
hadoop fs -mkdir testdata
hadoop fs -put synthetic_control.data testdata
12.3.3 测试各种算法
cd /usr/local/cloud/mahout/
# canopy
hadoop jar mahout-examples-0.7-job.jar org.apache.mahout.clustering.syntheticcontrol.canopy.Job
# kmeans
hadoop jar mahout-examples-0.7-job.jar org.apache.mahout.clustering.syntheticcontrol.kmeans.Job
12.4 推荐
12.4.1 协同过滤
- Taste简介
-
Taste 是 Apache Mahout
提供的一个协同过滤算法的高效实现,它是一个基于 Java 实现的可扩展的,高效的推荐引擎。Taste 既实现了最基本的基于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法。同时,Taste 不仅仅只适用于 Java 应用程序,它可以作为内部服务器的一个组件以 HTTP 和 Web Service 的形式向外界提供推荐的逻辑。Taste 的设计使它能满足企业对推荐引擎在性能、灵活性和可扩展性等方面的要求。
Taste原理
- 系统架构
-
接口设计
- DataModel
-
DataModel
是用户喜好信息的抽象接口,它的具体实现可能来自任意类型的数据源以抽取用户喜好信息。Taste提供了MySQLDataModel,方便用户通过JDBC和MySQL访问数据, 此外还通过FileDataModel提供了对文件数据源的支持。
- UserSimilarity 和 ItemSimilarity
-
UserSimilarity
用于定义两个用户间的相似度,它是基于协同过滤的推荐引擎的核心部分,可以用来计算用户的“邻居”,这里我们将与当前用户口味相似的用户称为他的邻居。ItemSimilarity 类似的,定义内容之间的相似度。
UserNeighborhood
用于基于用户相似度的推荐方法中,推荐的内容是基于找到与当前用户喜好相似的“邻居用户”的方式产生的。UserNeighborhood 定义了确定邻居用户的方法,具体实现一般是基于 UserSimilarity 计算得到的。
- Recommender
-
Recommender 是推荐引擎的抽象接口,Taste
中的核心组件。程序中,为它提供一个DataModel,它可以计算出对不同用户的推荐内容。实际应用中,主要使用它的实现类 GenericUserBasedRecommender 或者 GenericItemBasedRecommender,分别实现基于用户相似度的推荐引擎或者基于内容的推荐引擎。
Taste演示
- 拷贝到指定目录
cp ml-1m.zip /usr/local/cloud/mahout/
cd /usr/local/cloud/mahout/
unzip ml-1m.zip
# 电影信息文件 格式为MovieID::MovieName::MovieTags
cp movies.dat integration/src/main/resources/org/apache/mahout/cf/taste/example/grouplens/
# 打分信息文件 格式为UserID::MovieID::Rating::Timestamp
cp ratings.dat integration/src/main/resources/org/apache/mahout/cf/taste/example/grouplens/
mvn install -DskipTests - 修改pom文件添加对mahout-examples的依赖
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mahout-examples</artifactId>
<version>0.7</version>
</dependency> - 使用jetty进行测试
cd integration
mvn jetty:run访问如下地址查看效果http://hadooptest:8080/mahout-integration/RecommenderServlet?userID=1
- 命令行方式测试
mvn -q exec:java -Dexec.mainClass="org.apache.mahout.cf.taste.example.grouplens.GroupLensRecommenderEvaluatorRunner" -Dexec.args="-i /home/hadoop/cloud/ml-1m/ratings.dat"
- Taste示例
// 1. 选择数据源
// 数据源格式为UserID,MovieID,Ratings
// 使用文件型数据接口
DataModel model = new FileDataModel(new File("/Users/matrix/Documents/plan/test/ratings.txt")); // 2. 实现相似度算法
// 使用PearsonCorrelationSimilarity实现UserSimilarity接口, 计算用户的相似度
// 其中PearsonCorrelationSimilarity是基于皮尔逊相关系数计算相似度的实现类
// 其它的还包括
// EuclideanDistanceSimilarity:基于欧几里德距离计算相似度
// TanimotoCoefficientSimilarity:基于 Tanimoto 系数计算相似度
// UncerteredCosineSimilarity:计算 Cosine 相似度
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
// 可选项
similarity.setPreferenceInferrer(new AveragingPreferenceInferrer(model)); // 3. 选择邻居用户
// 使用NearestNUserNeighborhood实现UserNeighborhood接口, 选择最相似的三个用户
// 选择邻居用户可以基于'对每个用户取固定数量N个最近邻居'和'对每个用户基于一定的限制,取落在相似度限制以内的所有用户为邻居'
// 其中NearestNUserNeighborhood即基于固定数量求最近邻居的实现类
// 基于相似度限制的实现是ThresholdUserNeighborhood
UserNeighborhood neighborhood = new NearestNUserNeighborhood(3, similarity, model); // 4. 实现推荐引擎
// 使用GenericUserBasedRecommender实现Recommender接口, 基于用户相似度进行推荐
Recommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
Recommender cachingRecommender = new CachingRecommender(recommender);
List<RecommendedItem> recommendations = cachingRecommender.recommend(1234, 10); // 输出推荐结果
for (RecommendedItem item : recommendations) {
System.out.println(item.getItemID() + "\t" + item.getValue());
}
12.4.2 聚类分析
框架设计
针对分组需求,Mahout的聚类算法将对象表示成一种简单的数据模型:向量,然后通过计算各向量间的相似度进行分组。
- 数据模型
-
在Mahout中向量(Vector)有多种实现.
- DenseVector
-
它的实现就是一个浮点数数组, 对向量里所有维度进行存储,
适合用于存储密集向量。
- RandomAccessSparseVector
-
基于浮点数的HashMap实现, key是整数类型, value是浮点数类型,
只存储向量中不为空的值, 并提供随机访问。
- SequentialAccessVector
-
实现为整数类型和浮点数类型的并行数组, 同样只存储不为空的值,
但只提供顺序访问
- 数据建模
-
Mahout为实现将数据建模成向量, 提供了对数据进行向量化的各种方法。
- 简单的整数类型或浮点型数据这种数据因为本身就被描述成一个向量, 因此可以直接存为向量。
// 创建一个二维点集的向量组
public static final double[][] points = { { 1, 1 }, { 2, 1 }, { 1, 2 },
{ 2, 2 }, { 3, 3 }, { 8, 8 }, { 9, 8 }, { 8, 9 }, { 9, 9 }, { 5, 5 },
{ 5, 6 }, { 6, 6 }};
public static List<Vector> getPointVectors(double[][] raw) {
List<Vector> points = new ArrayList<Vector>();
for (int i = 0; i < raw.length; i++) {
double[] fr = raw[i];
// 这里选择创建 RandomAccessSparseVector
Vector vec = new RandomAccessSparseVector(fr.length);
// 将数据存放在创建的 Vector 中
vec.assign(fr);
points.add(vec);
}
return points;
} - 枚举类型数据这类数据是对物体的描述, 只是取值范围有限,
比如苹果的颜色数据包括: 红色、黄色和绿色, 则在数据建模时可以用数字表示颜色。 | 红色=1, 黄色=2, 绿色=3
// 创建苹果信息数据的向量组
public static List<Vector> generateAppleData() {
List<Vector> apples = new ArrayList<Vector>();
// 这里创建的是 NamedVector,其实就是在上面几种 Vector 的基础上,
// 为每个 Vector 提供一个可读的名字
NamedVector apple = new NamedVector(new DenseVector(new double[] {0.11, 510, 1}), "Small round green apple");
apples.add(apple); apple = new NamedVector(new DenseVector(new double[] {0.2, 650, 3}), "Large oval red apple");
apples.add(apple); apple = new NamedVector(new DenseVector(new double[] {0.09, 630, 1}), "Small elongated red apple");
apples.add(apple); apple = new NamedVector(new DenseVector(new double[] {0.18, 520, 2}), "Medium oval green apple");
apples.add(apple); return apples;
} - 文本信息
-
在信息检索领域中最常用的是向量空间模型,
文本的向量空间模型就是将文本信息建模成一个向量, 其中每个维度是文本中出现的一个词的权重。
常用算法
K均值聚类算法
- 原理
-
给定一个N个对象的数据集, 构建数据的K个划分,
每个划分就是一个聚类, K<=N, 需要满足两个要求:1.每个划分至少包含一个对象; 2. 每个对象必须属于且仅属于一个组。
- 过程
-
首先创建一个初始划分, 随机的选择K个对象,
每个对象初始的代表了一个划分的中心, 对于其它的对象, 根据其与各个划分的中心的距离, 把它们分给最近的划分。
然后使用迭代进行重定位,
尝试通过对象在划分间移动以改进划分。所谓重定位, 就是当有新的对象被分配到了某个划分或者有对象离开了某个划分时, 重新计算这个划分的中心。这个过程不断重复, 直到各个划分中的对象不再变化。
- 优缺点
-
当划分结果比较密集, 且划分之间的区别比较明显时,
- K均值的效果比较好。K均值算法复杂度为O(NKt), 其中t为迭代次数。
-
但其要求用户必须事先给出K值,
而K值的选择一般都基于一些经验值或多次实验的结果。而且, K均值对孤立点数据比较敏感, 少量这类的数据就能对评价值造成极大的影响。
示例
- 基于内存的单机应用(0.5版)
/**
* 基于内存的K均值聚类算法实现
*/
public static void kMeansClusterInMemoryKMeans(){
// 指定需要聚类的个数
int k = 2; // 指定K均值聚类算法的最大迭代次数
int maxIter = 3; // 指定K均值聚类算法的最大距离阈值
double distanceThreshold = 0.01; // 声明一个计算距离的方法,这里选择了欧几里德距离
DistanceMeasure measure = new EuclideanDistanceMeasure(); // 构建向量集,使用的是二维点集
List<Vector> pointVectors = getPointVectors(points); // 从点集向量中随机的选择k个向量作为初始分组的中心
List<Vector> randomPoints = chooseRandomPoints(pointVectors, k); // 基于前面选中的中心构建分组
List<Cluster> clusters = new ArrayList<Cluster>();
int clusterId = 0;
for(Vector v : randomPoints){
clusters.add(new Cluster(v, clusterId ++, measure));
}
// 调用 KMeansClusterer.clusterPoints 方法执行K均值聚类
List<List<Cluster>> finalClusters = KMeansClusterer.clusterPoints(pointVectors, clusters, measure, maxIter, distanceThreshold); // 打印最终的聚类结果
for(Cluster cluster : finalClusters.get(finalClusters.size() -1)) {
System.out.println("Cluster id: " + cluster.getId() + " center: " + cluster.getCenter().asFormatString());
System.out.println("\tPoints: " + cluster.getNumPoints());
}
}
- 基于Hadoop的集群应用(0.5版)注意:首先需要在MVN工程中添加如下依赖
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-core</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout-core</artifactId>
<version>0.5</version>
</dependency>
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout-utils</artifactId>
<version>0.5</version>
</dependency>
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout-math</artifactId>
<version>0.5</version>
</dependency>其次在集群上运行前需要进行相关配置# 需要在$HADOOP_HOME/conf/hadoop-env.sh中设置CLASSPATH
export MAHOUT_HOME=/usr/local/cloud/mahout
for f in $MAHOUT_HOME/lib/*.jar; do
HADOOP_CLASSPATH=${HADOOP_CLASSPATH}:$f;
done
for f in $MAHOUT_HOME/*.jar; do
HADOOP_CLASSPATH=$(HADOOP_CLASSPATH):$f;
done然后即可测试如下代码/**
* 基于 Hadoop 的K均值聚类算法实现
* @throws Exception
*/
public static void kMeansClusterUsingMapReduce () throws Exception{
Configuration conf = new Configuration(); // 声明一个计算距离的方法,这里选择了欧几里德距离
DistanceMeasure measure = new EuclideanDistanceMeasure(); // 指定输入路径,基于 Hadoop 的实现是通过指定输入输出的文件路径来指定数据源的。
Path testpoints = new Path("testpoints");
Path output = new Path("output"); // 清空输入输出路径下的数据
HadoopUtil.delete(conf, testpoints);
HadoopUtil.delete(conf, output); RandomUtils.useTestSeed(); // 在输入路径下生成点集,与内存的方法不同,这里需要把所有的向量写进文件
writePointsToFile(testpoints); // 指定需要聚类的个数,这里选择 2 类
int k = 2; // 指定 K 均值聚类算法的最大迭代次数
int maxIter = 3; // 指定 K 均值聚类算法的最大距离阈值
double distanceThreshold = 0.01; // 随机的选择k个作为簇的中心
Path clusters = RandomSeedGenerator.buildRandom(conf, testpoints, new Path(output, "clusters-0"), k, measure); // 调用 KMeansDriver.runJob 方法执行 K 均值聚类算法
KMeansDriver.run(testpoints, clusters, output, measure, distanceThreshold, maxIter, true, true); // 调用 ClusterDumper 的 printClusters 方法将聚类结果打印出来。
ClusterDumper clusterDumper = new ClusterDumper(new Path(output, "clusters-" + (maxIter - 1)), new Path(output, "clusteredPoints"));
clusterDumper.printClusters(null);
} - 基于Hadoop的集群应用(0.7版)
public static void kMeansClusterUsingMapReduce() throws IOException, InterruptedException,
ClassNotFoundException {
Configuration conf = new Configuration(); // 声明一个计算距离的方法,这里选择了欧几里德距离
DistanceMeasure measure = new EuclideanDistanceMeasure();
File testData = new File("input");
if (!testData.exists()) {
testData.mkdir();
} // 指定输入路径,基于 Hadoop 的实现是通过指定输入输出的文件路径来指定数据源的。
Path samples = new Path("input/file1"); // 在输入路径下生成点集,这里需要把所有的向量写进文件
List<Vector> sampleData = new ArrayList<Vector>(); RandomPointsUtil.generateSamples(sampleData, 400, 1, 1, 3);
RandomPointsUtil.generateSamples(sampleData, 300, 1, 0, 0.5);
RandomPointsUtil.generateSamples(sampleData, 300, 0, 2, 0.1);
ClusterHelper.writePointsToFile(sampleData, conf, samples); // 指定输出路径
Path output = new Path("output");
HadoopUtil.delete(conf, output); // 指定需要聚类的个数,这里选择3
int k = 3; // 指定 K 均值聚类算法的最大迭代次数
int maxIter = 10; // 指定 K 均值聚类算法的最大距离阈值
double distanceThreshold = 0.01; // 随机的选择k个作为簇的中心
Path clustersIn = new Path(output, "random-seeds");
RandomSeedGenerator.buildRandom(conf, samples, clustersIn, k, measure); // 调用 KMeansDriver.run 方法执行 K 均值聚类算法
KMeansDriver.run(samples, clustersIn, output, measure, distanceThreshold, maxIter, true, 0.0, true); // 输出结果
List<List<Cluster>> Clusters = ClusterHelper.readClusters(conf, output);
for (Cluster cluster : Clusters.get(Clusters.size() - 1)) {
System.out.println("Cluster id: " + cluster.getId() + " center: " + cluster.getCenter().asFormatString());
}
}输出结果为:Cluster id: 997 center: {1:3.6810451340150467,0:3.8594229542914538}
Cluster id: 998 center: {1:2.068611196044424,0:-0.5471173292759096}
Cluster id: 999 center: {1:-0.6392433868275759,0:1.2972649625289365}
12.4.3 分类分析
[转载] Mahout的更多相关文章
- Mahout之数据承载
转载自:https://www.douban.com/note/204399134/ 推荐数据的处理是大规模的,在集群环境下一次要处理的数据可能是数GB,所以Mahout针对推荐数据进行了优化. Pr ...
- Mahout推荐算法API详解
转载自:http://blog.fens.me/mahout-recommendation-api/ Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, ...
- 从源代码剖析Mahout推荐引擎
转载自:http://blog.fens.me/mahout-recommend-engine/ Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pi ...
- Mahout推荐算法基础
转载自(http://www.geek521.com/?p=1423) Mahout推荐算法分为以下几大类 GenericUserBasedRecommender 算法: 1.基于用户的相似度 2.相 ...
- 转】从源代码剖析Mahout推荐引擎
原博文出自于: http://blog.fens.me/mahout-recommend-engine/ 感谢! 从源代码剖析Mahout推荐引擎 Hadoop家族系列文章,主要介绍Hadoop家族产 ...
- 转】Mahout分步式程序开发 聚类Kmeans
原博文出自于: http://blog.fens.me/hadoop-mahout-kmeans/ 感谢! Mahout分步式程序开发 聚类Kmeans Hadoop家族系列文章,主要介绍Hadoop ...
- 转】Mahout分步式程序开发 基于物品的协同过滤ItemCF
原博文出自于: http://blog.fens.me/hadoop-mahout-mapreduce-itemcf/ 感谢! Posted: Oct 14, 2013 Tags: Hadoopite ...
- 转】Mahout推荐算法API详解
原博文出自于: http://blog.fens.me/mahout-recommendation-api/ 感谢! Posted: Oct 21, 2013 Tags: itemCFknnMahou ...
- 转】用Maven构建Mahout项目
原博文出自于: http://blog.fens.me/hadoop-mahout-maven-eclipse/ 感谢! 用Maven构建Mahout项目 Hadoop家族系列文章,主要介绍Hadoo ...
随机推荐
- java 虚拟机与并发处理几个问题简要(二)
六.两个重要的概念性问题: 1.同步:要保持数据的一致性,就需要一种保证并发进程正确执行顺序的机制.这种机制就是 进程同步(Process Synchronization). 竞争资源的多个进程按着特 ...
- wpf 制作必输项的*标记
直接引用帮助文档上的话吧,以免下次忘记! AdornedElementPlaceholder 类 .NET Framework 3.5 其他版本 此主题尚未评级 - 评价此主题 更新:20 ...
- javascript中关于this指向问题详解
前 言 LiuDaP 在前端的学习中,我们必然要用到js,js可以说是前端必不可少的的东西.在学习js的过程中,我们会经常用到this这个东西,而this的指向问题就变得尤为重要.今天正好有空闲 ...
- python 解析xml
在工作中很多时候都要用到xml,使用这个时候难免会设计到解析他,然后就研究了一下python解析xml问题,看了很多东西,python有很多解析xml的包,但是也折腾我好一段时间,最后选择了这个方法. ...
- 简述static关键字、void与void *(void指针)、函数指针
static关键字1.修饰局部变量,延长局部变量的生命周期.使变量成为静态局部变量,在编译时就为变量分配内存,直到程序退出才释放存储单元.2.修饰全局变量,限制全局变量的使用范围为本文件中.全局变量默 ...
- 将JavaScript转化为C#
因为一个需求,不得不将JavaScript转化为C#. 其实有强大的 Node.js. 说说代码, 其实可以使用dynamic 来实现.但是dynamic有很多问题. 直接上代码吧,不是很难,就是很啰 ...
- python数据结构之树和二叉树(先序遍历、中序遍历和后序遍历)
python数据结构之树和二叉树(先序遍历.中序遍历和后序遍历) 树 树是\(n\)(\(n\ge 0\))个结点的有限集.在任意一棵非空树中,有且只有一个根结点. 二叉树是有限个元素的集合,该集合或 ...
- jfinal拦截器配置
实现aop @Before(Tx.class) public void index(){ // renderText("hello world!"); render("/ ...
- Archlinux运行FlashTool
首先,http://www.flashtool.net/index.php下载linux版的FlashTool,并且按照其说明在/etc/udev加入如下字段: SUBSYSTEM== »usb », ...
- LINUX 笔记-命令执行顺序 && ,||
&& 格式:命令1 && 命令2 说明:命令1返回真(即返回0,成功被执行)后,命令2才能够被执行 例:/apps/bin目录将会被移到/apps/dev/bin目录下 ...