聚类属于无监督学习,就是对大量未标注的数据集就,按数据的内在相似性将数据集划分为多个类别,使类别内的数据相似度较大而类别间的数据相似度较小。
1.K-Means算法实现
算法实现:
- 未聚类的初始点集;
- 随机选取两个点作为聚类中心;
- 计算每个点到聚类中心的距离,并聚类到离该点最近的聚类中去;
- 计算每个聚类中所有点的座标平均值,并将这个平均值作为新的聚类中心;
- 重复(3),计算每个点到聚类中心的距离,并聚类到离该点最近的聚类中去;
- 重复(4),计算每个聚类中所有点的座标平均值,并将这个平均值作为新的聚类中心。
K-Means结束条件:直到类中心不再进行大范围移动或者聚类迭代次数达到要求为止。
2.相似度计算方法
1.欧式距离
2.余弦距离
3.K的初始位置
- 从输入的数据点集合中随机选择一个点作为第一个聚类中心。
- 对于数据集中的每一个点x,计算它与最近聚类中心(指已选择的聚类中心)的聚离D(x)。
- 选择一个新的数据点作为新的聚类中心,选择的原则是:D(x)较大的点,被选取作为聚类中心的概率较大。
- 重复2和3直到k个聚类中心被选出来。
- 利用这k个初始的聚类中心来运行标准的K-Means算法。
4.K-Means的优劣
优点:
1)是解决聚类问题的一种经典算法,简答、快速。
2)是处理大数据集,该算法保持可伸缩性和高效率。
3)当结果簇是密集的,它的效果较好。
缺点:
1)必须事先给出k(要生成的簇的数目),而且对初值敏感,对于不同的初始值,可能会导致不同结果。
2)对噪声和孤立点数据敏感。
5.代码实现
package com.dengdan
import org.apache.spark.mllib.clustering.{KMeans, KMeansModel}
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.{SparkConf, SparkContext}
object KmeansCluster extends App {
val sc = new SparkContext(new SparkConf().setMaster("local[4]").setAppName("K-Means"))
//加载数据
val path = "D:\\idea_workspace2020\\spark\\sparkMLib\\kmeans\\src\\main\\resources\\data.txt"
val data = sc.textFile(path)
val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble))).cache()
//通过KMeans将数据分成两个阵营
val numClusters = 2
val numIterations = 20
val clusters = KMeans.train(parsedData, numClusters, numIterations)
//输出当前的聚类中心
clusters.clusterCenters.foreach(println _)
//进行预测
val index = clusters.predict(Vectors.dense(Array(8.9, 7.2, 9.0)))
println(s"Vector[8.9, 7.2, 9.0]属于聚类索引为${index} 中心座标为:${clusters.clusterCenters(index)}")
//计算误差平方和
val WSSSE = clusters.computeCost(parsedData)
println(s"误差平方和= ${WSSSE}")
//模型存储位置
var modelPath = "target/tmp/KMeansModel"
//保存模型
clusters.save(sc, modelPath)
//加载模型
val sameModel = KMeansModel.load(sc, modelPath)
sc.stop()
}