大数据进阶必修课!Spark实战KMeans聚类算法

7.SparkMLlib KMeans聚类算法

7.1 KMeans聚类算法

KMeans聚类算法属于划分类型的聚类方法,其求解过程是迭代计算,基本思想是在开始时随机选择K个簇的中心,依据最近邻规则,把待分类样本点分给每个簇。按照平均计算的方法再计算每个簇的质心,对簇心的位置进行更新,开始新一轮的迭代,直到结果收敛于簇心的移动距离小于事先给定的阈值。
其算法的过程如下所示:
(1)根据给定的k值,选取k个样本点作为初始划分中心;
(2)计算所有样本点到每一个划分中心的距离,并将所有样本点划分到距离最近的划分中心;
(3)计算每个划分中样本点的平均值,将其作为新的中心;
循环进行2~3步直至达到最大迭代次数,或划分中心的变化小于某一预定阈值即聚类的中心不再进行大范围的移动。

7.2 算法源码分析

MLlib中对KMeans聚类算法的实现主要包括以下几个部分:
(1)KMeans聚类伴生对象
KMeans聚类伴生对象object KMeans是建立聚类模型的入口,定义了训练模型的train方法,该方法的参数及其意义如下:
*data——以RDD(Vector)形式输入的训练数据;
*k——创建的聚类簇的个数;
* maxIterations——允许迭代的最大次数;
*initializationMode——初始化聚类中心点的算法,可以选择随机或k-means++
*seed——聚类初始化的随机种子,默认是基于系统时间生成种子。
KMeans聚类类是classs KMeans,run方法根据初始化的参数训练模型。
(2)在上述的run方法中,MLlib使用runAlgorithm方法计算中心点,其算法步骤如下:
初始化中心;进行迭代计算各个样本点分别属于哪个中心点,累加中心点的样本值并完成计数;由中心点的样本数据更新中心点;与更新前的数值比较判断是否完成。runs参数表示并行度,在计算中心点时分多组进行计算,最后以最好的一组为聚类中心。
(3)runAlgorithm中MLlib支持k-means++:initKMeansParallel和随机初始化:initRandom,k-means++算法基于的是初始聚类中心之间相互距离尽可能远的思想,而随机初始化就是随机选择样本数据点作为中心点。
(4)MLlib中还提出了一种快速找到样本点与离其最近的聚类中心的方法:findClosest,还有一种快速计算两样本点之间距离的方法fastSquaredDistance。
(5)训练数据输入,得到一个KMeans聚类模型,模型参数为中心点向量,方法为:预测、保存和加载模型。其中预测方法predict支持RDD和向量格式数据的计算。

7.3 应用实战

7.3.1 数据说明

本次实战使用的是UCI数据集中很经典的鸢尾花数据Iris,一共有150条数据,示例如下:

5.4,3.0,4.5,1.5,versicolor

其中四个实数值表示花的四个部位的大小尺寸,最后对应的是对应花所属的亚种类型即标签值,一共有三种。

7.3.2 代码详解

//导入Vectors包和KMeans算法包
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.clustering.{KMeans, KMeansModel}
//添加自己的数据集路径,读取数据文件
val rawData = sc.textFile("/mnt/hgfs/thunder-download/MLlib_rep/data/iris.txt")

此处输出的信息如下:

rawData: org.apache.spark.rdd.RDD[String] = /mnt/hgfs/thunder-download/
MLlib_rep/data/iris.txt MapPartitionsRDD[44] at textFile at <console>:29

可以看到是RDD[String]格式的数据

//把读取的数据转化为训练数据
val trainingData = rawData.map(line => {Vectors.dense(line.split(",").filter(p => p.matches("\\d*(\\.?)\\d*")).map(_.toDouble))}).cache()

此处输出的信息如下:

trainingData: org.apache.spark.rdd.RDD[org.apache.spark.mllib.linalg.Vector] = MapPartitionsRDD[45] at map at <console>:31

训练数据为Vector类型,并且使用了filter方法,使用正则表达式将花的类别标签去掉。

//调用KMeans的run(RDD[Vector])方法训练KMeans模型
//该方法支持重载,这里使用KMeans.train(data, k, maxIterations, runs)的形式,
//传入训练样本和参数。k为聚类数目,默认2;maxIterations为最大迭代次数,
//默认20;runs为运行的次数,默认为1.
val model : KMeansModel = KMeans.train(trainingData, 3, 100, 5)

这一步就是RDD操作的action型操作,模型创建成功

//使用KMeansModel类的clusterCenters属性得到模型中聚类的中心
model.clusterCenters.foreach(
     | center => {
     | Display all 664 possibilities? (y or n)
     | println("Clustering Center:"+center)
     | })

输出结果如下:

Clustering Center:[5.901612903225806,2.7483870967741932,4.393548387096774,1.433870967741935]
Clustering Center:[5.005999999999999,3.4180000000000006,1.4640000000000002,0.2439999999999999]
Clustering Center:[6.85,3.0736842105263147,5.742105263157893,2.071052631578947]
//用predict()方法预测每个样本所属聚类
trainingData.collect().foreach(
     | sample => {
     | val predictedCluster = model.predict(sample)
     | println(sample.toString + " belongs to cluster " + predictedCluster)
     | })

输出的结果如下:

[5.1,3.5,1.4,0.2] belongs to cluster 1
[4.9,3.0,1.4,0.2] belongs to cluster 1
[4.7,3.2,1.3,0.2] belongs to cluster 1
[4.6,3.1,1.5,0.2] belongs to cluster 1
[5.0,3.6,1.4,0.2] belongs to cluster 1
…
[7.0,3.2,4.7,1.4] belongs to cluster 0
[6.4,3.2,4.5,1.5] belongs to cluster 0
[6.9,3.1,4.9,1.5] belongs to cluster 2
[5.5,2.3,4.0,1.3] belongs to cluster 0
[6.5,2.8,4.6,1.5] belongs to cluster 0
…
//最后可以计算下WSSSE即集合内误差平方和,此项数据是用来测量聚类的有效//性
val wssse = model.computeCost(trainingData)

输出结果为:
wssse: Double = 78.94084142614622,改变k值可以改变wssse,也就可以对无法明确分类的数据选择最优的分类k值即聚类数。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值