Spark 机器学习-实例演示- K-Means《二》

来源:互联网 发布:哇嘎无法连接网络 编辑:程序博客网 时间:2024/05/22 00:51


1.K-Means简介

K-Means 是聚类的一个算法,是一个无监督学习,目标是将一部分实体根据某种意义上的相似度 和另一部分实体聚在一起。聚类通常被用于探索性的分析。 
K-Means将n个观察实例分类到k个聚类中,以使得每个观察实例 距离它所在的聚类的中心点比其他的聚类中心点的距离更近。所 
以它是一种基于距离的迭代式算法。

 算法:
1 选择 K 个点作为初始中心 
2 将每个点指派到最近的中心 , 形成 K 个簇 ( 聚类 ) 
3 重新计算每个簇的中心 
4 重复 2 - 3 直至中心不发生变化 
即:
① 在所有点(向量)中随机抽取出k个点(向量),作为初始聚类中心点,然后遍历其余的点(向量),找到距离各自最近的聚类中心点, 
将其加到该聚类中。
②求出每个聚类的中心点作为新的聚类中心,然后再遍历所有的 观测点,找到距离其最近的中心点,加到该聚类中。重复运行
此步骤。
③当新产生的中心点与前一个中心点一致或者变化不大时,认为 迭代结束。

距离
– 绝对值距离
– 欧氏距离
– 闵可夫斯基距离
– 切比雪夫距离
– 马氏距离


迭代结束条件有很多种,比如:



MLlib K-Means 的实现中包含一个 k-means ++ 方法的并行化变体 kmeans || 。
MLlib 里面的实现有如下的参数:
k 是所需的类簇的个数。
maxI terations 是最大的迭代次数。
initiali z ationMode 这个参数决定了是用随机初始化还是通过 k-means || 进行初始化。
runs 是跑 k-means 算法的次数( k-mean 算法不能保证能找出最优解,如果在给定的数据集上运行多次,算法将会返回最佳的结果)。
initiali z iationSteps 决定了 k-means || 算法的步数。
epsilon 决定了判断 k-means 是否收敛的距离阀值。

2.数据格式



3.示例程序
import org.apache.log4j.{Level, Logger}import org.apache.spark.{SparkConf, SparkContext}import org.apache.spark.mllib.clustering.KMeansimport org.apache.spark.mllib.linalg.Vectorsobject 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/mmicky/IdeaProjects/machine-learning/kmeans_data.txt", 1)    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/mmicky/IdeaProjects/machine-learning/result1")    //交叉评估2,返回数据集和结果    val result2 = data.map {      line =>        val linevectore = Vectors.dense(line.split(' ').map(_.toDouble))        val prediction = model.predict(linevectore)        line + " " + prediction    }.saveAsTextFile("/home/mmicky/IdeaProjects/machine-learning/result2")    sc.stop()  }}

4.运行结果








5.R语言展示




6.用Scala实现K-Means算法

package cn.chinahadoop.ml/** * Created by chenchao on 14-3-24. */import java.util.Randomimport org.apache.spark.util.Vectorimport org.apache.spark.SparkContext._import scala.collection.mutable.HashMapimport scala.collection.mutable.HashSetimport org.apache.spark.util.Vector/** * K-means clustering. * 此例子会生成1000个向量,每个向量包含十个数字,任务是要选定十个向量作为质心 */object KMeans {  val N = 1000  val R = 1000 // Scaling factor  val D = 10  val K = 10  val convergeDist = 0.001  val rand = new Random(42)  def generateData = {    def generatePoint(i: Int) = {      Vector(D, _ => rand.nextDouble * R)    }    Array.tabulate(N)(generatePoint)  }  def closestPoint(p: Vector, centers: HashMap[Int, Vector]): Int = {    var index = 0    var bestIndex = 0    var closest = Double.PositiveInfinity    for (i <- 1 to centers.size) {      val vCurr = centers.get(i).get      val tempDist = p.squaredDist(vCurr)      if (tempDist < closest) {        closest = tempDist        bestIndex = i      }    }    bestIndex  }  def main(args: Array[String]) {    val data = generateData //初始化数据点,以向量形式存在,包含1000个向量,每个向量包含十个数字点    var points = new HashSet[Vector] //随机选取的十组向量作为质心    var kPoints = new HashMap[Int, Vector] //初始质心,共有十个 即每个质心对应着一个向量, 即这里的质心    var tempDist = 1.0    while (points.size < K) {      points.add(data(rand.nextInt(N)))    }    val iter = points.iterator    for (i <- 1 to points.size) {      kPoints.put(i, iter.next())    }    println("Initial centers: " + kPoints)    while(tempDist > convergeDist) {      //查找与每个向量距离最近的质心      var closest = data.map (p => (closestPoint(p, kPoints), (p, 1)))      //把那些具有相同质心的向量聚合在一起      var mappings = closest.groupBy[Int] (x => x._1)      //把具有相同质心的向量标量相加      var pointStats = mappings.map(pair => pair._2.reduceLeft [(Int, (Vector, Int))] {case ((id1, (x1, y1)), (id2, (x2, y2))) => (id1, (x1 + x2, y1+y2))})      //找出十个新的质心      var newPoints = pointStats.map {mapping => (mapping._1, mapping._2._1/mapping._2._2)}      //迭代收敛条件,即质心变化不大      tempDist = 0.0      for (mapping <- newPoints) {        tempDist += kPoints.get(mapping._1).get.squaredDist(mapping._2)      }      //将新质心放入kPoints      for (newP <- newPoints) {        kPoints.put(newP._1, newP._2)      }    }    println("Final centers: " + kPoints)  }}

运行结果:


1 0
原创粉丝点击