K-means过程原理
假设有一批关于计算机科学和数学统计相关的人才,这批人才中计算机人才、机器学习人才、数学人才三类,那么该如何将这批数据进行聚类?
我们可以直观的感觉到应该如下分类:
但问题是计算机不会直观的去观察数据,首先将这批数据向量化,K-means聚类会随机在这些点中找到三个点,然后计算所有的样本到当前三个点的距离大小,判断样本点与当前三个点哪个距离比较近,当前样本就属于那个类。
当经过一次计算之后,就是经过了一次迭代过程,当完成一次迭代后,就分出来是三个类别(簇),每个类别中都有质心。然后进行下一次迭代,继续计算所有点到三个类别中心点的距离,按照每个样本点与哪个质心距离最近就属于哪个簇,以此类推,继续迭代。当本次计算的中心点的距离较上次计算的中心点的位置不再变化,那么停止迭代。
下面是代码实现
import scala.tools.scalap.Main
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
import org.apache.spark.mllib.clustering.KMeansModel
import org.apache.spark.mllib.clustering.KMeans
import org.apache.spark.mllib.linalg.Vectors
/**
* 通过数据集使用kmeans训练模型
*/
object KMeansScala {
def main(args: Array[String]): Unit = {
//1 构建Spark对象
val conf = new SparkConf().setAppName("KMeans").setMaster("local")
val sc = new SparkContext(conf)
// 读取样本数据1,格式为LIBSVM format
val data = sc.textFile("kmeans_data.txt")
val parsedData = data.map(s => Vectors.dense(s.split(' ').map(_.toDouble))).cache()
val numClusters = 4
val numIterations = 100
val model = new KMeans().
//设置聚类的类数
setK(numClusters).
//设置找中心点最大的迭代次数
setMaxIterations(numIterations).
run(parsedData)
//四个中心点的坐标
val centers = model.clusterCenters
val k = model.k
centers.foreach(println)
println(k)
//保存模型
model.save(sc, "./Kmeans_model")
//加载模型
val sameModel = KMeansModel.load(sc, "./Kmeans_model")
//得出(1,1,1)是属于哪个类别
println(sameModel.predict(Vectors.dense(1,1,1)))
//SparkSQL读取显示4个中心点坐标
val sqlContext = new SQLContext(sc)
sqlContext.read.parquet("./Kmeans_model/data").show()
}
}
源数据
(1,1,1)经计算属于2分类