K-Means
1.1.1 算法说明
聚类其核心任务是:将一组目标object划分为若干个簇,每个簇之间的object尽可能相似,簇与簇之间的object尽可能相异。聚类算法是机器学习)中重要的一部分,最为简单的K-Means聚类算法.
所谓聚类问题,就是给定一个元素集合D,其中每个元素具有n个可观察属性,使用某种算法将D划分成k个子集,要求每个子集内部的元素之间相异度尽可能低,而不同子集的元素相异度尽可能高。其中每个子集叫做一个簇。
1.1.2 实例
K-Means属于基于平方误差的迭代重分配聚类算法,其核心思想十分简单:
随机选择K个中心点;
计算所有点到这K个中心点的距离,选择距离最近的中心点为其所在的簇;
简单地采用算术平均数(mean)来重新计算K个簇的中心;
重复步骤2和3,直至簇类不再发生变化或者达到最大迭代值;
输出结果。
K-Means算法的结果好坏依赖于对初始聚类中心的选择,容易陷入局部最优解,对K值的选择没有准则可依循,对异常数据较为敏感,只能处理数值属性的数据,聚类结构可能不平衡。
本实例中进行如下步骤:
1.装载数据,数据以文本文件方式进行存放;
2.将数据集聚类,设置2个类和20次迭代,进行模型训练形成数据模型;
3.打印数据模型的中心点;
4.使用误差平方之和来评估数据模型;
5.使用模型测试单点数据;
6.交叉评估1,返回结果;交叉评估2,返回数据集和结果。
1.1.3测试数据
该实例使用的数据为kmeans_data.txt。在该文件中提供了6个点的空间位置坐标,使用K-means聚类对这些点进行分类。
使用的kmeans_data.txt的数据如下所示:
0.0 0.0 0.0
0.1 0.1 0.1 0.2 0.2 0.2 9.0 9.0 9.0 9.1 9.1 9.1 9.2 9.2 9.2
1.1.4程序代码
import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.mllib.clustering.KMeans
import org.apache.spark.mllib.linalg.Vectors
object Kmeans {
def main(args: Array[String]) {
// 屏蔽不必要的日志显示在终端上
Logger.getLogger(\"org.apache.spark\").setLevel(Level.WARN)
Logger.getLogger(\"org.eclipse.jetty.server\").setLevel(Level.OFF)
// 设置运行环境
val conf = new SparkConf().setAppName(\"Kmeans\").setMaster(\"local[4]\")
val sc = new SparkContext(conf)
// 装载数据集
val data = sc.textFile(\"/home/hadoop/upload/class8/kmeans_data.txt\
val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble)))
// 将数据集聚类,2个类,20次迭代,进行模型训练形成数据模型
val numClusters = 2
val numIterations = 20
val model = KMeans.train(parsedData, numClusters, numIterations)
// 打印数据模型的中心点
println(\"Cluster centers:\")
for (c <- model.clusterCenters) {
println(\" \" + c.toString)
}
// 使用误差平方之和来评估数据模型
val cost = model.computeCost(parsedData)
println(\"Within Set Sum of Squared Errors = \" + cost)
// 使用模型测试单点数据
println(\"Vectors 0.2 0.2 0.2 is belongs to clusters:\" +
model.predict(Vectors.dense(\"0.2 0.2 0.2\".split(' ').map(_.toDouble))))
println(\"Vectors 0.25 0.25 0.25 is belongs to clusters:\" +
model.predict(Vectors.dense(\"0.25 0.25 0.25\".split(' ').map(_.toDouble))))
println(\"Vectors 8 8 8 is belongs to clusters:\" + model.predict(Vectors.dense(\"8 8 8\".split(' ').map(_.toDouble))))
// 交叉评估1,只返回结果
val testdata = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble)))
val result1 = model.predict(testdata)
result1.saveAsTextFile(\"/home/hadoop/upload/class8/result_kmeans1\")
// 交叉评估2,返回数据集和结果
val result2 = data.map {
line =>
val linevectore = Vectors.dense(line.split(' ').map(_.toDouble))
val prediction = model.predict(linevectore)
line + \" \" + prediction
}.saveAsTextFile(\"/home/hadoop/upload/class8/result_kmeans2\")
sc.stop()
}
}
1.1.5 IDEA执
行情况
第一步 使用如下命令启动Spark集群
$cd /app/hadoop/spark-1.1.0
$sbin/start-all.sh
第二步 在IDEA中设置运行环境
在IDEA运行配置中设置Kmeans运行配置,由于读入的数据已经在程序中指定,故在该设置界面中不需要设置输入参数
第三步 执行并观察输出
在运行日志窗口中可以看到,通过计算计算出模型并找出两个簇中心点:(9.1,9.1,9.1)和(0.1,0.1,0.1),使用模型对测试点进行分类求出分属于族簇。
第四步 查看输出结果文件
目录中有两个输出目录:
查看结果1,在该目录中只输出了结果,分别列出了6个点所属不同的族簇
查看结果2,在该目录中输出了数据集和结果
因篇幅问题不能全部显示,请点此查看更多更全内容